ONOS-4326: Focusing on add/remove cluster member. (WIP).
If reviewing this, please refer to http://tinyurl.com/onos-ui-topo-model
Change-Id: Ic6568074ac768ec828f9103e92caab5e9a06ade6
diff --git a/core/api/src/main/java/org/onosproject/ui/model/ServiceBundle.java b/core/api/src/main/java/org/onosproject/ui/model/ServiceBundle.java
new file mode 100644
index 0000000..61cf721
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/ui/model/ServiceBundle.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2016-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.onosproject.ui.model;
+
+import org.onosproject.cluster.ClusterService;
+import org.onosproject.mastership.MastershipService;
+import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.flow.FlowRuleService;
+import org.onosproject.net.host.HostService;
+import org.onosproject.net.intent.IntentService;
+import org.onosproject.net.link.LinkService;
+import org.onosproject.net.region.RegionService;
+
+/**
+ * A bundle of services to pass to elements that might need a reference to them.
+ */
+public interface ServiceBundle {
+ /**
+ * Reference to a cluster service implementation.
+ *
+ * @return cluster service
+ */
+ ClusterService cluster();
+
+ /**
+ * Reference to a mastership service implementation.
+ *
+ * @return mastership service
+ */
+ MastershipService mastership();
+
+ /**
+ * Reference to a region service implementation.
+ *
+ * @return region service
+ */
+ RegionService region();
+
+ /**
+ * Reference to a device service implementation.
+ *
+ * @return device service
+ */
+ DeviceService device();
+
+ /**
+ * Reference to a link service implementation.
+ *
+ * @return link service
+ */
+ LinkService link();
+
+ /**
+ * Reference to a host service implementation.
+ *
+ * @return host service
+ */
+ HostService host();
+
+ /**
+ * Reference to a intent service implementation.
+ *
+ * @return intent service
+ */
+ IntentService intent();
+
+ /**
+ * Reference to a flow service implementation.
+ *
+ * @return flow service
+ */
+ FlowRuleService flow();
+}
diff --git a/core/api/src/main/java/org/onosproject/ui/model/topo/UiCluster.java b/core/api/src/main/java/org/onosproject/ui/model/topo/UiCluster.java
index a5de405..40de28c 100644
--- a/core/api/src/main/java/org/onosproject/ui/model/topo/UiCluster.java
+++ b/core/api/src/main/java/org/onosproject/ui/model/topo/UiCluster.java
@@ -28,12 +28,14 @@
*/
class UiCluster extends UiElement {
+ private static final String DEFAULT_CLUSTER_ID = "CLUSTER-0";
+
private final List<UiClusterMember> members = new ArrayList<>();
private final Map<NodeId, UiClusterMember> lookup = new HashMap<>();
@Override
public String toString() {
- return String.valueOf(members.size()) + "-member cluster";
+ return String.valueOf(size()) + "-member cluster";
}
/**
@@ -65,6 +67,16 @@
}
/**
+ * Removes the given member from the cluster.
+ *
+ * @param member member to remove
+ */
+ public void remove(UiClusterMember member) {
+ members.remove(member);
+ lookup.remove(member.id());
+ }
+
+ /**
* Returns the number of members in the cluster.
*
* @return number of members
@@ -72,4 +84,9 @@
public int size() {
return members.size();
}
+
+ @Override
+ public String idAsString() {
+ return DEFAULT_CLUSTER_ID;
+ }
}
diff --git a/core/api/src/main/java/org/onosproject/ui/model/topo/UiClusterMember.java b/core/api/src/main/java/org/onosproject/ui/model/topo/UiClusterMember.java
index f89a9ae..1cc9234 100644
--- a/core/api/src/main/java/org/onosproject/ui/model/topo/UiClusterMember.java
+++ b/core/api/src/main/java/org/onosproject/ui/model/topo/UiClusterMember.java
@@ -16,9 +16,12 @@
package org.onosproject.ui.model.topo;
+import org.onlab.packet.IpAddress;
import org.onosproject.cluster.ControllerNode;
import org.onosproject.cluster.NodeId;
+import static org.onosproject.cluster.ControllerNode.State.INACTIVE;
+
/**
* Represents an individual member of the cluster (ONOS instance).
*/
@@ -26,6 +29,9 @@
private final ControllerNode cnode;
+ private int deviceCount = 0;
+ private ControllerNode.State state = INACTIVE;
+
/**
* Constructs a cluster member, with a reference to the specified
* controller node instance.
@@ -36,13 +42,33 @@
this.cnode = cnode;
}
+ @Override
+ public String toString() {
+ return "UiClusterMember{" + cnode +
+ ", online=" + isOnline() +
+ ", ready=" + isReady() +
+ ", #devices=" + deviceCount +
+ "}";
+ }
+
+
/**
- * Updates the information about this cluster member.
+ * Sets the state of this cluster member.
*
- * @param cnode underlying controller node
+ * @param state the state
*/
- public void update(ControllerNode cnode) {
- // TODO: update our information cache appropriately
+ public void setState(ControllerNode.State state) {
+ this.state = state;
+ }
+
+
+ /**
+ * Sets the number of devices for which this cluster member is master.
+ *
+ * @param deviceCount number of devices
+ */
+ public void setDeviceCount(int deviceCount) {
+ this.deviceCount = deviceCount;
}
/**
@@ -53,4 +79,45 @@
public NodeId id() {
return cnode.id();
}
+
+ /**
+ * Returns the IP address of the cluster member.
+ *
+ * @return the IP address
+ */
+ public IpAddress ip() {
+ return cnode.ip();
+ }
+
+ /**
+ * Returns true if this cluster member is online (active).
+ *
+ * @return true if online, false otherwise
+ */
+ public boolean isOnline() {
+ return state.isActive();
+ }
+
+ /**
+ * Returns true if this cluster member is considered ready.
+ *
+ * @return true if ready, false otherwise
+ */
+ public boolean isReady() {
+ return state.isReady();
+ }
+
+ /**
+ * Returns the number of devices for which this cluster member is master.
+ *
+ * @return number of devices for which this member is master
+ */
+ public int deviceCount() {
+ return deviceCount;
+ }
+
+ @Override
+ public String idAsString() {
+ return id().toString();
+ }
}
diff --git a/core/api/src/main/java/org/onosproject/ui/model/topo/UiDevice.java b/core/api/src/main/java/org/onosproject/ui/model/topo/UiDevice.java
index 78f9d47..88d86d0 100644
--- a/core/api/src/main/java/org/onosproject/ui/model/topo/UiDevice.java
+++ b/core/api/src/main/java/org/onosproject/ui/model/topo/UiDevice.java
@@ -17,6 +17,7 @@
package org.onosproject.ui.model.topo;
import org.onosproject.net.Device;
+import org.onosproject.net.DeviceId;
/**
* Represents a device.
@@ -29,4 +30,18 @@
protected void destroy() {
device = null;
}
+
+ /**
+ * Returns the identity of the device.
+ *
+ * @return device ID
+ */
+ public DeviceId id() {
+ return device.id();
+ }
+
+ @Override
+ public String idAsString() {
+ return id().toString();
+ }
}
diff --git a/core/api/src/main/java/org/onosproject/ui/model/topo/UiElement.java b/core/api/src/main/java/org/onosproject/ui/model/topo/UiElement.java
index 5e6144d..f0c2684 100644
--- a/core/api/src/main/java/org/onosproject/ui/model/topo/UiElement.java
+++ b/core/api/src/main/java/org/onosproject/ui/model/topo/UiElement.java
@@ -19,7 +19,7 @@
/**
* Abstract base class of all elements in the UI topology model.
*/
-public class UiElement {
+public abstract class UiElement {
/**
* Removes all external references, and prepares the instance for
@@ -28,4 +28,11 @@
protected void destroy() {
// does nothing
}
+
+ /**
+ * Returns a string representation of the element identifier.
+ *
+ * @return the element unique identifier
+ */
+ public abstract String idAsString();
}
diff --git a/core/api/src/main/java/org/onosproject/ui/model/topo/UiHost.java b/core/api/src/main/java/org/onosproject/ui/model/topo/UiHost.java
index 933e469..9a9e24a 100644
--- a/core/api/src/main/java/org/onosproject/ui/model/topo/UiHost.java
+++ b/core/api/src/main/java/org/onosproject/ui/model/topo/UiHost.java
@@ -17,6 +17,7 @@
package org.onosproject.ui.model.topo;
import org.onosproject.net.Host;
+import org.onosproject.net.HostId;
/**
* Represents an end-station host.
@@ -29,4 +30,18 @@
protected void destroy() {
host = null;
}
+
+ /**
+ * Returns the identity of the host.
+ *
+ * @return host ID
+ */
+ public HostId id() {
+ return host.id();
+ }
+
+ @Override
+ public String idAsString() {
+ return id().toString();
+ }
}
diff --git a/core/api/src/main/java/org/onosproject/ui/model/topo/UiLink.java b/core/api/src/main/java/org/onosproject/ui/model/topo/UiLink.java
index f45a630..99d6144 100644
--- a/core/api/src/main/java/org/onosproject/ui/model/topo/UiLink.java
+++ b/core/api/src/main/java/org/onosproject/ui/model/topo/UiLink.java
@@ -54,4 +54,10 @@
children = null;
}
}
+
+ @Override
+ public String idAsString() {
+ // TODO
+ return null;
+ }
}
diff --git a/core/api/src/main/java/org/onosproject/ui/model/topo/UiRegion.java b/core/api/src/main/java/org/onosproject/ui/model/topo/UiRegion.java
index 9a3d6fb..488c37b 100644
--- a/core/api/src/main/java/org/onosproject/ui/model/topo/UiRegion.java
+++ b/core/api/src/main/java/org/onosproject/ui/model/topo/UiRegion.java
@@ -17,6 +17,7 @@
package org.onosproject.ui.model.topo;
import org.onosproject.net.region.Region;
+import org.onosproject.net.region.RegionId;
import java.util.Set;
import java.util.TreeSet;
@@ -46,4 +47,17 @@
region = null;
}
+ /**
+ * Returns the identity of the region.
+ *
+ * @return region ID
+ */
+ public RegionId id() {
+ return region.id();
+ }
+
+ @Override
+ public String idAsString() {
+ return id().toString();
+ }
}
diff --git a/core/api/src/main/java/org/onosproject/ui/model/topo/UiTopology.java b/core/api/src/main/java/org/onosproject/ui/model/topo/UiTopology.java
index 898c8eb..a8b5b06 100644
--- a/core/api/src/main/java/org/onosproject/ui/model/topo/UiTopology.java
+++ b/core/api/src/main/java/org/onosproject/ui/model/topo/UiTopology.java
@@ -28,6 +28,8 @@
*/
public class UiTopology extends UiElement {
+ private static final String DEFAULT_TOPOLOGY_ID = "TOPOLOGY-0";
+
private static final Logger log = LoggerFactory.getLogger(UiTopology.class);
private final UiCluster uiCluster = new UiCluster();
@@ -69,6 +71,15 @@
}
/**
+ * Removes the given cluster member from the topology model.
+ *
+ * @param member cluster member to remove
+ */
+ public void remove(UiClusterMember member) {
+ uiCluster.remove(member);
+ }
+
+ /**
* Returns the number of members in the cluster.
*
* @return number of cluster members
@@ -85,4 +96,9 @@
public int regionCount() {
return uiRegions.size();
}
+
+ @Override
+ public String idAsString() {
+ return DEFAULT_TOPOLOGY_ID;
+ }
}
diff --git a/core/api/src/test/java/org/onosproject/ui/AbstractUiTest.java b/core/api/src/test/java/org/onosproject/ui/AbstractUiTest.java
new file mode 100644
index 0000000..077d132
--- /dev/null
+++ b/core/api/src/test/java/org/onosproject/ui/AbstractUiTest.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2016-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.onosproject.ui;
+
+/**
+ * Abstract base class for UI tests.
+ */
+public abstract class AbstractUiTest {
+
+ /**
+ * System agnostic end-of-line character.
+ */
+ protected static final String EOL = String.format("%n");
+
+ /**
+ * Prints the given string to stdout.
+ *
+ * @param s string to print
+ */
+ protected static void print(String s) {
+ System.out.println(s);
+ }
+
+ /**
+ * Prints the toString() of the given object to stdout.
+ *
+ * @param o object to print
+ */
+ protected static void print(Object o) {
+ if (o == null) {
+ print("<null>");
+ } else {
+ print(o.toString());
+ }
+ }
+
+ /**
+ * Prints the formatted string to stdout.
+ *
+ * @param fmt format string
+ * @param params parameters
+ * @see String#format(String, Object...)
+ */
+ protected static void print(String fmt, Object... params) {
+ print(String.format(fmt, params));
+ }
+
+ /**
+ * Prints a title, to delimit individual unit test output.
+ *
+ * @param s a title for the test
+ */
+ protected static void title(String s) {
+ print(EOL + "=== %s ===", s);
+ }
+}
diff --git a/core/api/src/test/java/org/onosproject/ui/model/AbstractUiModelTest.java b/core/api/src/test/java/org/onosproject/ui/model/AbstractUiModelTest.java
new file mode 100644
index 0000000..5037832
--- /dev/null
+++ b/core/api/src/test/java/org/onosproject/ui/model/AbstractUiModelTest.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2016-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.onosproject.ui.model;
+
+import org.onosproject.cluster.ClusterService;
+import org.onosproject.cluster.ClusterServiceAdapter;
+import org.onosproject.cluster.ControllerNode;
+import org.onosproject.cluster.NodeId;
+import org.onosproject.mastership.MastershipService;
+import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.flow.FlowRuleService;
+import org.onosproject.net.host.HostService;
+import org.onosproject.net.intent.IntentService;
+import org.onosproject.net.link.LinkService;
+import org.onosproject.net.region.RegionService;
+import org.onosproject.ui.AbstractUiTest;
+
+/**
+ * Base class for UI model unit tests.
+ */
+public class AbstractUiModelTest extends AbstractUiTest {
+
+ /**
+ * Returns canned results.
+ * At some future point, we may make this "programmable", so that
+ * it returns certain values based on element IDs etc.
+ */
+ protected static final ServiceBundle MOCK_SERVICES =
+ new ServiceBundle() {
+ @Override
+ public ClusterService cluster() {
+ return MOCK_CLUSTER;
+ }
+
+ @Override
+ public MastershipService mastership() {
+ return null;
+ }
+
+ @Override
+ public RegionService region() {
+ return null;
+ }
+
+ @Override
+ public DeviceService device() {
+ return null;
+ }
+
+ @Override
+ public LinkService link() {
+ return null;
+ }
+
+ @Override
+ public HostService host() {
+ return null;
+ }
+
+ @Override
+ public IntentService intent() {
+ return null;
+ }
+
+ @Override
+ public FlowRuleService flow() {
+ return null;
+ }
+ };
+
+ private static final ClusterService MOCK_CLUSTER = new MockClusterService();
+
+
+ private static class MockClusterService extends ClusterServiceAdapter {
+ @Override
+ public ControllerNode.State getState(NodeId nodeId) {
+ // For now, a hardcoded state of ACTIVE (but not READY)
+ // irrespective of the node ID.
+ return ControllerNode.State.ACTIVE;
+ }
+ }
+
+}
diff --git a/core/api/src/test/java/org/onosproject/ui/model/topo/UiClusterMemberTest.java b/core/api/src/test/java/org/onosproject/ui/model/topo/UiClusterMemberTest.java
new file mode 100644
index 0000000..db35b33
--- /dev/null
+++ b/core/api/src/test/java/org/onosproject/ui/model/topo/UiClusterMemberTest.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2016-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.onosproject.ui.model.topo;
+
+import org.junit.Test;
+import org.onlab.packet.IpAddress;
+import org.onosproject.cluster.ControllerNode;
+import org.onosproject.cluster.DefaultControllerNode;
+import org.onosproject.cluster.NodeId;
+import org.onosproject.ui.model.AbstractUiModelTest;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Unit tests for {@link UiClusterMember}.
+ */
+public class UiClusterMemberTest extends AbstractUiModelTest {
+
+ private static final NodeId NODE_ID = NodeId.nodeId("Node-1");
+ private static final IpAddress NODE_IP = IpAddress.valueOf("1.2.3.4");
+
+ private static final ControllerNode CNODE_1 =
+ new DefaultControllerNode(NODE_ID, NODE_IP);
+
+ private UiClusterMember member;
+
+ @Test
+ public void basic() {
+ title("basic");
+ member = new UiClusterMember(CNODE_1);
+ print(member);
+
+ assertEquals("wrong id", NODE_ID, member.id());
+ assertEquals("wrong IP", NODE_IP, member.ip());
+ assertEquals("unex. online", false, member.isOnline());
+ assertEquals("unex. ready", false, member.isReady());
+ assertEquals("unex. device count", 0, member.deviceCount());
+ }
+}