Support to inject hostRoutes and DNS info inside DHCP reply message

Change-Id: Ic88f98b6fca88aa69a23c6a576d4d0a6ac4b8f99
diff --git a/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/codec/KubevirtNetworkCodec.java b/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/codec/KubevirtNetworkCodec.java
index c8cc377..f04106e 100644
--- a/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/codec/KubevirtNetworkCodec.java
+++ b/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/codec/KubevirtNetworkCodec.java
@@ -51,6 +51,7 @@
     private static final String CIDR = "cidr";
     private static final String HOST_ROUTES = "hostRoutes";
     private static final String IP_POOL = "ipPool";
+    private static final String DNSES = "dnses";
 
     private static final String MISSING_MESSAGE = " is required in KubevirtNetwork";
 
@@ -85,6 +86,14 @@
             result.set(IP_POOL, ipPoolJson);
         }
 
+        if (network.dnses() != null && !network.dnses().isEmpty()) {
+            ArrayNode dnses = context.mapper().createArrayNode();
+            network.dnses().forEach(dns -> {
+                dnses.add(dns.toString());
+            });
+            result.set(DNSES, dnses);
+        }
+
         return result;
     }
 
@@ -144,6 +153,19 @@
         }
         networkBuilder.hostRoutes(hostRoutes);
 
+        // parse DNSes
+        Set<IpAddress> dnses = new HashSet<>();
+        JsonNode dnsesJson = json.get(DNSES);
+        if (dnsesJson != null) {
+            for (int i = 0; i < dnsesJson.size(); i++) {
+                JsonNode dnsJson = dnsesJson.get(i);
+                if (dnsJson != null) {
+                    dnses.add(IpAddress.valueOf(dnsJson.asText()));
+                }
+            }
+        }
+        networkBuilder.dnses(dnses);
+
         log.trace("Network is {}", networkBuilder.build().toString());
 
         return networkBuilder.build();
diff --git a/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtDhcpHandler.java b/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtDhcpHandler.java
index e3b9469..983a5bb 100644
--- a/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtDhcpHandler.java
+++ b/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtDhcpHandler.java
@@ -474,28 +474,25 @@
 
             option.setCode(OptionCode_DomainServer.getValue());
 
-            option.setLength((byte) DHCP_OPTION_DNS_LENGTH);
-            ByteBuffer dnsByteBuf = ByteBuffer.allocate(DHCP_OPTION_DNS_LENGTH);
-            dnsByteBuf.put(DEFAULT_PRIMARY_DNS.toOctets());
-            dnsByteBuf.put(DEFAULT_SECONDARY_DNS.toOctets());
+            if (network.dnses().isEmpty()) {
+                option.setLength((byte) DHCP_OPTION_DNS_LENGTH);
+                ByteBuffer dnsByteBuf = ByteBuffer.allocate(DHCP_OPTION_DNS_LENGTH);
+                dnsByteBuf.put(DEFAULT_PRIMARY_DNS.toOctets());
+                dnsByteBuf.put(DEFAULT_SECONDARY_DNS.toOctets());
 
-            option.setData(dnsByteBuf.array());
+                option.setData(dnsByteBuf.array());
+            } else {
+                int dnsLength = 4 * network.dnses().size();
 
-            // TODO: need to customize the DNS server list
-//            if (dnsServers.isEmpty()) {
-//
-//            } else {
-//                int dnsLength = 4 * dnsServers.size();
-//
-//                option.setLength((byte) dnsLength);
-//
-//                ByteBuffer dnsByteBuf = ByteBuffer.allocate(DHCP_OPTION_DNS_LENGTH);
-//
-//                for (String dnsServer : dnsServers) {
-//                    dnsByteBuf.put(IpAddress.valueOf(dnsServer).toOctets());
-//                }
-//                option.setData(dnsByteBuf.array());
-//            }
+                option.setLength((byte) dnsLength);
+
+                ByteBuffer dnsByteBuf = ByteBuffer.allocate(DHCP_OPTION_DNS_LENGTH);
+
+                for (IpAddress dnsServer : network.dnses()) {
+                    dnsByteBuf.put(dnsServer.toOctets());
+                }
+                option.setData(dnsByteBuf.array());
+            }
 
             return option;
         }
