CORD-151 add initial skeleton for cord-vtn application
Change-Id: I57bf17445f1e571b51bca2fe7c2631e65cd43145
diff --git a/apps/cordvtn/pom.xml b/apps/cordvtn/pom.xml
index 443fc2c..a019bec 100644
--- a/apps/cordvtn/pom.xml
+++ b/apps/cordvtn/pom.xml
@@ -36,6 +36,19 @@
</properties>
<dependencies>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.compendium</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-core-serializers</artifactId>
+ <version>${project.version}</version>
+ </dependency>
</dependencies>
</project>
diff --git a/apps/cordvtn/src/main/java/org/onosproject/cordvtn/ConnectionHandler.java b/apps/cordvtn/src/main/java/org/onosproject/cordvtn/ConnectionHandler.java
new file mode 100644
index 0000000..af73823
--- /dev/null
+++ b/apps/cordvtn/src/main/java/org/onosproject/cordvtn/ConnectionHandler.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2014-2015 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.onosproject.cordvtn;
+
+/**
+ * Entity capable of handling a subject connected and disconnected situation.
+ */
+public interface ConnectionHandler<T> {
+
+ /**
+ * Processes the connected subject.
+ *
+ * @param subject subject
+ */
+ void connected(T subject);
+
+ /**
+ * Processes the disconnected subject.
+ *
+ * @param subject subject.
+ */
+ void disconnected(T subject);
+}
diff --git a/apps/cordvtn/src/main/java/org/onosproject/cordvtn/CordVtn.java b/apps/cordvtn/src/main/java/org/onosproject/cordvtn/CordVtn.java
new file mode 100644
index 0000000..072254d
--- /dev/null
+++ b/apps/cordvtn/src/main/java/org/onosproject/cordvtn/CordVtn.java
@@ -0,0 +1,311 @@
+/*
+ * Copyright 2014-2015 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.onosproject.cordvtn;
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.apache.felix.scr.annotations.Service;
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.TpPort;
+import org.onlab.util.KryoNamespace;
+import org.onosproject.cluster.ClusterService;
+import org.onosproject.cluster.LeadershipEvent;
+import org.onosproject.cluster.LeadershipEventListener;
+import org.onosproject.cluster.LeadershipService;
+import org.onosproject.cluster.NodeId;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.CoreService;
+import org.onosproject.mastership.MastershipService;
+import org.onosproject.net.Device;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.Host;
+import org.onosproject.net.config.ConfigFactory;
+import org.onosproject.net.config.NetworkConfigRegistry;
+import org.onosproject.net.config.NetworkConfigService;
+import org.onosproject.net.config.basics.SubjectFactories;
+import org.onosproject.net.device.DeviceEvent;
+import org.onosproject.net.device.DeviceListener;
+import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.host.HostEvent;
+import org.onosproject.net.host.HostListener;
+import org.onosproject.net.host.HostService;
+import org.onosproject.store.serializers.KryoNamespaces;
+import org.onosproject.store.service.EventuallyConsistentMap;
+import org.onosproject.store.service.LogicalClockService;
+import org.onosproject.store.service.StorageService;
+import org.slf4j.Logger;
+
+import java.util.List;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.stream.Collectors;
+
+import static org.onlab.util.Tools.groupedThreads;
+import static org.onosproject.cordvtn.OvsdbNode.State.INIT;
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * CORD VTN Application that provisions overlay virtual tenant networks.
+ */
+@Component(immediate = true)
+@Service
+public class CordVtn implements CordVtnService {
+
+ protected final Logger log = getLogger(getClass());
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected CoreService coreService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected StorageService storageService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected LogicalClockService clockService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected ClusterService clusterService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected LeadershipService leadershipService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected NetworkConfigService configService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected NetworkConfigRegistry configRegistry;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected DeviceService deviceService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected HostService hostService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected MastershipService mastershipService;
+
+ private static final int DEFAULT_NUM_THREADS = 1;
+ private static final KryoNamespace.Builder NODE_SERIALIZER = KryoNamespace.newBuilder()
+ .register(KryoNamespaces.API)
+ .register(OvsdbNode.class);
+
+ private final ExecutorService eventExecutor = Executors.newFixedThreadPool(
+ DEFAULT_NUM_THREADS, groupedThreads("onos/cordvtn", "event-handler"));
+
+ private final LeadershipEventListener leadershipListener = new InternalLeadershipListener();
+ private final DeviceListener deviceListener = new InternalDeviceListener();
+ private final HostListener hostListener = new InternalHostListener();
+ private final NodeHandler nodeHandler = new NodeHandler();
+ private final BridgeHandler bridgeHandler = new BridgeHandler();
+ private final VirtualMachineHandler vmHandler = new VirtualMachineHandler();
+
+ private final ConfigFactory configFactory =
+ new ConfigFactory(SubjectFactories.APP_SUBJECT_FACTORY, CordVtnConfig.class, "cordvtn") {
+ @Override
+ public CordVtnConfig createConfig() {
+ return new CordVtnConfig();
+ }
+ };
+
+ private ApplicationId appId;
+ private NodeId local;
+ private EventuallyConsistentMap<DeviceId, OvsdbNode> nodeStore;
+ private NodeConnectionManager nodeConnectionManager;
+
+ @Activate
+ protected void activate() {
+ appId = coreService.registerApplication("org.onosproject.cordvtn");
+
+ local = clusterService.getLocalNode().id();
+ nodeStore = storageService.<DeviceId, OvsdbNode>eventuallyConsistentMapBuilder()
+ .withName("cordvtn-nodestore")
+ .withSerializer(NODE_SERIALIZER)
+ .withTimestampProvider((k, v) -> clockService.getTimestamp())
+ .build();
+ configRegistry.registerConfigFactory(configFactory);
+
+ deviceService.addListener(deviceListener);
+ hostService.addListener(hostListener);
+ leadershipService.addListener(leadershipListener);
+ leadershipService.runForLeadership(appId.name());
+ nodeConnectionManager = new NodeConnectionManager(appId, local, nodeStore,
+ mastershipService, leadershipService);
+ nodeConnectionManager.start();
+ log.info("Started");
+ }
+
+ @Deactivate
+ protected void deactivate() {
+ nodeConnectionManager.stop();
+ leadershipService.removeListener(leadershipListener);
+ leadershipService.withdraw(appId.name());
+ deviceService.removeListener(deviceListener);
+ hostService.removeListener(hostListener);
+ eventExecutor.shutdown();
+ nodeStore.destroy();
+ configRegistry.unregisterConfigFactory(configFactory);
+ log.info("Stopped");
+ }
+
+ @Override
+ public void addNode(String hostname, IpAddress ip, TpPort port) {
+ DefaultOvsdbNode node = new DefaultOvsdbNode(hostname, ip, port, DeviceId.NONE, INIT);
+
+ if (nodeStore.containsKey(node.deviceId())) {
+ log.warn("Node {} with ovsdb-server {}:{} already exists", hostname, ip, port);
+ return;
+ }
+ nodeStore.put(node.deviceId(), node);
+ log.info("New node {} with ovsdb-server {}:{} has been added", hostname, ip, port);
+ }
+
+ @Override
+ public void deleteNode(IpAddress ip, TpPort port) {
+ DeviceId deviceId = DeviceId.deviceId("ovsdb:" + ip + ":" + port);
+ OvsdbNode node = nodeStore.get(deviceId);
+
+ if (node == null) {
+ log.warn("Node with ovsdb-server on {}:{} does not exist", ip, port);
+ return;
+ }
+ nodeConnectionManager.disconnectNode(node);
+ nodeStore.remove(node.deviceId());
+ }
+
+ @Override
+ public int getNodeCount() {
+ return nodeStore.size();
+ }
+
+ @Override
+ public List<OvsdbNode> getNodes() {
+ return nodeStore.values()
+ .stream()
+ .collect(Collectors.toList());
+ }
+
+ private void initialSetup() {
+ // Read ovsdb nodes from network config
+ CordVtnConfig config = configService.getConfig(appId, CordVtnConfig.class);
+ if (config == null) {
+ log.warn("No configuration found");
+ return;
+ }
+ config.ovsdbNodes().forEach(
+ node -> addNode(node.hostname(), node.ip(), node.port()));
+ }
+
+ private synchronized void processLeadershipChange(NodeId leader) {
+ // Only the leader performs the initial setup
+ if (leader == null || !leader.equals(local)) {
+ return;
+ }
+ initialSetup();
+ }
+
+ private class InternalLeadershipListener implements LeadershipEventListener {
+
+ @Override
+ public void event(LeadershipEvent event) {
+ if (event.subject().topic().equals(appId.name())) {
+ processLeadershipChange(event.subject().leader());
+ }
+ }
+ }
+
+ private class InternalDeviceListener implements DeviceListener {
+
+ @Override
+ public void event(DeviceEvent event) {
+ Device device = event.subject();
+ ConnectionHandler handler =
+ (device.type() == Device.Type.CONTROLLER ? nodeHandler : bridgeHandler);
+
+ switch (event.type()) {
+ case DEVICE_ADDED:
+ eventExecutor.submit(() -> handler.connected(device));
+ break;
+ case DEVICE_AVAILABILITY_CHANGED:
+ eventExecutor.submit(() -> handler.disconnected(device));
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ private class InternalHostListener implements HostListener {
+
+ @Override
+ public void event(HostEvent event) {
+ Host vm = event.subject();
+
+ switch (event.type()) {
+ case HOST_ADDED:
+ eventExecutor.submit(() -> vmHandler.connected(vm));
+ break;
+ case HOST_REMOVED:
+ eventExecutor.submit(() -> vmHandler.disconnected(vm));
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ private class NodeHandler implements ConnectionHandler<Device> {
+
+ @Override
+ public void connected(Device device) {
+ // create bridge and set bridgeId
+ // set node state connected
+ }
+
+ @Override
+ public void disconnected(Device device) {
+ // set node state disconnected if the node exists
+ // which means that the node is not deleted explicitly
+ }
+ }
+
+ private class BridgeHandler implements ConnectionHandler<Device> {
+
+ @Override
+ public void connected(Device device) {
+ // create vxlan port
+ }
+
+ @Override
+ public void disconnected(Device device) {
+
+ }
+ }
+
+ private class VirtualMachineHandler implements ConnectionHandler<Host> {
+
+ @Override
+ public void connected(Host host) {
+ // install flow rules for this vm
+ }
+
+ @Override
+ public void disconnected(Host host) {
+ // uninstall flow rules associated with this vm
+ }
+ }
+}
diff --git a/apps/cordvtn/src/main/java/org/onosproject/cordvtn/CordVtnConfig.java b/apps/cordvtn/src/main/java/org/onosproject/cordvtn/CordVtnConfig.java
new file mode 100644
index 0000000..c2c37ab
--- /dev/null
+++ b/apps/cordvtn/src/main/java/org/onosproject/cordvtn/CordVtnConfig.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2014-2015 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.onosproject.cordvtn;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.google.common.collect.Sets;
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.TpPort;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.net.config.Config;
+
+import java.util.Set;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Configuration object for CORD VTN service.
+ */
+public class CordVtnConfig extends Config<ApplicationId> {
+
+ public static final String OVSDB_NODES = "ovsdbNodes";
+ public static final String HOSTNAME = "hostname";
+ public static final String IP = "ip";
+ public static final String PORT = "port";
+
+ /**
+ * Returns the set of ovsdb nodes read from network config.
+ *
+ * @return set of OvsdbNodeConfig or null
+ */
+ public Set<OvsdbNodeConfig> ovsdbNodes() {
+ Set<OvsdbNodeConfig> ovsdbNodes = Sets.newHashSet();
+
+ JsonNode nodes = object.get(OVSDB_NODES);
+ if (nodes == null) {
+ return null;
+ }
+ nodes.forEach(jsonNode -> ovsdbNodes.add(new OvsdbNodeConfig(
+ jsonNode.path(HOSTNAME).asText(),
+ IpAddress.valueOf(jsonNode.path(IP).asText()),
+ TpPort.tpPort(jsonNode.path(PORT).asInt()))));
+
+ return ovsdbNodes;
+ }
+
+ /**
+ * Configuration for an OVSDB node.
+ */
+ public static class OvsdbNodeConfig {
+
+ private final String hostname;
+ private final IpAddress ip;
+ private final TpPort port;
+
+ public OvsdbNodeConfig(String hostname, IpAddress ip, TpPort port) {
+ this.hostname = checkNotNull(hostname);
+ this.ip = checkNotNull(ip);
+ this.port = checkNotNull(port);
+ }
+
+ /**
+ * Returns hostname of the node.
+ *
+ * @return hostname
+ */
+ public String hostname() {
+ return this.hostname;
+ }
+
+ /**
+ * Returns ip address to access ovsdb-server of the node.
+ *
+ * @return ip address
+ */
+ public IpAddress ip() {
+ return this.ip;
+ }
+
+ /**
+ * Returns port number to access ovsdb-server of the node.
+ *
+ * @return port number
+ */
+ public TpPort port() {
+ return this.port;
+ }
+ }
+}
diff --git a/apps/cordvtn/src/main/java/org/onosproject/cordvtn/CordVtnService.java b/apps/cordvtn/src/main/java/org/onosproject/cordvtn/CordVtnService.java
index 1dee476..d26a10a 100644
--- a/apps/cordvtn/src/main/java/org/onosproject/cordvtn/CordVtnService.java
+++ b/apps/cordvtn/src/main/java/org/onosproject/cordvtn/CordVtnService.java
@@ -15,6 +15,9 @@
*/
package org.onosproject.cordvtn;
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.TpPort;
+
import java.util.List;
/**
@@ -22,19 +25,21 @@
*/
public interface CordVtnService {
/**
- * Adds new nodes to the service and processes initial setup.
+ * Adds a new node to the service.
*
- * @param ovsdbNodes list of nodes
+ * @param hostname hostname of the node
+ * @param ip ip address to access the ovsdb server running on the node
+ * @param port port number to access the ovsdb server running on the node
*/
- void addNodes(List<OvsdbNode> ovsdbNodes);
+ void addNode(String hostname, IpAddress ip, TpPort port);
/**
- * Deletes the nodes from the service and cleans up unnecessary configurations
- * associated with the deleted nodes.
+ * Deletes the node from the service.
*
- * @param ovsdbNodes list of nodes
+ * @param ip ip address to access the ovsdb server running on the node
+ * @param port port number to access the ovsdb server running on the node
*/
- void deleteNodes(List<OvsdbNode> ovsdbNodes);
+ void deleteNode(IpAddress ip, TpPort port);
/**
* Returns the number of the nodes known to the service.
diff --git a/apps/cordvtn/src/main/java/org/onosproject/cordvtn/DefaultOvsdbNode.java b/apps/cordvtn/src/main/java/org/onosproject/cordvtn/DefaultOvsdbNode.java
new file mode 100644
index 0000000..b8cdbe9
--- /dev/null
+++ b/apps/cordvtn/src/main/java/org/onosproject/cordvtn/DefaultOvsdbNode.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2014-2015 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.onosproject.cordvtn;
+
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.TpPort;
+import org.onosproject.net.DeviceId;
+
+import java.util.Objects;
+
+/**
+ * OvsdbNode implementation.
+ */
+public class DefaultOvsdbNode implements OvsdbNode {
+
+ private final String hostname;
+ private final IpAddress ip;
+ private final TpPort port;
+ private final DeviceId deviceId;
+ private final DeviceId bridgeId;
+ private final State state;
+
+ public DefaultOvsdbNode(String hostname, IpAddress ip, TpPort port,
+ DeviceId bridgeId, State state) {
+ this.hostname = hostname;
+ this.ip = ip;
+ this.port = port;
+ this.deviceId = DeviceId.deviceId(
+ "ovsdb:" + ip.toString() + ":" + port.toString());
+ this.bridgeId = bridgeId;
+ this.state = state;
+ }
+
+ @Override
+ public IpAddress ip() {
+ return this.ip;
+ }
+
+ @Override
+ public TpPort port() {
+ return this.port;
+ }
+
+ @Override
+ public String hostname() {
+ return this.hostname;
+ }
+
+ @Override
+ public State state() {
+ return this.state;
+ }
+
+ @Override
+ public DeviceId deviceId() {
+ return this.deviceId;
+ }
+
+ @Override
+ public DeviceId bridgeId() {
+ return this.bridgeId;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+
+ if (o instanceof DefaultOvsdbNode) {
+ DefaultOvsdbNode that = (DefaultOvsdbNode) o;
+ // We compare the ip and port only.
+ if (this.ip.equals(that.ip) && this.port.equals(that.port)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(ip, port);
+ }
+}
diff --git a/apps/cordvtn/src/main/java/org/onosproject/cordvtn/NodeConnectionManager.java b/apps/cordvtn/src/main/java/org/onosproject/cordvtn/NodeConnectionManager.java
new file mode 100644
index 0000000..0b7029e
--- /dev/null
+++ b/apps/cordvtn/src/main/java/org/onosproject/cordvtn/NodeConnectionManager.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright 2014-2015 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.onosproject.cordvtn;
+
+import org.onosproject.cluster.LeadershipService;
+import org.onosproject.cluster.NodeId;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.mastership.MastershipService;
+import org.onosproject.net.DeviceId;
+import org.onosproject.store.service.EventuallyConsistentMap;
+import org.slf4j.Logger;
+
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+
+import static org.onlab.util.Tools.groupedThreads;
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * Node connection manager.
+ */
+public class NodeConnectionManager {
+ protected final Logger log = getLogger(getClass());
+
+ private final ApplicationId appId;
+ private final NodeId localId;
+ private final EventuallyConsistentMap<DeviceId, OvsdbNode> nodeStore;
+ private final MastershipService mastershipService;
+ private final LeadershipService leadershipService;
+
+ private static final int DELAY_SEC = 5;
+ private ScheduledExecutorService connectionExecutor;
+
+ /**
+ * Creates a new NodeConnectionManager.
+ *
+ * @param localId local id
+ * @param nodeStore node store
+ * @param mastershipService mastership service
+ */
+ public NodeConnectionManager(ApplicationId appId, NodeId localId,
+ EventuallyConsistentMap<DeviceId, OvsdbNode> nodeStore,
+ MastershipService mastershipService,
+ LeadershipService leadershipService) {
+ this.appId = appId;
+ this.localId = localId;
+ this.nodeStore = nodeStore;
+ this.mastershipService = mastershipService;
+ this.leadershipService = leadershipService;
+ }
+
+ /**
+ * Starts the node connection manager.
+ */
+ public void start() {
+ connectionExecutor = Executors.newSingleThreadScheduledExecutor(
+ groupedThreads("onos/cordvtn", "connection-executor"));
+ connectionExecutor.scheduleWithFixedDelay(() -> nodeStore.values()
+ .stream()
+ .filter(node -> localId.equals(getMaster(node)))
+ .forEach(node -> connectNode(node)), 0, DELAY_SEC, TimeUnit.SECONDS);
+ }
+
+ /**
+ * Stops the node connection manager.
+ */
+ public void stop() {
+ connectionExecutor.shutdown();
+ }
+
+ /**
+ * Adds a new node to the system.
+ *
+ * @param ovsdbNode ovsdb node
+ */
+ public void connectNode(OvsdbNode ovsdbNode) {
+ switch (ovsdbNode.state()) {
+ case INIT:
+ case DISCONNECTED:
+ // TODO: set the node to passive mode
+ case READY:
+ // TODO: initiate connection
+ break;
+ case CONNECTED:
+ break;
+ default:
+ }
+ }
+
+ /**
+ * Deletes the ovsdb node.
+ *
+ * @param ovsdbNode ovsdb node
+ */
+ public void disconnectNode(OvsdbNode ovsdbNode) {
+ switch (ovsdbNode.state()) {
+ case CONNECTED:
+ // TODO: disconnect
+ break;
+ case INIT:
+ case READY:
+ case DISCONNECTED:
+ break;
+ default:
+ }
+ }
+
+ private NodeId getMaster(OvsdbNode ovsdbNode) {
+ // Return the master of the bridge(switch) if it exist or
+ // return the current leader
+ if (ovsdbNode.bridgeId() == DeviceId.NONE) {
+ return leadershipService.getLeader(this.appId.name());
+ } else {
+ return mastershipService.getMasterFor(ovsdbNode.bridgeId());
+ }
+ }
+
+ private void setPassiveMode(OvsdbNode ovsdbNode) {
+ // TODO: need ovsdb client implementation first
+ // TODO: set the remove ovsdb server passive mode
+ // TODO: set the node state READY if it succeed
+ }
+
+ private void connect(OvsdbNode ovsdbNode) {
+ // TODO: need ovsdb client implementation first
+ }
+
+ private void disconnect(OvsdbNode ovsdbNode) {
+ // TODO: need ovsdb client implementation first
+ }
+}
diff --git a/apps/cordvtn/src/main/java/org/onosproject/cordvtn/OvsdbNode.java b/apps/cordvtn/src/main/java/org/onosproject/cordvtn/OvsdbNode.java
index 75e61d7..bb2a0b7 100644
--- a/apps/cordvtn/src/main/java/org/onosproject/cordvtn/OvsdbNode.java
+++ b/apps/cordvtn/src/main/java/org/onosproject/cordvtn/OvsdbNode.java
@@ -18,8 +18,6 @@
import org.onlab.packet.IpAddress;
import org.onlab.packet.TpPort;
import org.onosproject.net.DeviceId;
-import org.onosproject.net.behaviour.BridgeConfig;
-import org.onosproject.net.behaviour.TunnelConfig;
/**
* Representation of a node with ovsdb server.
@@ -29,7 +27,7 @@
* State of the ovsdb node.
*/
enum State {
- READY, CONNECTED, DISCONNECTED
+ INIT, READY, CONNECTED, DISCONNECTED
}
/**
@@ -47,44 +45,30 @@
TpPort port();
/**
+ * Returns the hostname of the node.
+ *
+ * @return hostname
+ */
+ String hostname();
+
+ /**
* Returns the state of the node.
*
* @return state of the node
*/
- State getState();
-
- /**
- * Sets the state of the node.
- *
- * @param state state of the node
- */
- void setState(State state);
+ State state();
/**
* Returns the device ID of the node.
*
* @return device id
*/
- DeviceId getDeviceId();
+ DeviceId deviceId();
/**
- * Sets the device id of the node.
+ * Returns the device ID of the bridge associated with this node.
*
- * @param deviceId device identifier
+ * @return device id
*/
- void setDeviceId(DeviceId deviceId);
-
- /**
- * Returns the bridge configuration handler of the node.
- *
- * @return bridge config behavior instance
- */
- BridgeConfig getBridgeConfig();
-
- /**
- * Returns the tunnel configuration handler of the node.
- *
- * @return tunnel config behavior instance
- */
- TunnelConfig getTunnelConfig();
+ DeviceId bridgeId();
}