Public IP configurable

Change-Id: I5b5f1a846701326abbdc81295646d431c1ff62bf
diff --git a/local/bigswitch/src/main/java/org/opencord/ce/local/bigswitch/BigSwitchManager.java b/local/bigswitch/src/main/java/org/opencord/ce/local/bigswitch/BigSwitchManager.java
index 6297ab7..ebe2179 100644
--- a/local/bigswitch/src/main/java/org/opencord/ce/local/bigswitch/BigSwitchManager.java
+++ b/local/bigswitch/src/main/java/org/opencord/ce/local/bigswitch/BigSwitchManager.java
@@ -27,6 +27,7 @@
 import org.apache.felix.scr.annotations.Reference;
 import org.apache.felix.scr.annotations.ReferenceCardinality;
 import org.apache.felix.scr.annotations.Service;
+import org.onosproject.cfg.ComponentConfigService;
 import org.onosproject.core.ApplicationId;
 import org.onosproject.core.CoreService;
 import org.onosproject.event.AbstractListenerManager;
@@ -119,7 +120,10 @@
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected NetworkConfigService networkConfigService;
 
-    @Property(name = DOMAIN_ID, value = DEFAULT_DOMAIN_ID, label = "Domain ID where this ONOS is running")
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected ComponentConfigService componentConfigService;
+
+    @Property(name = "domainId", value = DEFAULT_DOMAIN_ID, label = "Domain ID where this ONOS is running")
     private String siteId = DEFAULT_DOMAIN_ID;
 
     private static final String PROP_ENABLED = "enabled";
@@ -165,6 +169,7 @@
     @Activate
     public void activate() {
         appId = coreService.registerApplication(APP_NAME);
+        componentConfigService.registerProperties(getClass());
         configRegistry.registerConfigFactory(configFactory);
         networkConfigService.addListener(configListener);
         //deviceService = opticalView(deviceService);
@@ -193,6 +198,7 @@
         configRegistry.unregisterConfigFactory(configFactory);
         //edgePortService.removeListener(edgeListener);
         deviceService.removeListener(deviceListener);
+        componentConfigService.unregisterProperties(getClass(), false);
         log.info("Stopped");
     }
 
@@ -226,6 +232,7 @@
 
         // TODO: manage new site ID
         siteId = newSiteId;
+        log.info("siteId {}", siteId);
     }
 
     @Override
@@ -258,6 +265,7 @@
 
     @Override
     public DomainId siteId() {
+        log.info("siteId {}", siteId);
         return DomainId.domainId(siteId);
     }
 
