[ONOS-7902] Add default implementation of k8s node with unit tests
Change-Id: I283967ae14dc7f38e749d7407e4bec698536c18b
diff --git a/apps/k8s-node/api/src/main/java/org/onosproject/k8snode/api/DefaultK8sNode.java b/apps/k8s-node/api/src/main/java/org/onosproject/k8snode/api/DefaultK8sNode.java
new file mode 100644
index 0000000..60c02b4
--- /dev/null
+++ b/apps/k8s-node/api/src/main/java/org/onosproject/k8snode/api/DefaultK8sNode.java
@@ -0,0 +1,270 @@
+/*
+ * Copyright 2019-present Open Networking Foundation
+ *
+ * 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.k8snode.api;
+
+import com.google.common.base.MoreObjects;
+import org.onlab.osgi.DefaultServiceDirectory;
+import org.onlab.packet.IpAddress;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.Port;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.device.DeviceService;
+
+import java.util.Objects;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static org.onosproject.k8snode.api.Constants.GENEVE_TUNNEL;
+import static org.onosproject.k8snode.api.Constants.GRE_TUNNEL;
+import static org.onosproject.k8snode.api.Constants.VXLAN_TUNNEL;
+import static org.onosproject.net.AnnotationKeys.PORT_NAME;
+
+/**
+ * Representation of a kubernetes node.
+ */
+public class DefaultK8sNode implements K8sNode {
+
+ private final String hostname;
+ private final Type type;
+ private final DeviceId intgBridge;
+ private final IpAddress managementIp;
+ private final IpAddress dataIp;
+ private final K8sNodeState state;
+
+ private static final String NOT_NULL_MSG = "Node % cannot be null";
+
+ private static final String OVSDB = "ovsdb:";
+
+ /**
+ * A default constructor of kubernetes Node.
+ *
+ * @param hostname hostname
+ * @param type node type
+ * @param intgBridge integration bridge
+ * @param managementIp management IP address
+ * @param dataIp data IP address
+ * @param state node state
+ */
+ protected DefaultK8sNode(String hostname, Type type, DeviceId intgBridge,
+ IpAddress managementIp, IpAddress dataIp, K8sNodeState state) {
+ this.hostname = hostname;
+ this.type = type;
+ this.intgBridge = intgBridge;
+ this.managementIp = managementIp;
+ this.dataIp = dataIp;
+ this.state = state;
+ }
+
+ @Override
+ public String hostname() {
+ return hostname;
+ }
+
+ @Override
+ public Type type() {
+ return type;
+ }
+
+ @Override
+ public DeviceId ovsdb() {
+ return DeviceId.deviceId(OVSDB + managementIp().toString());
+ }
+
+ @Override
+ public DeviceId intgBridge() {
+ return intgBridge;
+ }
+
+ @Override
+ public IpAddress managementIp() {
+ return managementIp;
+ }
+
+ @Override
+ public IpAddress dataIp() {
+ return dataIp;
+ }
+
+ @Override
+ public K8sNodeState state() {
+ return state;
+ }
+
+ @Override
+ public K8sNode updateState(K8sNodeState newState) {
+ return new Builder()
+ .hostname(hostname)
+ .type(type)
+ .intgBridge(intgBridge)
+ .managementIp(managementIp)
+ .dataIp(dataIp)
+ .state(newState)
+ .build();
+ }
+
+ @Override
+ public PortNumber grePortNum() {
+ return tunnelPortNum(GRE_TUNNEL);
+ }
+
+ @Override
+ public PortNumber vxlanPortNum() {
+ return tunnelPortNum(VXLAN_TUNNEL);
+ }
+
+ @Override
+ public PortNumber genevePortNum() {
+ return tunnelPortNum(GENEVE_TUNNEL);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+
+ if (obj instanceof DefaultK8sNode) {
+ DefaultK8sNode that = (DefaultK8sNode) obj;
+
+ return hostname.equals(that.hostname) &&
+ type == that.type &&
+ intgBridge.equals(that.intgBridge) &&
+ managementIp.equals(that.managementIp) &&
+ dataIp.equals(that.dataIp) &&
+ state == that.state;
+ }
+
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(hostname, type, intgBridge, managementIp, dataIp, state);
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("hostname", hostname)
+ .add("type", type)
+ .add("intgBridge", intgBridge)
+ .add("managementIp", managementIp)
+ .add("dataIp", dataIp)
+ .add("state", state)
+ .toString();
+ }
+
+ private PortNumber tunnelPortNum(String tunnelType) {
+ 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), tunnelType))
+ .findAny().orElse(null);
+ return port != null ? port.number() : null;
+ }
+
+ /**
+ * Returns new builder instance.
+ *
+ * @return kubernetes node builder
+ */
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ /**
+ * Returns new builder instance with the given node as a default value.
+ *
+ * @param node kubernetes node
+ * @return kubernetes node builder
+ */
+ public static Builder from(K8sNode node) {
+ return new Builder()
+ .hostname(node.hostname())
+ .type(node.type())
+ .intgBridge(node.intgBridge())
+ .managementIp(node.managementIp())
+ .dataIp(node.dataIp())
+ .state(node.state());
+ }
+
+ public static final class Builder implements K8sNode.Builder {
+
+ private String hostname;
+ private Type type;
+ private DeviceId intgBridge;
+ private IpAddress managementIp;
+ private IpAddress dataIp;
+ private K8sNodeState state;
+
+ // private constructor not intended to use from external
+ private Builder() {
+ }
+
+ @Override
+ public K8sNode build() {
+ checkArgument(hostname != null, NOT_NULL_MSG, "hostname");
+ checkArgument(type != null, NOT_NULL_MSG, "type");
+ checkArgument(state != null, NOT_NULL_MSG, "state");
+ checkArgument(managementIp != null, NOT_NULL_MSG, "management IP");
+
+ return new DefaultK8sNode(hostname,
+ type,
+ intgBridge,
+ managementIp,
+ dataIp,
+ state);
+ }
+
+ @Override
+ public Builder hostname(String hostname) {
+ this.hostname = hostname;
+ return this;
+ }
+
+ @Override
+ public Builder type(Type type) {
+ this.type = type;
+ return this;
+ }
+
+ @Override
+ public Builder intgBridge(DeviceId deviceId) {
+ this.intgBridge = deviceId;
+ 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 state(K8sNodeState state) {
+ this.state = state;
+ return this;
+ }
+ }
+}