Add VM name field in kubevirt port object, expose via CLI and REST

Change-Id: I0ac84073fa7692862314fdf8862b4e3a256dd2d8
diff --git a/apps/kubevirt-networking/api/src/main/java/org/onosproject/kubevirtnetworking/api/DefaultKubevirtPort.java b/apps/kubevirt-networking/api/src/main/java/org/onosproject/kubevirtnetworking/api/DefaultKubevirtPort.java
index ccd35e9..493d80a 100644
--- a/apps/kubevirt-networking/api/src/main/java/org/onosproject/kubevirtnetworking/api/DefaultKubevirtPort.java
+++ b/apps/kubevirt-networking/api/src/main/java/org/onosproject/kubevirtnetworking/api/DefaultKubevirtPort.java
@@ -37,6 +37,7 @@
 
     private static final String NOT_NULL_MSG = "Port % cannot be null";
 
+    private final String vmName;
     private final String networkId;
     private final MacAddress macAddress;
     private final IpAddress ipAddress;
@@ -47,6 +48,7 @@
     /**
      * Default constructor.
      *
+     * @param vmName            VM name
      * @param networkId         network identifier
      * @param macAddress        MAC address
      * @param ipAddress         IP address
@@ -54,8 +56,9 @@
      * @param portNumber        port number
      * @param securityGroups    security groups
      */
