ONOS-6742 Refactored OpenstackNode
- Removed gateway node uplink interface configuration steps
- Added checking group states
- Refactored interface, store, manager and handler
Change-Id: I9149edbec6481b15377848c8f24bdc5c6c73adc4
diff --git a/apps/openstacknode/src/main/java/org/onosproject/openstacknode/impl/DefaultOpenstackNode.java b/apps/openstacknode/src/main/java/org/onosproject/openstacknode/impl/DefaultOpenstackNode.java
new file mode 100644
index 0000000..670d4e8
--- /dev/null
+++ b/apps/openstacknode/src/main/java/org/onosproject/openstacknode/impl/DefaultOpenstackNode.java
@@ -0,0 +1,355 @@
+/*
+ * 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.onosproject.openstacknode.impl;
+
+import com.google.common.base.MoreObjects;
+import com.google.common.base.Strings;
+import org.onlab.osgi.DefaultServiceDirectory;
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.MacAddress;
+import org.onosproject.core.GroupId;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.Port;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.group.DefaultGroupKey;
+import org.onosproject.net.group.GroupKey;
+import org.onosproject.openstacknode.api.NodeState;
+import org.onosproject.openstacknode.api.OpenstackNode;
+
+import java.util.Objects;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static org.onosproject.net.AnnotationKeys.PORT_MAC;
+import static org.onosproject.net.AnnotationKeys.PORT_NAME;
+import static org.onosproject.openstacknode.api.Constants.DEFAULT_TUNNEL;
+import static org.onosproject.openstacknode.api.Constants.PATCH_INTG_BRIDGE;
+
+/**
+ * Representation of a openstack node.
+ */
+public final class DefaultOpenstackNode implements OpenstackNode {
+
+ private final String hostname;
+ private final NodeType type;
+ private final DeviceId intgBridge;
+ private final DeviceId routerBridge;
+ private final IpAddress managementIp;
+ private final IpAddress dataIp;
+ private final String vlanIntf;
+ private final NodeState state;
+
+ private DefaultOpenstackNode(String hostname,
+ NodeType type,
+ DeviceId intgBridge,
+ DeviceId routerBridge,
+ IpAddress managementIp,
+ IpAddress dataIp,
+ String vlanIntf,
+ NodeState state) {
+ this.hostname = hostname;
+ this.type = type;
+ this.intgBridge = intgBridge;
+ this.routerBridge = routerBridge;
+ this.managementIp = managementIp;
+ this.dataIp = dataIp;
+ this.vlanIntf = vlanIntf;
+ this.state = state;
+ }
+
+ @Override
+ public String hostname() {
+ return hostname;
+ }
+
+ @Override
+ public NodeType type() {
+ return type;
+ }
+
+ @Override
+ public DeviceId ovsdb() {
+ return DeviceId.deviceId("ovsdb:" + managementIp().toString());
+ }
+
+ @Override
+ public DeviceId intgBridge() {
+ return intgBridge;
+ }
+
+ @Override
+ public DeviceId routerBridge() {
+ return routerBridge;
+ }
+
+ @Override
+ public IpAddress managementIp() {
+ return managementIp;
+ }
+
+ @Override
+ public IpAddress dataIp() {
+ return dataIp;
+ }
+
+ @Override
+ public String vlanIntf() {
+ return vlanIntf;
+ }
+
+ @Override
+ public NodeState state() {
+ return state;
+ }
+
+ @Override
+ public GroupKey gatewayGroupKey(NetworkMode mode) {
+ return new DefaultGroupKey(intgBridge.toString().concat(mode.name()).getBytes());
+ }
+
+ @Override
+ public PortNumber tunnelPortNum() {
+ if (dataIp == null) {
+ return null;
+ }
+ DeviceService deviceService = DefaultServiceDirectory.getService(DeviceService.class);
+ Port port = deviceService.getPorts(intgBridge).stream()
+ .filter(p -> p.isEnabled() &&
+ Objects.equals(p.annotations().value(PORT_NAME), DEFAULT_TUNNEL))
+ .findAny().orElse(null);
+ return port != null ? port.number() : null;
+ }
+
+ @Override
+ public PortNumber vlanPortNum() {
+ if (vlanIntf == null) {
+ return null;
+ }
+ DeviceService deviceService = DefaultServiceDirectory.getService(DeviceService.class);
+ Port port = deviceService.getPorts(intgBridge).stream()
+ .filter(p -> p.isEnabled() &&
+ Objects.equals(p.annotations().value(PORT_NAME), vlanIntf))
+ .findAny().orElse(null);
+ return port != null ? port.number() : null;
+ }
+
+ @Override
+ public PortNumber patchPortNum() {
+ if (type == NodeType.COMPUTE) {
+ return null;
+ }
+ DeviceService deviceService = DefaultServiceDirectory.getService(DeviceService.class);
+ Port port = deviceService.getPorts(intgBridge).stream()
+ .filter(p -> p.isEnabled() &&
+ Objects.equals(p.annotations().value(PORT_NAME), PATCH_INTG_BRIDGE))
+ .findAny().orElse(null);
+ return port != null ? port.number() : null;
+ }
+
+ @Override
+ public MacAddress vlanPortMac() {
+ if (vlanIntf == null) {
+ return null;
+ }
+ DeviceService deviceService = DefaultServiceDirectory.getService(DeviceService.class);
+ Port port = deviceService.getPorts(intgBridge).stream()
+ .filter(p -> p.annotations().value(PORT_NAME).equals(vlanIntf))
+ .findAny().orElse(null);
+ return port != null ? MacAddress.valueOf(port.annotations().value(PORT_MAC)) : null;
+ }
+
+ @Override
+ public GroupId gatewayGroupId(NetworkMode mode) {
+ return new GroupId(intgBridge.toString().concat(mode.name()).hashCode());
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+
+ if (obj instanceof DefaultOpenstackNode) {
+ DefaultOpenstackNode that = (DefaultOpenstackNode) obj;
+ if (Objects.equals(hostname, that.hostname) &&
+ Objects.equals(type, that.type) &&
+ Objects.equals(intgBridge, that.intgBridge) &&
+ Objects.equals(routerBridge, that.routerBridge) &&
+ Objects.equals(managementIp, that.managementIp) &&
+ Objects.equals(dataIp, that.dataIp) &&
+ Objects.equals(vlanIntf, that.vlanIntf)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(hostname,
+ type,
+ intgBridge,
+ routerBridge,
+ managementIp,
+ dataIp,
+ vlanIntf);
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(getClass())
+ .add("hostname", hostname)
+ .add("type", type)
+ .add("integrationBridge", intgBridge)
+ .add("routerBridge", routerBridge)
+ .add("managementIp", managementIp)
+ .add("dataIp", dataIp)
+ .add("vlanIntf", vlanIntf)
+ .add("state", state)
+ .toString();
+ }
+
+ @Override
+ public OpenstackNode updateState(NodeState newState) {
+ return new Builder()
+ .type(type)
+ .hostname(hostname)
+ .intgBridge(intgBridge)
+ .routerBridge(routerBridge)
+ .managementIp(managementIp)
+ .dataIp(dataIp)
+ .vlanIntf(vlanIntf)
+ .state(newState)
+ .build();
+ }
+
+ /**
+ * Returns new builder instance.
+ *
+ * @return openstack node builder
+ */
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ /**
+ * Returns new builder instance with the given node as a default value.
+ *
+ * @param osNode openstack node
+ * @return openstack node builder
+ */
+ public static Builder from(OpenstackNode osNode) {
+ return new Builder()
+ .hostname(osNode.hostname())
+ .intgBridge(osNode.intgBridge())
+ .routerBridge(osNode.routerBridge())
+ .managementIp(osNode.managementIp())
+ .dataIp(osNode.dataIp())
+ .vlanIntf(osNode.vlanIntf())
+ .state(osNode.state());
+ }
+
+ public static final class Builder implements OpenstackNode.Builder {
+
+ private String hostname;
+ private NodeType type;
+ private DeviceId intgBridge;
+ private DeviceId routerBridge;
+ private IpAddress managementIp;
+ private IpAddress dataIp;
+ private String vlanIntf;
+ private NodeState state;
+
+ private Builder() {
+ }
+
+ @Override
+ public DefaultOpenstackNode build() {
+ checkArgument(hostname != null, "Node hostname cannot be null");
+ checkArgument(type != null, "Node type cannot be null");
+ checkArgument(intgBridge != null, "Node integration bridge cannot be null");
+ checkArgument(managementIp != null, "Node management IP cannot be null");
+ checkArgument(state != null, "Node state cannot be null");
+
+ if (type == NodeType.GATEWAY && routerBridge == null) {
+ throw new IllegalArgumentException("Router bridge is required for gateway node");
+ }
+ if (dataIp == null && Strings.isNullOrEmpty(vlanIntf)) {
+ throw new IllegalArgumentException("Either data IP or VLAN interface is required");
+ }
+
+ return new DefaultOpenstackNode(hostname,
+ type,
+ intgBridge,
+ routerBridge,
+ managementIp,
+ dataIp,
+ vlanIntf,
+ state);
+ }
+
+ @Override
+ public Builder hostname(String hostname) {
+ if (!Strings.isNullOrEmpty(hostname)) {
+ this.hostname = hostname;
+ }
+ return this;
+ }
+
+ @Override
+ public Builder type(NodeType type) {
+ this.type = type;
+ return this;
+ }
+
+ @Override
+ public Builder intgBridge(DeviceId intgBridge) {
+ this.intgBridge = intgBridge;
+ return this;
+ }
+
+ @Override
+ public Builder routerBridge(DeviceId routerBridge) {
+ this.routerBridge = routerBridge;
+ return this;
+ }
+
+ @Override
+ public Builder managementIp(IpAddress managementIp) {
+ this.managementIp = managementIp;
+ return this;
+ }
+
+ @Override
+ public Builder dataIp(IpAddress dataIp) {
+ this.dataIp = dataIp;
+ return this;
+ }
+
+ @Override
+ public Builder vlanIntf(String vlanIntf) {
+ this.vlanIntf = vlanIntf;
+ return this;
+ }
+
+ @Override
+ public Builder state(NodeState state) {
+ this.state = state;
+ return this;
+ }
+ }
+}
+