diff --git a/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/NetworkAttachmentDefinitionWatcher.java b/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/NetworkAttachmentDefinitionWatcher.java
index 186ca90..93a3504 100644
--- a/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/NetworkAttachmentDefinitionWatcher.java
+++ b/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/NetworkAttachmentDefinitionWatcher.java
@@ -19,15 +19,19 @@
 import io.fabric8.kubernetes.client.Watcher;
 import io.fabric8.kubernetes.client.WatcherException;
 import io.fabric8.kubernetes.client.dsl.base.CustomResourceDefinitionContext;
+import org.apache.commons.lang.StringUtils;
+import org.json.JSONArray;
 import org.json.JSONException;
 import org.json.JSONObject;
 import org.onlab.packet.IpAddress;
+import org.onlab.packet.IpPrefix;
 import org.onosproject.cluster.ClusterService;
 import org.onosproject.cluster.LeadershipService;
 import org.onosproject.cluster.NodeId;
 import org.onosproject.core.ApplicationId;
 import org.onosproject.core.CoreService;
 import org.onosproject.kubevirtnetworking.api.DefaultKubevirtNetwork;
+import org.onosproject.kubevirtnetworking.api.KubevirtHostRoute;
 import org.onosproject.kubevirtnetworking.api.KubevirtIpPool;
 import org.onosproject.kubevirtnetworking.api.KubevirtNetwork;
 import org.onosproject.kubevirtnetworking.api.KubevirtNetwork.Type;
@@ -44,7 +48,9 @@
 import org.slf4j.Logger;
 
 import java.io.IOException;
+import java.util.HashSet;
 import java.util.Objects;
+import java.util.Set;
 import java.util.concurrent.ExecutorService;
 
 import static java.util.concurrent.Executors.newSingleThreadExecutor;
@@ -69,9 +75,12 @@
     private static final String GATEWAY_IP = "gatewayIp";
     private static final String CIDR = "cidr";
     private static final String HOST_ROUTES = "hostRoutes";
+    private static final String DESTINATION = "destination";
+    private static final String NEXTHOP = "nexthop";
     private static final String IP_POOL = "ipPool";
     private static final String START = "start";
     private static final String END = "end";
+    private static final String DNSES = "dnses";
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY)
     protected CoreService coreService;
@@ -284,6 +293,36 @@
                                 IpAddress.valueOf(start), IpAddress.valueOf(end)));
                     }
 
+                    JSONArray routesJson = configJson.getJSONArray(HOST_ROUTES);
+                    Set<KubevirtHostRoute> hostRoutes = new HashSet<>();
+                    if (routesJson != null) {
+                        for (int i = 0; i < routesJson.length(); i++) {
+                            JSONObject route = routesJson.getJSONObject(i);
+                            String destinationStr = route.getString(DESTINATION);
+                            String nexthopStr = route.getString(NEXTHOP);
+
+                            if (StringUtils.isNotEmpty(destinationStr) &&
+                                    StringUtils.isNotEmpty(nexthopStr)) {
+                                hostRoutes.add(new KubevirtHostRoute(
+                                        IpPrefix.valueOf(destinationStr),
+                                        IpAddress.valueOf(nexthopStr)));
+                            }
+                        }
+                    }
+                    builder.hostRoutes(hostRoutes);
+
+                    JSONArray dnsesJson = configJson.getJSONArray(DNSES);
+                    Set<IpAddress> dnses = new HashSet<>();
+                    if (dnsesJson != null) {
+                        for (int i = 0; i < dnsesJson.length(); i++) {
+                             String dns = dnsesJson.getString(i);
+                             if (StringUtils.isNotEmpty(dns)) {
+                                 dnses.add(IpAddress.valueOf(dns));
+                             }
+                        }
+                    }
+                    builder.dnses(dnses);
+
                     builder.networkId(name).name(name).type(Type.valueOf(type))
                             .mtu(mtu).gatewayIp(IpAddress.valueOf(gatewayIp)).cidr(cidr);
 
diff --git a/apps/kubevirt-networking/app/src/test/java/org/onosproject/kubevirtnetworking/codec/KubevirtNetworkCodecTest.java b/apps/kubevirt-networking/app/src/test/java/org/onosproject/kubevirtnetworking/codec/KubevirtNetworkCodecTest.java
index 285b190..492847a 100644
--- a/apps/kubevirt-networking/app/src/test/java/org/onosproject/kubevirtnetworking/codec/KubevirtNetworkCodecTest.java
+++ b/apps/kubevirt-networking/app/src/test/java/org/onosproject/kubevirtnetworking/codec/KubevirtNetworkCodecTest.java
@@ -100,6 +100,7 @@
                 .cidr("10.10.10.0/24")
                 .hostRoutes(ImmutableSet.of(hostRoute1, hostRoute2))
                 .ipPool(ipPool)