-    public DefaultKubevirtPort(String networkId, MacAddress macAddress, IpAddress ipAddress,
+    public DefaultKubevirtPort(String vmName, String networkId, MacAddress macAddress, IpAddress ipAddress,
                                DeviceId deviceId, PortNumber portNumber, Set<String> securityGroups) {
+        this.vmName = vmName;
         this.networkId = networkId;
         this.macAddress = macAddress;
         this.ipAddress = ipAddress;
@@ -65,6 +68,11 @@
     }
 
     @Override
+    public String vmName() {
+        return vmName;
+    }
+
+    @Override
     public String networkId() {
         return networkId;
     }
@@ -122,6 +130,7 @@
     @Override
     public KubevirtPort updateIpAddress(IpAddress updateIpAddress) {
         return new Builder()
+                .vmName(vmName)
                 .networkId(networkId)
                 .macAddress(macAddress)
                 .ipAddress(updateIpAddress)
@@ -134,6 +143,7 @@
     @Override
     public KubevirtPort updatePortNumber(PortNumber updatedPortNumber) {
         return new Builder()
+                .vmName(vmName)
                 .networkId(networkId)
                 .macAddress(macAddress)
                 .ipAddress(ipAddress)
@@ -146,6 +156,7 @@
     @Override
     public KubevirtPort updateDeviceId(DeviceId updatedDeviceId) {
         return new Builder()
+                .vmName(vmName)
                 .networkId(networkId)
                 .macAddress(macAddress)
                 .ipAddress(ipAddress)
@@ -167,6 +178,7 @@
     @Override
     public KubevirtPort updateSecurityGroups(Set<String> sgs) {
         return new Builder()
+                .vmName(vmName)
                 .networkId(networkId)
                 .macAddress(macAddress)
                 .ipAddress(ipAddress)
@@ -185,19 +197,21 @@
             return false;
         }
         DefaultKubevirtPort that = (DefaultKubevirtPort) o;
-        return networkId.equals(that.networkId) && macAddress.equals(that.macAddress) &&
-                ipAddress.equals(that.ipAddress) && deviceId.equals(that.deviceId) &&
-                portNumber.equals(that.portNumber) && securityGroups.equals(that.securityGroups);
+        return vmName.equals(that.vmName) && networkId.equals(that.networkId) &&
+                macAddress.equals(that.macAddress) && ipAddress.equals(that.ipAddress) &&
+                deviceId.equals(that.deviceId) && portNumber.equals(that.portNumber) &&
+                securityGroups.equals(that.securityGroups);
     }
 
     @Override
     public int hashCode() {
-        return Objects.hash(networkId, macAddress, ipAddress, deviceId, portNumber, securityGroups);
+        return Objects.hash(vmName, networkId, macAddress, ipAddress, deviceId, portNumber, securityGroups);
     }
 
     @Override
     public String toString() {
         return MoreObjects.toStringHelper(this)
+                .add("vmName", vmName)
                 .add("networkId", networkId)
                 .add("macAddress", macAddress)
                 .add("ipAddress", ipAddress)
@@ -221,6 +235,7 @@
      */
     public static final class Builder implements KubevirtPort.Builder {
 
+        private String vmName;
         private String networkId;
         private MacAddress macAddress;
         private IpAddress ipAddress;
@@ -234,11 +249,18 @@
 
         @Override
         public KubevirtPort build() {
+            checkArgument(vmName != null, NOT_NULL_MSG, "vmName");
             checkArgument(networkId != null, NOT_NULL_MSG, "networkId");
             checkArgument(macAddress != null, NOT_NULL_MSG, "macAddress");
 
-            return new DefaultKubevirtPort(networkId, macAddress, ipAddress,
-                    deviceId, portNumber, securityGroups);
+            return new DefaultKubevirtPort(vmName, networkId, macAddress,
+                    ipAddress, deviceId, portNumber, securityGroups);
+        }
+
+        @Override
+        public KubevirtPort.Builder vmName(String vmName) {
+            this.vmName = vmName;
+            return this;
         }
 
         @Override
diff --git a/apps/kubevirt-networking/api/src/main/java/org/onosproject/kubevirtnetworking/api/KubevirtPort.java b/apps/kubevirt-networking/api/src/main/java/org/onosproject/kubevirtnetworking/api/KubevirtPort.java
index 3f19640..48c75d4 100644
--- a/apps/kubevirt-networking/api/src/main/java/org/onosproject/kubevirtnetworking/api/KubevirtPort.java
+++ b/apps/kubevirt-networking/api/src/main/java/org/onosproject/kubevirtnetworking/api/KubevirtPort.java
@@ -28,6 +28,13 @@
 public interface KubevirtPort {
 
     /**
+     * Returns the name of VM where the kubevirt port is attached.
+     *
+     * @return VM name
+     */
+    String vmName();
+
+    /**
      * Returns the network identifier associated with the port.
      *
      * @return network identifier
@@ -128,6 +135,14 @@
         KubevirtPort build();
 
         /**
+         * Returns port builder with supplied VM name.
+         *
+         * @param vmName VM name
+         * @return port builder
+         */
+        Builder vmName(String vmName);
+
+        /**
          * Returns port builder with supplied network identifier.
          *
          * @param networkId network identifier
diff --git a/apps/kubevirt-networking/api/src/test/java/org/onosproject/kubevirtnetworking/api/DefaultKubevirtInstanceTest.java b/apps/kubevirt-networking/api/src/test/java/org/onosproject/kubevirtnetworking/api/DefaultKubevirtInstanceTest.java
index c391eb4..e70afce 100644
--- a/apps/kubevirt-networking/api/src/test/java/org/onosproject/kubevirtnetworking/api/DefaultKubevirtInstanceTest.java
+++ b/apps/kubevirt-networking/api/src/test/java/org/onosproject/kubevirtnetworking/api/DefaultKubevirtInstanceTest.java
@@ -38,6 +38,8 @@
     private static final String NAME_2 = "instance-2";
     private static final String NETWORK_ID_1 = "net-1";
     private static final String NETWORK_ID_2 = "net-2";
+    private static final String VM_NAME_1 = "test-vm-1";
+    private static final String VM_NAME_2 = "test-vm-2";
     private static final MacAddress MAC_1 = MacAddress.valueOf("11:22:33:44:55:66");
     private static final MacAddress MAC_2 = MacAddress.valueOf("66:55:44:33:22:11");
     private static final IpAddress IP_1 = IpAddress.valueOf("10.10.10.10");
@@ -46,8 +48,8 @@
     private static final DeviceId DID_2 = DeviceId.deviceId("did2");
     private static final PortNumber PN_1 = PortNumber.portNumber(1);
     private static final PortNumber PN_2 = PortNumber.portNumber(2);
-    private static final KubevirtPort PORT_1 = createPort(NETWORK_ID_1, MAC_1, IP_1, DID_1, PN_1);
-    private static final KubevirtPort PORT_2 = createPort(NETWORK_ID_2, MAC_2, IP_2, DID_2, PN_2);
+    private static final KubevirtPort PORT_1 = createPort(VM_NAME_1, NETWORK_ID_1, MAC_1, IP_1, DID_1, PN_1);
+    private static final KubevirtPort PORT_2 = createPort(VM_NAME_2, NETWORK_ID_2, MAC_2, IP_2, DID_2, PN_2);
 
     private KubevirtInstance instance1;
     private KubevirtInstance sameAsInstance1;
@@ -107,9 +109,10 @@
         assertEquals(ImmutableSet.of(PORT_1), instance1.ports());
     }
 
-    static KubevirtPort createPort(String networkId, MacAddress mac, IpAddress ip,
-                                   DeviceId did, PortNumber pn) {
+    static KubevirtPort createPort(String vmName, String networkId, MacAddress mac,
+                                    IpAddress ip, DeviceId did, PortNumber pn) {
         return DefaultKubevirtPort.builder()
+                .vmName(vmName)
                 .networkId(networkId)
                 .macAddress(mac)
                 .ipAddress(ip)
diff --git a/apps/kubevirt-networking/api/src/test/java/org/onosproject/kubevirtnetworking/api/DefaultKubevirtPortTest.java b/apps/kubevirt-networking/api/src/test/java/org/onosproject/kubevirtnetworking/api/DefaultKubevirtPortTest.java
index 69b53ed..f529ca7 100644
--- a/apps/kubevirt-networking/api/src/test/java/org/onosproject/kubevirtnetworking/api/DefaultKubevirtPortTest.java
+++ b/apps/kubevirt-networking/api/src/test/java/org/onosproject/kubevirtnetworking/api/DefaultKubevirtPortTest.java
@@ -33,6 +33,8 @@
  * Unit tests for the default kubevirt port class.
  */
 public class DefaultKubevirtPortTest {
+    private static final String VM_NAME_1 = "test-vm-1";
+    private static final String VM_NAME_2 = "test-vm-2";
     private static final String NETWORK_ID_1 = "net-1";
     private static final String NETWORK_ID_2 = "net-2";
     private static final MacAddress MAC_ADDRESS_1 = MacAddress.valueOf("00:11:22:33:44:55");
@@ -64,6 +66,7 @@
     @Before
     public void setUp() {
         port1 = DefaultKubevirtPort.builder()
+                .vmName(VM_NAME_1)
                 .networkId(NETWORK_ID_1)
                 .macAddress(MAC_ADDRESS_1)
                 .ipAddress(IP_ADDRESS_1)
@@ -73,6 +76,7 @@
                 .build();
 
         sameAsPort1 = DefaultKubevirtPort.builder()
+                .vmName(VM_NAME_1)
                 .networkId(NETWORK_ID_1)
                 .macAddress(MAC_ADDRESS_1)
                 .ipAddress(IP_ADDRESS_1)
@@ -82,6 +86,7 @@
                 .build();
 
         port2 = DefaultKubevirtPort.builder()
+                .vmName(VM_NAME_2)
                 .networkId(NETWORK_ID_2)
                 .macAddress(MAC_ADDRESS_2)
                 .ipAddress(IP_ADDRESS_2)
@@ -108,6 +113,7 @@
     public void testConstruction() {
         KubevirtPort port = port1;
 
+        assertEquals(VM_NAME_1, port.vmName());
         assertEquals(NETWORK_ID_1, port.networkId());
         assertEquals(MAC_ADDRESS_1, port.macAddress());
         assertEquals(IP_ADDRESS_1, port.ipAddress());
diff --git a/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/cli/KubevirtListPortCommand.java b/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/cli/KubevirtListPortCommand.java
index 5752436..1ce747e 100644
--- a/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/cli/KubevirtListPortCommand.java
+++ b/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/cli/KubevirtListPortCommand.java
@@ -59,7 +59,7 @@
         ports.sort(Comparator.comparing(KubevirtPort::networkId));
 
         String format = genFormatString(ImmutableList.of(CLI_NAME_LENGTH,
-                CLI_MAC_ADDRESS_LENGTH, CLI_IP_ADDRESSES_LENGTH));
+                CLI_NAME_LENGTH, CLI_MAC_ADDRESS_LENGTH, CLI_IP_ADDRESSES_LENGTH));
 
         if (!Strings.isNullOrEmpty(networkId)) {
             ports.removeIf(port -> !port.networkId().equals(networkId));
@@ -68,9 +68,11 @@
         if (outputJson()) {
             print("%s", json(ports));
         } else {
-            print(format, "Network", "MAC Address", "Fixed IPs");
+            print(format, "VM Name", "Network", "MAC Address", "Fixed IPs");
             for (KubevirtPort port: ports) {
                 print(format,
+                        StringUtils.substring(port.vmName(), 0,
+                                CLI_NAME_LENGTH - CLI_MARGIN_LENGTH),
                         StringUtils.substring(port.networkId(), 0,
                                 CLI_NAME_LENGTH - CLI_MARGIN_LENGTH),
                         StringUtils.substring(port.macAddress().toString(), 0,
diff --git a/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/codec/KubevirtPortCodec.java b/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/codec/KubevirtPortCodec.java
index a388227..281855e 100644
--- a/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/codec/KubevirtPortCodec.java
+++ b/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/codec/KubevirtPortCodec.java
@@ -36,6 +36,7 @@
 
     private final Logger log = getLogger(getClass());
 
+    private static final String VM_NAME = "vmName";
     private static final String NETWORK_ID = "networkId";
     private static final String MAC_ADDRESS = "macAddress";
     private static final String IP_ADDRESS = "ipAddress";
@@ -50,6 +51,7 @@
         checkNotNull(port, "Kubevirt port cannot be null");
 
         ObjectNode result = context.mapper().createObjectNode()
+                .put(VM_NAME, port.vmName())
                 .put(NETWORK_ID, port.networkId())
                 .put(MAC_ADDRESS, port.macAddress().toString());
 
@@ -82,6 +84,9 @@
             return null;
         }
 
+        String vmName = nullIsIllegal(json.get(VM_NAME).asText(),
+                VM_NAME + MISSING_MESSAGE);
+
         String networkId = nullIsIllegal(json.get(NETWORK_ID).asText(),
                 NETWORK_ID + MISSING_MESSAGE);
 
@@ -89,6 +94,7 @@
                 MAC_ADDRESS + MISSING_MESSAGE);
 
         KubevirtPort.Builder builder = DefaultKubevirtPort.builder()
+                .vmName(vmName)
                 .networkId(networkId)
                 .macAddress(MacAddress.valueOf(macAddress));
 
diff --git a/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtVmWatcher.java b/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtVmWatcher.java
index 8f38c4a..e48bb18 100644
--- a/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtVmWatcher.java
+++ b/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtVmWatcher.java
@@ -224,8 +224,11 @@
                 return;
             }
 
+            String vmName = parseVmName(resource);
+
             parseMacAddresses(resource).forEach((mac, net) -> {
                 KubevirtPort port = DefaultKubevirtPort.builder()
+                        .vmName(vmName)
                         .macAddress(mac)
                         .networkId(net)
                         .build();
@@ -249,8 +252,11 @@
                 return;
             }
 
+            String vmName = parseVmName(resource);
+
             parseMacAddresses(resource).forEach((mac, net) -> {
                 KubevirtPort port = DefaultKubevirtPort.builder()
+                        .vmName(vmName)
                         .macAddress(mac)
                         .networkId(net)
                         .build();
@@ -288,6 +294,22 @@
             return Objects.equals(localNodeId, leadershipService.getLeader(appId.name()));
         }
 
+        private String parseVmName(String resource) {
+            String vmName = null;
+            try {
+                ObjectMapper mapper = new ObjectMapper();
+                JsonNode json = mapper.readTree(resource);
+                JsonNode nameJson = json.get(METADATA).get(NAME);
+                if (nameJson != null) {
+                    vmName = nameJson.asText();
+                }
+            } catch (IOException e) {
+                log.error("Failed to parse kubevirt VM name");
+            }
+
+            return vmName;
+        }
+
         private Map<String, IpAddress> parseIpAddresses(String resource) {
             try {
                 ObjectMapper mapper = new ObjectMapper();
diff --git a/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/util/KubevirtNetworkingUtil.java b/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/util/KubevirtNetworkingUtil.java
index a60bd0a..b49bbcc 100644
--- a/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/util/KubevirtNetworkingUtil.java
+++ b/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/util/KubevirtNetworkingUtil.java
@@ -89,9 +89,9 @@
     private static final String MAC = "mac";
     private static final String IPS = "ips";
     private static final String BR_INT = "br-int";
+    private static final String METADATA = "metadata";
     private static final String STATUS = "status";
     private static final String INTERFACES = "interfaces";
-    private static final String IP_ADDRESS = "ipAddress";
     private static final String NODE_NAME = "nodeName";
 
     /**
@@ -343,6 +343,7 @@
             JsonNode json = mapper.readTree(resource);
             JsonNode statusJson = json.get(STATUS);
             ArrayNode interfacesJson = (ArrayNode) statusJson.get(INTERFACES);
+            String vmName = parseResourceName(resource);
 
             KubevirtPort.Builder builder = DefaultKubevirtPort.builder();
             String nodeName = parseVmiNodeName(resource);
@@ -365,7 +366,8 @@
                     // FIXME: we do not update IP address, as learning IP address
                     // requires much more time due to the lag from VM agent
                     String mac = interfaceJson.get(MAC).asText();
-                    builder.macAddress(MacAddress.valueOf(mac))
+                    builder.vmName(vmName)
+                            .macAddress(MacAddress.valueOf(mac))
                             .networkId(network.networkId());
                     ports.add(builder.build());
                 }
diff --git a/apps/kubevirt-networking/app/src/test/java/org/onosproject/kubevirtnetworking/codec/KubevirtPortCodecTest.java b/apps/kubevirt-networking/app/src/test/java/org/onosproject/kubevirtnetworking/codec/KubevirtPortCodecTest.java
index e928b90..5c21a28 100644
--- a/apps/kubevirt-networking/app/src/test/java/org/onosproject/kubevirtnetworking/codec/KubevirtPortCodecTest.java
+++ b/apps/kubevirt-networking/app/src/test/java/org/onosproject/kubevirtnetworking/codec/KubevirtPortCodecTest.java
@@ -72,6 +72,7 @@
     @Test
     public void testKubevirtPortEncode() {
         KubevirtPort port = DefaultKubevirtPort.builder()
+                .vmName("test-vm-1")
                 .networkId("net-1")
                 .macAddress(MacAddress.valueOf("11:22:33:44:55:66"))
                 .ipAddress(IpAddress.valueOf("10.10.10.100"))
diff --git a/apps/kubevirt-networking/app/src/test/java/org/onosproject/kubevirtnetworking/codec/KubevirtPortJsonMatcher.java b/apps/kubevirt-networking/app/src/test/java/org/onosproject/kubevirtnetworking/codec/KubevirtPortJsonMatcher.java
index e9fa500..1fc6207 100644
--- a/apps/kubevirt-networking/app/src/test/java/org/onosproject/kubevirtnetworking/codec/KubevirtPortJsonMatcher.java
+++ b/apps/kubevirt-networking/app/src/test/java/org/onosproject/kubevirtnetworking/codec/KubevirtPortJsonMatcher.java
@@ -30,6 +30,7 @@
 
     private final KubevirtPort port;
 
+    private static final String VM_NAME = "vmName";
     private static final String NETWORK_ID = "networkId";
     private static final String MAC_ADDRESS = "macAddress";
     private static final String IP_ADDRESS = "ipAddress";
@@ -42,6 +43,14 @@
 
     @Override
     protected boolean matchesSafely(JsonNode jsonNode, Description description) {
+        // check VM name
+        String jsonVmName = jsonNode.get(VM_NAME).asText();
+        String vmName = port.vmName();
+        if (!jsonVmName.equals(vmName)) {
+            description.appendText("VM name was " + jsonVmName);
+            return false;
+        }
+
         // check network ID
         String jsonNetworkId = jsonNode.get(NETWORK_ID).asText();
         String networkId = port.networkId();
diff --git a/apps/kubevirt-networking/app/src/test/java/org/onosproject/kubevirtnetworking/impl/KubevirtPortManagerTest.java b/apps/kubevirt-networking/app/src/test/java/org/onosproject/kubevirtnetworking/impl/KubevirtPortManagerTest.java
index e6e4219..d9a9f77 100644
--- a/apps/kubevirt-networking/app/src/test/java/org/onosproject/kubevirtnetworking/impl/KubevirtPortManagerTest.java
+++ b/apps/kubevirt-networking/app/src/test/java/org/onosproject/kubevirtnetworking/impl/KubevirtPortManagerTest.java
@@ -57,6 +57,7 @@
 
     private static final String PORT_MAC = "00:11:22:33:44:55";
     private static final KubevirtPort PORT = DefaultKubevirtPort.builder()
+            .vmName("test-vm-1")
             .networkId(NETWORK_ID)
             .deviceId(DeviceId.deviceId("dev-1"))
             .ipAddress(IpAddress.valueOf("20.20.20.20"))
@@ -64,6 +65,7 @@
             .portNumber(PortNumber.portNumber("1"))
             .build();
     private static final KubevirtPort PORT_UPDATED = DefaultKubevirtPort.builder()
+            .vmName("test-vm-1")
             .networkId(UPDATED_ID)
             .deviceId(DeviceId.deviceId("dev-1"))
             .ipAddress(IpAddress.valueOf("20.20.20.20"))