Added static DHCP lease for a new host

Change-Id: Ib3c614bb008d65accec3570ff526f541b1332382
diff --git a/apps/cordvtn/pom.xml b/apps/cordvtn/pom.xml
index 1b47313..0936d89 100644
--- a/apps/cordvtn/pom.xml
+++ b/apps/cordvtn/pom.xml
@@ -45,7 +45,8 @@
         <api.package>org.onosproject.cordvtn.rest</api.package>
         <onos.app.requires>
             org.onosproject.ovsdb-base,
-            org.onosproject.openstackswitching
+            org.onosproject.openstackswitching,
+            org.onosproject.dhcp
         </onos.app.requires>
     </properties>
 
@@ -110,6 +111,11 @@
             <artifactId>onos-app-openstackswitching-api</artifactId>
             <version>${project.version}</version>
         </dependency>
+        <dependency>
+            <groupId>org.onosproject</groupId>
+            <artifactId>onos-app-dhcp-api</artifactId>
+            <version>${project.version}</version>
+        </dependency>
     </dependencies>
 
     <build>
diff --git a/apps/cordvtn/src/main/java/org/onosproject/cordvtn/CordVtn.java b/apps/cordvtn/src/main/java/org/onosproject/cordvtn/CordVtn.java
index 1dc094b..4c0bf72 100644
--- a/apps/cordvtn/src/main/java/org/onosproject/cordvtn/CordVtn.java
+++ b/apps/cordvtn/src/main/java/org/onosproject/cordvtn/CordVtn.java
@@ -15,6 +15,7 @@
  */
 package org.onosproject.cordvtn;
 
+import com.google.common.collect.Lists;
 import com.google.common.collect.Sets;
 import org.apache.felix.scr.annotations.Activate;
 import org.apache.felix.scr.annotations.Component;
@@ -23,11 +24,13 @@
 import org.apache.felix.scr.annotations.ReferenceCardinality;
 import org.apache.felix.scr.annotations.Service;
 import org.onlab.packet.Ethernet;
+import org.onlab.packet.Ip4Address;
 import org.onlab.packet.IpAddress;
 import org.onlab.packet.MacAddress;
 import org.onlab.packet.VlanId;
 import org.onosproject.core.ApplicationId;
 import org.onosproject.core.CoreService;
+import org.onosproject.dhcp.DhcpService;
 import org.onosproject.mastership.MastershipService;
 import org.onosproject.net.ConnectPoint;
 import org.onosproject.net.DefaultAnnotations;
@@ -65,6 +68,7 @@
 import org.onosproject.openstackswitching.OpenstackSwitchingService;
 import org.slf4j.Logger;
 
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.ExecutorService;
@@ -121,6 +125,9 @@
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected OpenstackSwitchingService openstackService;
 
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected DhcpService dhcpService;
+
     private final ConfigFactory configFactory =
             new ConfigFactory(SubjectFactories.APP_SUBJECT_FACTORY, CordVtnConfig.class, "cordvtn") {
                 @Override
@@ -130,6 +137,7 @@
             };
 
     private static final String DEFAULT_TUNNEL = "vxlan";
+    private static final Ip4Address DEFAULT_DNS = Ip4Address.valueOf("8.8.8.8");
     private static final String SERVICE_ID = "serviceId";
     private static final String LOCATION_IP = "locationIp";
     private static final String OPENSTACK_VM_ID = "openstackVmId";
@@ -244,9 +252,13 @@
         if (host != null) {
             // Host is already known to the system, no HOST_ADDED event is triggered in this case.
             // It happens when the application is restarted.
-            // TODO check host description if it has all the information
-            serviceVmAdded(host);
-            return;
+            String vmId = host.annotations().value(OPENSTACK_VM_ID);
+            if (vmId != null && vmId.equals(vPort.deviceId())) {
+                serviceVmAdded(host);
+                return;
+            } else {
+                hostProvider.hostVanished(host.id());
+            }
         }
 
         Set<IpAddress> ip = Sets.newHashSet(vPort.fixedIps().values());
@@ -382,6 +394,26 @@
     }
 
     /**
+     * Registers static DHCP lease for a given host.
+     *
+     * @param host host
+     * @param service cord service
+     */
+    private void registerDhcpLease(Host host, CordService service) {
+        List<Ip4Address> options = Lists.newArrayList();
+        options.add(Ip4Address.makeMaskPrefix(service.serviceIpRange().prefixLength()));
+        options.add(service.serviceIp().getIp4Address());
+        options.add(service.serviceIp().getIp4Address());
+        options.add(DEFAULT_DNS);
+
+        log.debug("Set static DHCP mapping for {}", host.mac());
+        dhcpService.setStaticMapping(host.mac(),
+                                     host.ipAddresses().stream().findFirst().get().getIp4Address(),
+                                     true,
+                                     options);
+    }
+
+    /**
      * Handles VM detected situation.
      *
      * @param host host
@@ -420,6 +452,7 @@
         }
 
         ruleInstaller.populateBasicConnectionRules(host, getTunnelIp(host), vNet);
+        registerDhcpLease(host, service);
     }
 
     /**
@@ -428,6 +461,11 @@
      * @param host host
      */
     private void serviceVmRemoved(Host host) {
+        if (host.annotations().value(OPENSTACK_VM_ID) == null) {
+            // this host was not injected from CordVtn, just return
+            return;
+        }
+
         String vNetId = host.annotations().value(SERVICE_ID);
         OpenstackNetwork vNet = openstackService.network(host.annotations().value(SERVICE_ID));
         if (vNet == null) {