diff --git a/local/config-samples/co1-config.json b/local/config-samples/co1-config.json
index 1a1b169..222832d 100644
--- a/local/config-samples/co1-config.json
+++ b/local/config-samples/co1-config.json
@@ -16,9 +16,7 @@
     },
     "org.opencord.ce.local.channel.http" : {
       "global" : {
-        "clusterIps" : [
-          "10.128.14.1"
-        ],
+        "publicIp" : "10.128.14.1",
         "port" : "8181",
         "username" : "sdn",
         "password" : "rocks",
diff --git a/local/config-samples/co1-withEE-config.json b/local/config-samples/co1-withEE-config.json
index 2109145..6c1ef4c 100644
--- a/local/config-samples/co1-withEE-config.json
+++ b/local/config-samples/co1-withEE-config.json
@@ -28,9 +28,7 @@
     },
     "org.opencord.ce.local.channel.http" : {
       "global" : {
-        "clusterIps" : [
-          "10.128.14.1"
-        ],
+        "publicIp" : "10.128.14.1",
         "port" : "8181",
         "username" : "sdn",
         "password" : "rocks",
diff --git a/local/config-samples/co2-config.json b/local/config-samples/co2-config.json
index 4567139..2b6f525 100644
--- a/local/config-samples/co2-config.json
+++ b/local/config-samples/co2-config.json
@@ -16,9 +16,7 @@
     },
     "org.opencord.ce.local.channel.http" : {
       "global" : {
-        "clusterIps" : [
-          "10.128.14.1"
-        ],
+        "publicIp" : "10.128.14.1",
         "port" : "8181",
         "username" : "sdn",
         "password" : "rocks",
diff --git a/local/config-samples/co2-withEE-config.json b/local/config-samples/co2-withEE-config.json
index 8cc3fb9..1140d7c 100644
--- a/local/config-samples/co2-withEE-config.json
+++ b/local/config-samples/co2-withEE-config.json
@@ -28,9 +28,7 @@
     },
     "org.opencord.ce.local.channel.http" : {
       "global" : {
-        "clusterIps" : [
-          "10.128.14.1"
-        ],
+        "publicIp" : "10.128.14.1",
         "port" : "8181",
         "username" : "sdn",
         "password" : "rocks",
diff --git a/local/config-samples/co3-config.json b/local/config-samples/co3-config.json
deleted file mode 100644
index e2bcb4f..0000000
--- a/local/config-samples/co3-config.json
+++ /dev/null
@@ -1,28 +0,0 @@
-{
-  "apps" : {
-    "org.opencord.ce.local.bigswitch" : {
-      "mefPorts" :
-      [
-        {
-          "mefPortType" : "UNI",
-          "connectPoint" : "netconf:10.0.0.30:830/0"
-        },
-        {
-          "mefPortType" : "GENERIC",
-          "connectPoint" : "netconf:10.0.0.30:830/1"
-        }
-      ]
-    },
-    "org.opencord.ce.local.channel.http" : {
-      "global" : {
-        "clusterIps" : [
-          "10.128.14.1"
-        ],
-        "port" : "8181",
-        "username" : "sdn",
-        "password" : "rocks",
-        "topic" : "ecord-domains-topic-one"
-      }
-    }
-  }
-}
diff --git a/local/http-channel/src/main/java/org/opencord/ce/local/channel/client/ConnectionConfig.java b/local/http-channel/src/main/java/org/opencord/ce/local/channel/client/ConnectionConfig.java
index a98365b..851c876 100644
--- a/local/http-channel/src/main/java/org/opencord/ce/local/channel/client/ConnectionConfig.java
+++ b/local/http-channel/src/main/java/org/opencord/ce/local/channel/client/ConnectionConfig.java
@@ -21,7 +21,7 @@
 import org.onosproject.core.ApplicationId;
 import org.onosproject.net.config.Config;
 import org.onosproject.net.domain.DomainId;
-import org.opencord.ce.api.services.channel.EndPoint;
+import org.opencord.ce.api.models.DomainEndPoint;
 
 import java.util.Set;
 
@@ -34,16 +34,14 @@
 public class ConnectionConfig extends Config<ApplicationId> {
 
     private static final String PORT = "port";
-    private static final String DOMAIN_IPS = "clusterIps";
+    private static final String PUBLIC_IP = "publicIp";
     private static final String USERNAME = "username";
     private static final String PASSWD = "password";
     private static final String TOPIC = "topic";
 
-    public EndPoint global() {
+    public DomainEndPoint global() {
         Set<IpAddress> ipAddresses = Sets.newHashSet();
-        object.path(DOMAIN_IPS).forEach(ipAddress -> ipAddresses.add(
-                IpAddress.valueOf(ipAddress.asText())
-        ));
+        IpAddress publicIp = IpAddress.valueOf(object.path(PUBLIC_IP).asText());
         int port = object.path(PORT).asInt();
 
         String username = object.path(USERNAME).asText();
@@ -51,7 +49,7 @@
 
         String topic = object.path(TOPIC).asText();
 
-        return new EndPoint(DomainId.domainId("global"), ipAddresses, port,
+        return new DomainEndPoint(DomainId.domainId("global"), publicIp, port,
                 username, password, topic);
     }
 }
diff --git a/local/http-channel/src/main/java/org/opencord/ce/local/channel/client/DomainMasterIpDiscoveryTask.java b/local/http-channel/src/main/java/org/opencord/ce/local/channel/client/DomainMasterIpDiscoveryTask.java
index e93625a..5a7d9bc 100644
--- a/local/http-channel/src/main/java/org/opencord/ce/local/channel/client/DomainMasterIpDiscoveryTask.java
+++ b/local/http-channel/src/main/java/org/opencord/ce/local/channel/client/DomainMasterIpDiscoveryTask.java
@@ -23,7 +23,7 @@
 import org.jboss.netty.util.TimerTask;
 import org.onlab.packet.IpAddress;
 import org.onlab.util.Timer;
-import org.opencord.ce.api.services.channel.EndPoint;
+import org.opencord.ce.api.models.DomainEndPoint;
 import org.slf4j.Logger;
 
 import javax.ws.rs.client.Client;
@@ -53,13 +53,13 @@
 
     private Timeout timeout;
     private volatile boolean isStopped;
-    private EndPoint endPoint;
+    private DomainEndPoint endPoint;
     private Client client;
     private String localSiteId;
 
     private ObjectMapper mapper;
 
-    public DomainMasterIpDiscoveryTask(EndPoint endPoint, Client client,
+    public DomainMasterIpDiscoveryTask(DomainEndPoint endPoint, Client client,
                                        ObjectMapper mapper, String localSiteId) {
         this.endPoint = endPoint;
         this.client = client;
@@ -98,32 +98,26 @@
         if (isStopped()) {
             return;
         }
-        for (IpAddress ipAddress : endPoint.ipAddresses()) {
-            String url = HTTP + COLON + DOUBLESLASH + ipAddress.toString() + COLON +
+            String url = HTTP + COLON + DOUBLESLASH + endPoint.publicIp() + COLON +
                     endPoint.port() + BASE_URL + "/global" + MASTER + "/" + localSiteId;
             log.info("GET: " + url);
             WebTarget wt = client.target(url);
             Response response = wt.request(MediaType.APPLICATION_JSON)
                     .get();
             log.info("DEBUG response: " + response.toString());
-            if (response.getStatus() != Response.Status.OK.getStatusCode()) {
-
-                continue;
-            }
-            String stringBody = response.readEntity(String.class);
-            try {
-                ObjectNode responseBody = (ObjectNode) mapper.readTree(stringBody);
-                if (responseBody.path(RESULT).asText().equals(OK)) {
-                    IpAddress masterIpAdress =  IpAddress.valueOf(responseBody.path(MASTER_IP).asText());
-                    HttpClientInstance.INSTANCE.setMasterIp(endPoint, masterIpAdress);
-                    this.stop();
-                    return;
+            if (response.getStatus() == Response.Status.OK.getStatusCode()) {
+                String stringBody = response.readEntity(String.class);
+                try {
+                    ObjectNode responseBody = (ObjectNode) mapper.readTree(stringBody);
+                    if (responseBody.path(RESULT).asText().equals(OK)) {
+                        IpAddress masterIpAdress =  IpAddress.valueOf(responseBody.path(MASTER_IP).asText());
+                        this.stop();
+                        return;
+                    }
+                } catch (IOException ex) {
+                    log.info("getLocalMasterIp() IOException, try next endpoint ip");
                 }
-            } catch (IOException ex) {
-                log.info("getLocalMasterIp() IOException, try next endpoint ip");
             }
-        }
-
         if (!isStopped()) {
             timeout = Timer.getTimer().newTimeout(this, 3, SECONDS);
         }
diff --git a/local/http-channel/src/main/java/org/opencord/ce/local/channel/client/HttpClientComponent.java b/local/http-channel/src/main/java/org/opencord/ce/local/channel/client/HttpClientComponent.java
index 99f0d3c..17cfa4e 100644
--- a/local/http-channel/src/main/java/org/opencord/ce/local/channel/client/HttpClientComponent.java
+++ b/local/http-channel/src/main/java/org/opencord/ce/local/channel/client/HttpClientComponent.java
@@ -32,7 +32,7 @@
 import org.onosproject.net.config.NetworkConfigService;
 import org.onosproject.net.config.basics.SubjectFactories;
 import org.onosproject.net.device.PortDescription;
-import org.opencord.ce.api.services.channel.EndPoint;
+import org.opencord.ce.api.models.DomainEndPoint;
 import org.opencord.ce.local.bigswitch.BigSwitchEvent;
 import org.opencord.ce.local.bigswitch.BigSwitchListener;
 import org.opencord.ce.local.bigswitch.BigSwitchService;
@@ -75,7 +75,7 @@
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected BigSwitchService bigSwitchService;
 
-    private EndPoint globalOnos;
+    private static DomainEndPoint globalOnos;
 
     private final ExecutorService eventExecutor =
             Executors.newSingleThreadExecutor();
@@ -107,12 +107,13 @@
     @Deactivate
     public void deactivate() {
         log.info("Stopped");
-
         leadershipService.withdraw(TOPIC_ONE);
         bigSwitchService.removeListener(bigSwitchListener);
         configService.removeListener(configListener);
         configRegistry.unregisterConfigFactory(configFactory);
-        HttpClientInstance.INSTANCE.stopNetworkTasks();
+        if (globalOnos != null) {
+            leadershipService.withdraw(globalOnos.topic());
+        }
     }
 
     private void readConfig() {
@@ -122,6 +123,7 @@
             log.error("Configuration failure");
             return;
         }
+        leadershipService.runForLeadership(globalOnos.topic());
         HttpClientInstance.INSTANCE.setGlobalOnos(globalOnos);
     }
 
@@ -133,14 +135,14 @@
             switch (event.type()) {
                 case DEVICE_CREATED:
                     log.info("DEBUG: DEV_CREATED event");
-                    HttpClientInstance.INSTANCE.notifyBigSwitch();
+                    HttpClientInstance.INSTANCE.notifyBigSwitch(bigSwitchService.siteId());
                 case PORT_ADDED:
                 case PORT_UPDATED:
                 case PORT_REMOVED:
                     // the subject is port last updated / added port
                     // but we are not interested in it now
                     List<PortDescription> ports = event.allPorts();
-                    HttpClientInstance.INSTANCE.notifyBigSwitchPorts(ports);
+                    HttpClientInstance.INSTANCE.notifyBigSwitchPorts(bigSwitchService.siteId(), ports);
                     break;
                 case DEVICE_REMOVED:
                     // TODO
diff --git a/local/http-channel/src/main/java/org/opencord/ce/local/channel/client/HttpClientInstance.java b/local/http-channel/src/main/java/org/opencord/ce/local/channel/client/HttpClientInstance.java
index 0d831d9..d2e1079 100644
--- a/local/http-channel/src/main/java/org/opencord/ce/local/channel/client/HttpClientInstance.java
+++ b/local/http-channel/src/main/java/org/opencord/ce/local/channel/client/HttpClientInstance.java
@@ -19,7 +19,6 @@
 import com.fasterxml.jackson.databind.node.ArrayNode;
 import com.fasterxml.jackson.databind.node.ObjectNode;
 import org.onlab.packet.ChassisId;
-import org.onlab.packet.IpAddress;
 import org.onosproject.cluster.ClusterService;
 import org.onosproject.cluster.LeadershipService;
 import org.onosproject.codec.JsonCodec;
@@ -29,9 +28,10 @@
 import org.onosproject.net.DeviceId;
 import org.onosproject.net.Port;
 import org.onosproject.net.device.PortDescription;
+import org.onosproject.net.domain.DomainId;
 import org.onosproject.net.provider.ProviderId;
 import org.onosproject.rest.AbstractWebResource;
-import org.opencord.ce.api.services.channel.EndPoint;
+import org.opencord.ce.api.models.DomainEndPoint;
 import org.opencord.ce.api.services.channel.RequestCallback;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -72,9 +72,7 @@
 
     private ClusterService clusterService;
     private LeadershipService leadershipService;
-    private EndPoint globalOnos;
-    private IpAddress currentRemoteMasterIp;
-    private DomainMasterIpDiscoveryTask globalMasterIpDiscoveryTask;
+    private DomainEndPoint globalOnos;
 
     private final ExecutorService networkExecutor =
             newSingleThreadExecutor();
@@ -84,25 +82,10 @@
             this.leadershipService = leadershipService;
     }
 
-    protected void setGlobalOnos(EndPoint globalOnos) {
+    protected void setGlobalOnos(DomainEndPoint globalOnos) {
         synchronized (MONITOR) {
             this.globalOnos = globalOnos;
         }
-        // TODO: add leadership listeners to react to changes
-        if (isLeader(globalOnos.topic())) {
-            globalMasterIpDiscoveryTask =
-                    new DomainMasterIpDiscoveryTask(globalOnos, client, codecContext.mapper(),
-                            clusterService.getLocalNode().id().id());
-        }  else {
-            log.info("I am NOT the leader for the communication with the global");
-        }
-    }
-
-    protected void setMasterIp(EndPoint endPoint, IpAddress ipAddress) {
-        synchronized (MONITOR) {
-            currentRemoteMasterIp = ipAddress;
-            MONITOR.notify();
-        }
     }
 
     private boolean isLeader(String topic) {
@@ -128,13 +111,8 @@
         }
     }
 
-    public void stopNetworkTasks() {
-        globalMasterIpDiscoveryTask.stop();
-    }
-
-    public void notifyBigSwitch() {
-        String siteId = clusterService.getLocalNode().id().id();
-        String deviceId = "domain:" + siteId;
+    public void notifyBigSwitch(DomainId siteId) {
+        String deviceId = "domain:" + siteId.id();
         String resource = "/" + siteId + "/" + deviceId;
         ObjectNode body = codecContext.mapper().createObjectNode();
         // body is empty for now
@@ -151,11 +129,10 @@
         }));
     }
 
-    public void notifyBigSwitchPorts(List<PortDescription> ports) {
-        String siteId = clusterService.getLocalNode().id().id();
+    public void notifyBigSwitchPorts(DomainId siteId, List<PortDescription> ports) {
         JsonCodec<Port> portCodec = codecContext.codec(Port.class);
         ArrayNode body = codecContext.mapper().createArrayNode();
-        DeviceId deviceId = DeviceId.deviceId("domain:" + siteId);
+        DeviceId deviceId = DeviceId.deviceId("domain:" + siteId.id());
         ports.forEach(portDescription ->
             body.add(portCodec.encode(new DefaultPort(new DummyDevice(deviceId), portDescription.portNumber(),
                     portDescription.isEnabled(), portDescription.type(),
@@ -191,16 +168,19 @@
         @Override
         public void run() {
             synchronized (MONITOR) {
-                while (globalOnos == null || currentRemoteMasterIp == null) {
+                while (globalOnos == null) {
                     try {
-                        log.info("wait() global-ONOS endpoint");
+                        log.info("wait() global ONOS endpoint");
                         MONITOR.wait();
                     } catch (InterruptedException ie) {
                         log.info("Interrupted exception: " + ie.getMessage());
                     }
                 }
             }
-            String url = HTTP + COLON + DOUBLESLASH + currentRemoteMasterIp + COLON +
+            if (!isLeader(globalOnos.topic())) {
+                return;
+            }
+            String url = HTTP + COLON + DOUBLESLASH + globalOnos.publicIp() + COLON +
                     globalOnos.port() + BASE_URL + "/global/topology" + resource;
 
             log.info("Sending data via http: url: {}\n body: {}", url, body);
diff --git a/local/http-channel/src/main/java/org/opencord/ce/local/channel/server/DomainMasterIpResource.java b/local/http-channel/src/main/java/org/opencord/ce/local/channel/server/DomainMasterIpResource.java
deleted file mode 100644
index 4f906c6..0000000
--- a/local/http-channel/src/main/java/org/opencord/ce/local/channel/server/DomainMasterIpResource.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright 2017-present Open Networking Laboratory
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.opencord.ce.local.channel.server;
-
-import com.fasterxml.jackson.databind.node.ObjectNode;
-import org.onlab.packet.IpAddress;
-import org.onosproject.cluster.ClusterService;
-import org.onosproject.rest.AbstractWebResource;
-import org.slf4j.Logger;
-
-import javax.ws.rs.GET;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-
-import static org.opencord.ce.api.services.channel.Symbols.MASTER_API_NO_IP_BODY;
-import static org.opencord.ce.api.services.channel.Symbols.MASTER_IP;
-import static org.opencord.ce.api.services.channel.Symbols.OK;
-import static org.opencord.ce.api.services.channel.Symbols.RESULT;
-import static org.slf4j.LoggerFactory.getLogger;
-
-/**
- * Gets the ip of the instance leader of the communication with the specified
- * domainId.
- */
-@Path("master")
-public class DomainMasterIpResource extends AbstractWebResource {
-    private final Logger log = getLogger(getClass());
-
-    @GET
-    @Produces(MediaType.APPLICATION_JSON)
-    public Response getMasterIp() {
-        log.info("Global domain asks who is the master for him");
-
-        //IpAddress ip = get(ConnectionService.class).getLocalMasterIp(id);
-
-        // testing
-        IpAddress ip = get(ClusterService.class).getLocalNode().ip();
-        if (ip != null) {
-            ObjectNode body = mapper().createObjectNode();
-            body.put(RESULT, OK);
-            body.put(MASTER_IP, ip.toString());
-
-            return ok(body.toString()).build();
-        } else {
-            return ok(MASTER_API_NO_IP_BODY).build();
-        }
-    }
-}
diff --git a/local/http-channel/src/main/java/org/opencord/ce/local/channel/server/EcordLocalRestApp.java b/local/http-channel/src/main/java/org/opencord/ce/local/channel/server/EcordLocalRestApp.java
index 810fa2d..52fd88c 100644
--- a/local/http-channel/src/main/java/org/opencord/ce/local/channel/server/EcordLocalRestApp.java
+++ b/local/http-channel/src/main/java/org/opencord/ce/local/channel/server/EcordLocalRestApp.java
@@ -28,6 +28,6 @@
 
     @Override
     public Set<Class<?>> getClasses() {
-        return getClasses(MetroNetworkResource.class, DomainMasterIpResource.class);
+        return getClasses(MetroNetworkResource.class);
     }
 }