+                .dnses(ImmutableSet.of(IpAddress.valueOf("8.8.8.8")))
                 .build();
 
         ObjectNode networkJson = kubevirtNetworkCodec.encode(network, context);
@@ -122,6 +123,10 @@
         assertThat(network.gatewayIp().toString(), is("10.10.0.1"));
         assertThat(network.ipPool().start().toString(), is("10.10.10.100"));
         assertThat(network.ipPool().end().toString(), is("10.10.10.200"));
+        assertThat(network.dnses().size(), is(1));
+        KubevirtHostRoute route = network.hostRoutes().stream().findFirst().orElse(null);
+        assertThat(route, is(new KubevirtHostRoute(IpPrefix.valueOf("10.10.10.0/24"),
+                IpAddress.valueOf("10.10.10.1"))));
     }
 
     private KubevirtNetwork getKubevirtNetwork(String resourceName) throws IOException {
diff --git a/apps/kubevirt-networking/app/src/test/java/org/onosproject/kubevirtnetworking/codec/KubevirtNetworkJsonMatcher.java b/apps/kubevirt-networking/app/src/test/java/org/onosproject/kubevirtnetworking/codec/KubevirtNetworkJsonMatcher.java
index 215e289..4a67e07 100644
--- a/apps/kubevirt-networking/app/src/test/java/org/onosproject/kubevirtnetworking/codec/KubevirtNetworkJsonMatcher.java
+++ b/apps/kubevirt-networking/app/src/test/java/org/onosproject/kubevirtnetworking/codec/KubevirtNetworkJsonMatcher.java
@@ -18,6 +18,7 @@
 import com.fasterxml.jackson.databind.JsonNode;
 import org.hamcrest.Description;
 import org.hamcrest.TypeSafeDiagnosingMatcher;
+import org.onlab.packet.IpAddress;
 import org.onosproject.kubevirtnetworking.api.KubevirtHostRoute;
 import org.onosproject.kubevirtnetworking.api.KubevirtIpPool;
 import org.onosproject.kubevirtnetworking.api.KubevirtNetwork;
@@ -37,6 +38,7 @@
     private static final String CIDR = "cidr";
     private static final String HOST_ROUTES = "hostRoutes";
     private static final String IP_POOL = "ipPool";
+    private static final String DNSES = "dnses";
 
     private KubevirtNetworkJsonMatcher(KubevirtNetwork network) {
         this.network = network;
@@ -142,6 +144,32 @@
             }
         }
 
+        // check dnses
+        JsonNode jsonDnses = jsonNode.get(DNSES);
+        if (jsonDnses != null) {
+            if (jsonDnses.size() != network.dnses().size()) {
+                description.appendText("DNSes size was " + jsonDnses.size());
+                return false;
+            }
+
+
+            for (IpAddress dns : network.dnses()) {
+                boolean dnsFound = false;
+                for (int dnsIndex = 0; dnsIndex < jsonDnses.size(); dnsIndex++) {
+                    String jsonDns = jsonDnses.get(dnsIndex).asText();
+                    if (jsonDns.equals(dns.toString())) {
+                        dnsFound = true;
+                        break;
+                    }
+                }
+
+                if (!dnsFound) {
+                    description.appendText("DNS not found " + dns.toString());
+                    return false;
+                }
+            }
+        }
+
         return true;
     }
 
diff --git a/apps/kubevirt-networking/app/src/test/resources/org/onosproject/kubevirtnetworking/codec/KubevirtNetwork.json b/apps/kubevirt-networking/app/src/test/resources/org/onosproject/kubevirtnetworking/codec/KubevirtNetwork.json
index df048ba..afef160 100644
--- a/apps/kubevirt-networking/app/src/test/resources/org/onosproject/kubevirtnetworking/codec/KubevirtNetwork.json
+++ b/apps/kubevirt-networking/app/src/test/resources/org/onosproject/kubevirtnetworking/codec/KubevirtNetwork.json
@@ -8,5 +8,14 @@
   "ipPool": {
     "start": "10.10.10.100",
     "end": "10.10.10.200"
-  }
+  },
+  "hostRoutes": [
+    {
+      "destination": "10.10.10.0/24",
+      "nexthop": "10.10.10.1"
+    }
+  ],
+  "dnses": [
+    "8.8.8.8"
+  ]
 }
\ No newline at end of file