Use openstack4j for OpenStack data model and rest client

Change-Id: I4eb52c3c82d847c442420d1287392fe9079bf699
diff --git a/apps/cordvtn/app.xml b/apps/cordvtn/app.xml
index 11e78cb..5163375 100644
--- a/apps/cordvtn/app.xml
+++ b/apps/cordvtn/app.xml
@@ -18,7 +18,7 @@
         category="Traffic Steering" url="http://onosproject.org" title="CORD Virtual Tenant Network"
         featuresRepo="mvn:${project.groupId}/${project.artifactId}/${project.version}/xml/features"
         features="${project.artifactId}"
-        apps="org.onosproject.ovsdb-base,org.onosproject.openstackinterface,org.onosproject.dhcp">
+        apps="org.onosproject.ovsdb-base,org.onosproject.dhcp">
     <description>${project.description}</description>
     <artifact>mvn:${project.groupId}/onos-app-cordvtn/${project.version}</artifact>
 </app>
diff --git a/apps/cordvtn/features.xml b/apps/cordvtn/features.xml
index 1425b03..7bd3c66 100644
--- a/apps/cordvtn/features.xml
+++ b/apps/cordvtn/features.xml
@@ -19,5 +19,6 @@
         <feature>onos-api</feature>
         <bundle>mvn:${project.groupId}/onos-app-cordvtn/${project.version}</bundle>
         <bundle>wrap:mvn:com.jcraft/jsch/0.1.53$Bundle-SymbolicName=jsch&amp;Bundle-Version=0.1.53</bundle>
+        <bundle>wrap:mvn:org.pacesys/openstack4j/2.11/jar/withdeps$Bundle-SymbolicName=openstack4j&amp;Bundle-Version=2.11</bundle>
     </feature>
 </features>
diff --git a/apps/cordvtn/pom.xml b/apps/cordvtn/pom.xml
index 148f47c..851714b 100644
--- a/apps/cordvtn/pom.xml
+++ b/apps/cordvtn/pom.xml
@@ -112,6 +112,21 @@
             <artifactId>jsch</artifactId>
             <version>0.1.53</version>
         </dependency>
+        <dependency>
+            <groupId>org.pacesys</groupId>
+            <artifactId>openstack4j-core</artifactId>
+            <version>2.11</version>
+        </dependency>
+        <dependency>
+            <groupId>org.pacesys.openstack4j.connectors</groupId>
+            <artifactId>openstack4j-http-connector</artifactId>
+            <version>2.11</version>
+        </dependency>
+        <dependency>
+            <groupId>org.pacesys.openstack4j.connectors</groupId>
+            <artifactId>openstack4j-httpclient</artifactId>
+            <version>2.11</version>
+        </dependency>
     </dependencies>
 
     <build>
@@ -131,8 +146,14 @@
                             ${project.groupId}.${project.artifactId}
                         </Bundle-SymbolicName>
                         <Import-Package>
+                            !org.apache.http.*,
                             *,org.glassfish.jersey.servlet
                         </Import-Package>
+                        <Embed-Dependency>
+                            openstack4j-core,
+                            openstack4j-http-connector,
+                            openstack4j-httpclient
+                        </Embed-Dependency>
                         <Web-ContextPath>${web.context}</Web-ContextPath>
                     </instructions>
                 </configuration>
diff --git a/apps/cordvtn/src/main/java/org/onosproject/cordvtn/api/CordService.java b/apps/cordvtn/src/main/java/org/onosproject/cordvtn/api/CordService.java
index b6fa9b0..8a10015 100644
--- a/apps/cordvtn/src/main/java/org/onosproject/cordvtn/api/CordService.java
+++ b/apps/cordvtn/src/main/java/org/onosproject/cordvtn/api/CordService.java
@@ -19,8 +19,8 @@
 import org.onlab.packet.IpAddress;
 import org.onlab.packet.IpPrefix;
 import org.onosproject.net.Host;
-import org.onosproject.openstackinterface.OpenstackNetwork;
-import org.onosproject.openstackinterface.OpenstackSubnet;
+import org.openstack4j.model.network.Network;
+import org.openstack4j.model.network.Subnet;
 
 import java.util.Map;
 import java.util.Objects;
@@ -47,18 +47,18 @@
     /**
      * Default constructor.
      *
-     * @param vNet OpenStack network
-     * @param subnet OpenStack subnet
+     * @param osNet OpenStack network
+     * @param osSubnet OpenStack subnet
      * @param hosts host and tunnel ip map
      * @param tenantServices list of tenant service ids
      */
-    public CordService(OpenstackNetwork vNet, OpenstackSubnet subnet,
+    public CordService(Network osNet, Subnet osSubnet,
                        Map<Host, IpAddress> hosts, Set<CordServiceId> tenantServices) {
-        this.id = CordServiceId.of(vNet.id());
-        this.segmentationId = Long.parseLong(vNet.segmentId());
-        this.serviceType = getServiceType(vNet.name());
-        this.serviceIpRange = IpPrefix.valueOf(subnet.cidr());
-        this.serviceIp = IpAddress.valueOf(subnet.gatewayIp());
+        this.id = CordServiceId.of(osNet.getId());
+        this.segmentationId = Long.parseLong(osNet.getProviderSegID());
+        this.serviceType = getServiceType(osNet.getName());
+        this.serviceIpRange = IpPrefix.valueOf(osSubnet.getCidr());
+        this.serviceIp = IpAddress.valueOf(osSubnet.getGateway());
         this.hosts = hosts;
         this.tenantServices = tenantServices;
     }
diff --git a/apps/cordvtn/src/main/java/org/onosproject/cordvtn/api/CordVtnConfig.java b/apps/cordvtn/src/main/java/org/onosproject/cordvtn/api/CordVtnConfig.java
index 008012e..2c48ba3 100644
--- a/apps/cordvtn/src/main/java/org/onosproject/cordvtn/api/CordVtnConfig.java
+++ b/apps/cordvtn/src/main/java/org/onosproject/cordvtn/api/CordVtnConfig.java
@@ -46,10 +46,6 @@
     public static final String LOCAL_MANAGEMENT_IP = "localManagementIp";
     public static final String OVSDB_PORT = "ovsdbPort";
 
-    public static final String SSH_PORT = "sshPort";
-    public static final String SSH_USER = "sshUser";
-    public static final String SSH_KEY_FILE = "sshKeyFile";
-
     public static final String CORDVTN_NODES = "nodes";
     public static final String HOSTNAME = "hostname";
     public static final String HOST_MANAGEMENT_IP = "hostManagementIp";
@@ -57,6 +53,17 @@
     public static final String DATA_PLANE_INTF = "dataPlaneIntf";
     public static final String BRIDGE_ID = "bridgeId";
 
+    public static final String SSH = "ssh";
+    public static final String SSH_PORT = "sshPort";
+    public static final String SSH_USER = "sshUser";
+    public static final String SSH_KEY_FILE = "sshKeyFile";
+
+    public static final String OPENSTACK = "openstack";
+    public static final String OPENSTACK_ENDPOINT = "endpoint";
+    public static final String OPENSTACK_TENANT = "tenant";
+    public static final String OPENSTACK_USER = "user";
+    public static final String OPENSTACK_PASSWORD = "password";
+
     /**
      * Returns the set of nodes read from network config.
      *
@@ -65,15 +72,22 @@
     public Set<CordVtnNode> cordVtnNodes() {
 
         Set<CordVtnNode> nodes = Sets.newHashSet();
-        JsonNode jsonNodes = object.get(CORDVTN_NODES);
-        if (jsonNodes == null) {
+
+        JsonNode cordvtnNodes = object.get(CORDVTN_NODES);
+        if (cordvtnNodes == null) {
             log.debug("No CORD VTN nodes found");
             return nodes;
         }
 
-        for (JsonNode jsonNode : jsonNodes) {
+        JsonNode sshNode = object.get(SSH);
+        if (sshNode == null) {
+            log.warn("SSH information not found");
+            return nodes;
+        }
+
+        for (JsonNode cordvtnNode : cordvtnNodes) {
             try {
-                NetworkAddress hostMgmt = NetworkAddress.valueOf(getConfig(jsonNode, HOST_MANAGEMENT_IP));
+                NetworkAddress hostMgmt = NetworkAddress.valueOf(getConfig(cordvtnNode, HOST_MANAGEMENT_IP));
                 NetworkAddress localMgmt = NetworkAddress.valueOf(getConfig(object, LOCAL_MANAGEMENT_IP));
                 if (hostMgmt.prefix().contains(localMgmt.prefix()) ||
                         localMgmt.prefix().contains(hostMgmt.prefix())) {
@@ -84,22 +98,22 @@
                 Ip4Address hostMgmtIp = hostMgmt.ip().getIp4Address();
                 SshAccessInfo sshInfo = new SshAccessInfo(
                         hostMgmtIp,
-                        TpPort.tpPort(Integer.parseInt(getConfig(object, SSH_PORT))),
-                        getConfig(object, SSH_USER), getConfig(object, SSH_KEY_FILE));
+                        TpPort.tpPort(Integer.parseInt(getConfig(sshNode, SSH_PORT))),
+                        getConfig(sshNode, SSH_USER), getConfig(sshNode, SSH_KEY_FILE));
 
-                String hostname = getConfig(jsonNode, HOSTNAME);
+                String hostname = getConfig(cordvtnNode, HOSTNAME);
                 CordVtnNode newNode = new CordVtnNode(
                         hostname, hostMgmt, localMgmt,
-                        NetworkAddress.valueOf(getConfig(jsonNode, DATA_PLANE_IP)),
+                        NetworkAddress.valueOf(getConfig(cordvtnNode, DATA_PLANE_IP)),
                         TpPort.tpPort(Integer.parseInt(getConfig(object, OVSDB_PORT))),
                         sshInfo,
-                        DeviceId.deviceId(getConfig(jsonNode, BRIDGE_ID)),
-                        getConfig(jsonNode, DATA_PLANE_INTF),
+                        DeviceId.deviceId(getConfig(cordvtnNode, BRIDGE_ID)),
+                        getConfig(cordvtnNode, DATA_PLANE_INTF),
                         CordVtnNodeState.noState());
 
                 nodes.add(newNode);
             } catch (IllegalArgumentException | NullPointerException e) {
-                log.error("{}", e.toString());
+                log.error("{}", e);
             }
         }
 
@@ -167,5 +181,90 @@
 
         return publicGateways;
     }
-}
 
+    /**
+     * Returns OpenStack API access information.
+     *
+     * @return openstack config
+     */
+    public OpenStackConfig openstackConfig() {
+        JsonNode jsonNode = object.get(OPENSTACK);
+        if (jsonNode == null) {
+            log.error("Failed to get OpenStack configurations");
+            return null;
+        }
+
+        try {
+            return new OpenStackConfig(
+                    jsonNode.path(OPENSTACK_ENDPOINT).asText(),
+                    jsonNode.path(OPENSTACK_TENANT).asText(),
+                    jsonNode.path(OPENSTACK_USER).asText(),
+                    jsonNode.path(OPENSTACK_PASSWORD).asText());
+        } catch (IllegalArgumentException | NullPointerException e) {
+            log.error("Failed to get OpenStack configurations");
+            return null;
+        }
+    }
+
+    /**
+     * Configuration for OpenStack API access.
+     */
+    public static class OpenStackConfig {
+
+        private final String endpoint;
+        private final String tenant;
+        private final String user;
+        private final String password;
+
+        /**
+         * Default constructor.
+         *
+         * @param endpoint Keystone endpoint
+         * @param tenant tenant name
+         * @param user user name
+         * @param password passwowrd
+         */
+        public OpenStackConfig(String endpoint, String tenant, String user, String password) {
+            this.endpoint = endpoint;
+            this.tenant = tenant;
+            this.user = user;
+            this.password = password;
+        }
+
+        /**
+         * Returns OpenStack API endpoint.
+         *
+         * @return endpoint
+         */
+        public String endpoint() {
+            return this.endpoint;
+        }
+
+        /**
+         * Returns OpenStack tenant name.
+         *
+         * @return tenant name
+         */
+        public String tenant() {
+            return this.tenant;
+        }
+
+        /**
+         * Returns OpenStack user.
+         *
+         * @return user name
+         */
+        public String user() {
+            return this.user;
+        }
+
+        /**
+         * Returns OpenStack password for the user.
+         *
+         * @return password
+         */
+        public String password() {
+            return this.password;
+        }
+    }
+}
diff --git a/apps/cordvtn/src/main/java/org/onosproject/cordvtn/impl/CordVtn.java b/apps/cordvtn/src/main/java/org/onosproject/cordvtn/impl/CordVtn.java
index 967ca02..24f650d 100644
--- a/apps/cordvtn/src/main/java/org/onosproject/cordvtn/impl/CordVtn.java
+++ b/apps/cordvtn/src/main/java/org/onosproject/cordvtn/impl/CordVtn.java
@@ -67,10 +67,13 @@
 import org.onosproject.net.packet.PacketService;
 import org.onosproject.net.provider.AbstractProvider;
 import org.onosproject.net.provider.ProviderId;
-import org.onosproject.openstackinterface.OpenstackInterfaceService;
-import org.onosproject.openstackinterface.OpenstackNetwork;
-import org.onosproject.openstackinterface.OpenstackPort;
-import org.onosproject.openstackinterface.OpenstackSubnet;
+
+import org.openstack4j.api.OSClient;
+import org.openstack4j.api.exceptions.AuthenticationException;
+import org.openstack4j.model.identity.Access;
+import org.openstack4j.model.network.Network;
+import org.openstack4j.model.network.Subnet;
+import org.openstack4j.openstack.OSFactory;
 import org.slf4j.Logger;
 
 import java.util.List;
@@ -130,9 +133,6 @@
     protected GroupService groupService;
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    protected OpenstackInterfaceService openstackService;
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected DhcpService dhcpService;
 
     private final ConfigFactory configFactory =
@@ -165,6 +165,8 @@
     private HostProviderService hostProvider;
     private CordVtnRuleInstaller ruleInstaller;
     private CordVtnArpProxy arpProxy;
+
+    private volatile Access osAccess = null;
     private volatile MacAddress privateGatewayMac = MacAddress.NONE;
 
     /**
@@ -250,20 +252,26 @@
 
     @Override
     public void addServiceVm(CordVtnNode node, ConnectPoint connectPoint) {
+        checkNotNull(osAccess, "OpenStack access is not set");
+
+        OSClient osClient = OSFactory.clientFromAccess(osAccess);
         Port port = deviceService.getPort(connectPoint.deviceId(), connectPoint.port());
-        OpenstackPort vPort = openstackService.port(port);
-        if (vPort == null) {
-            log.warn("Failed to get OpenstackPort for {}", getPortName(port));
+        org.openstack4j.model.network.Port osPort = osClient.networking().port().list()
+                .stream()
+                .filter(p -> p.getId().contains(getPortName(port).substring(3)))
+                .findFirst().orElse(null);
+        if (osPort == null) {
+            log.warn("Failed to get OpenStack port for {}", getPortName(port));
             return;
         }
 
-        MacAddress mac = vPort.macAddress();
+        MacAddress mac = MacAddress.valueOf(osPort.getMacAddress());
         HostId hostId = HostId.hostId(mac);
 
         Host existingHost = hostService.getHost(hostId);
         if (existingHost != null) {
             String serviceId = existingHost.annotations().value(SERVICE_ID);
-            if (serviceId == null || !serviceId.equals(vPort.networkId())) {
+            if (serviceId == null || !serviceId.equals(osPort.getNetworkId())) {
                 // this host is not injected by cordvtn or a stale host, remove it
                 hostProvider.hostVanished(existingHost.id());
             }
@@ -273,15 +281,18 @@
         // event so that the flow rule population for this host can happen.
         // This ensures refreshing data plane by pushing network config always make
         // the data plane synced.
-        Set<IpAddress> fixedIp = Sets.newHashSet(vPort.fixedIps().values());
+        Set<IpAddress> fixedIps = osPort.getFixedIps().stream()
+                .map(ip -> IpAddress.valueOf(ip.getIpAddress()))
+                .collect(Collectors.toSet());
+
         DefaultAnnotations.Builder annotations = DefaultAnnotations.builder()
-                .set(SERVICE_ID, vPort.networkId())
-                .set(OPENSTACK_PORT_ID, vPort.id())
+                .set(SERVICE_ID, osPort.getNetworkId())
+                .set(OPENSTACK_PORT_ID, osPort.getId())
                 .set(DATA_PLANE_IP, node.dpIp().ip().toString())
                 .set(DATA_PLANE_INTF, node.dpIntf())
                 .set(CREATED_TIME, String.valueOf(System.currentTimeMillis()));
 
-        String serviceVlan = getServiceVlan(vPort);
+        String serviceVlan = getServiceVlan(osPort);
         if (serviceVlan != null) {
             annotations.set(S_TAG, serviceVlan);
         }
@@ -290,7 +301,7 @@
                 mac,
                 VlanId.NONE,
                 new HostLocation(connectPoint, System.currentTimeMillis()),
-                fixedIp,
+                fixedIps,
                 annotations.build());
 
         hostProvider.hostDetected(hostId, hostDesc, false);
@@ -365,21 +376,30 @@
      * @return map of ip and mac address, or empty map
      */
     private Map<IpAddress, MacAddress> getSubscriberGateways(Host vSgHost) {
-        String vPortId = vSgHost.annotations().value(OPENSTACK_PORT_ID);
+        checkNotNull(osAccess, "OpenStack access is not set");
+
+        String osPortId = vSgHost.annotations().value(OPENSTACK_PORT_ID);
         String serviceVlan = vSgHost.annotations().value(S_TAG);
 
-        OpenstackPort vPort = openstackService.port(vPortId);
-        if (vPort == null) {
-            log.warn("Failed to get OpenStack port {} for VM {}", vPortId, vSgHost.id());
+        OSClient osClient = OSFactory.clientFromAccess(osAccess);
+        org.openstack4j.model.network.Port osPort = osClient.networking().port().get(osPortId);
+        if (osPort == null) {
+            log.warn("Failed to get OpenStack port {} for VM {}", osPortId, vSgHost.id());
             return Maps.newHashMap();
         }
 
-        if (!serviceVlan.equals(getServiceVlan(vPort))) {
-            log.error("Host({}) s-tag does not match with vPort s-tag", vSgHost.id());
+        if (!serviceVlan.equals(getServiceVlan(osPort))) {
+            log.error("Host({}) s-tag does not match with OpenStack port s-tag", vSgHost.id());
             return Maps.newHashMap();
         }
 
-        return vPort.allowedAddressPairs();
+        Map<IpAddress, MacAddress> addressPairs = Maps.newHashMap();
+        osPort.getAllowedAddressPairs()
+                .stream().forEach(p -> addressPairs.put(
+                IpAddress.valueOf(p.getIpAddress()),
+                MacAddress.valueOf(p.getMacAddress())));
+
+        return addressPairs;
     }
 
     /**
@@ -389,16 +409,20 @@
      * @return cord service, or null if it fails to get network from OpenStack
      */
     private CordService getCordService(CordServiceId serviceId) {
-        OpenstackNetwork vNet = openstackService.network(serviceId.id());
-        if (vNet == null) {
+        checkNotNull(osAccess, "OpenStack access is not set");
+
+        OSClient osClient = OSFactory.clientFromAccess(osAccess);
+        Network osNet = osClient.networking().network().get(serviceId.id());
+        if (osNet == null) {
             log.warn("Couldn't find OpenStack network for service {}", serviceId.id());
             return null;
         }
 
-        OpenstackSubnet subnet = vNet.subnets().stream()
+        // here it assumes all cord service networks has only one subnet
+        Subnet osSubnet = osNet.getNeutronSubnets().stream()
                 .findFirst()
                 .orElse(null);
-        if (subnet == null) {
+        if (osSubnet == null) {
             log.warn("Couldn't find OpenStack subnet for service {}", serviceId.id());
             return null;
         }
@@ -406,39 +430,40 @@
         Set<CordServiceId> tServices = Sets.newHashSet();
         // TODO get tenant services from XOS
 
-        Map<Host, IpAddress> hosts = getHostsWithOpenstackNetwork(vNet)
+        Map<Host, IpAddress> hosts = getHostsWithOpenstackNetwork(osNet)
                 .stream()
                 .collect(Collectors.toMap(host -> host, this::getTunnelIp));
 
-        return new CordService(vNet, subnet, hosts, tServices);
+        return new CordService(osNet, osSubnet, hosts, tServices);
     }
 
     /**
      * Returns CordService by OpenStack network.
      *
-     * @param vNet OpenStack network
+     * @param osNet OpenStack network
      * @return cord service
      */
-    private CordService getCordService(OpenstackNetwork vNet) {
-        checkNotNull(vNet);
+    private CordService getCordService(Network osNet) {
+        checkNotNull(osNet);
 
-        CordServiceId serviceId = CordServiceId.of(vNet.id());
-        OpenstackSubnet subnet = vNet.subnets().stream()
+        CordServiceId serviceId = CordServiceId.of(osNet.getId());
+        // here it assumes all cord service networks has only one subnet
+        Subnet osSubnet = osNet.getNeutronSubnets().stream()
                 .findFirst()
                 .orElse(null);
-        if (subnet == null) {
-            log.warn("Couldn't find OpenStack subnet for service {}", serviceId);
+        if (osSubnet == null) {
+            log.warn("Couldn't find OpenStack subnet for service {}", serviceId.id());
             return null;
         }
 
         Set<CordServiceId> tServices = Sets.newHashSet();
         // TODO get tenant services from XOS
 
-        Map<Host, IpAddress> hosts = getHostsWithOpenstackNetwork(vNet)
+        Map<Host, IpAddress> hosts = getHostsWithOpenstackNetwork(osNet)
                 .stream()
                 .collect(Collectors.toMap(host -> host, this::getTunnelIp));
 
-        return new CordService(vNet, subnet, hosts, tServices);
+        return new CordService(osNet, osSubnet, hosts, tServices);
     }
 
     /**
@@ -465,14 +490,15 @@
     /**
      * Returns s-tag from a given OpenStack port.
      *
-     * @param vPort openstack port
+     * @param osPort openstack port
      * @return s-tag string
      */
-    private String getServiceVlan(OpenstackPort vPort) {
-        checkNotNull(vPort);
+    private String getServiceVlan(org.openstack4j.model.network.Port osPort) {
+        checkNotNull(osPort);
 
-        if (vPort.name() != null && vPort.name().startsWith(S_TAG)) {
-            return vPort.name().split("-")[1];
+        String portName = osPort.getName();
+        if (portName != null && portName.startsWith(S_TAG)) {
+            return portName.split("-")[1];
         } else {
             return null;
         }
@@ -491,15 +517,15 @@
     /**
      * Returns hosts associated with a given OpenStack network.
      *
-     * @param vNet openstack network
+     * @param osNet openstack network
      * @return set of hosts
      */
-    private Set<Host> getHostsWithOpenstackNetwork(OpenstackNetwork vNet) {
-        checkNotNull(vNet);
+    private Set<Host> getHostsWithOpenstackNetwork(Network osNet) {
+        checkNotNull(osNet);
 
-        String vNetId = vNet.id();
+        String osNetId = osNet.getId();
         return StreamSupport.stream(hostService.getHosts().spliterator(), false)
-                .filter(host -> Objects.equals(vNetId, getServiceId(host)))
+                .filter(host -> Objects.equals(osNetId, getServiceId(host)))
                 .collect(Collectors.toSet());
     }
 
@@ -529,21 +555,24 @@
      * @param host host
      */
     private void serviceVmAdded(Host host) {
+        checkNotNull(osAccess, "OpenStack access is not set");
+
         String serviceVlan = host.annotations().value(S_TAG);
         if (serviceVlan != null) {
             virtualSubscriberGatewayAdded(host, serviceVlan);
         }
 
-        String vNetId = host.annotations().value(SERVICE_ID);
-        if (vNetId == null) {
+        String osNetId = host.annotations().value(SERVICE_ID);
+        if (osNetId == null) {
             // ignore this host, it is not the service VM, or it's a vSG
             return;
         }
 
-        OpenstackNetwork vNet = openstackService.network(vNetId);
-        if (vNet == null) {
+        OSClient osClient = OSFactory.clientFromAccess(osAccess);
+        Network osNet = osClient.networking().network().get(osNetId);
+        if (osNet == null) {
             log.warn("Failed to get OpenStack network {} for VM {}.",
-                     vNetId, host.id());
+                     osNetId, host.id());
             return;
         }
 
@@ -551,7 +580,7 @@
                  host.mac(),
                  host.ipAddresses().stream().findFirst().get());
 
-        CordService service = getCordService(vNet);
+        CordService service = getCordService(osNet);
         if (service == null) {
             return;
         }
@@ -573,7 +602,7 @@
         }
 
         registerDhcpLease(host, service);
-        ruleInstaller.populateBasicConnectionRules(host, getTunnelIp(host), vNet);
+        ruleInstaller.populateBasicConnectionRules(host, getTunnelIp(host), osNet);
     }
 
     /**
@@ -582,21 +611,24 @@
      * @param host host
      */
     private void serviceVmRemoved(Host host) {
+        checkNotNull(osAccess, "OpenStack access is not set");
+
         String serviceVlan = host.annotations().value(S_TAG);
         if (serviceVlan != null) {
             virtualSubscriberGatewayRemoved(host);
         }
 
-        String vNetId = host.annotations().value(SERVICE_ID);
-        if (vNetId == null) {
+        String osNetId = host.annotations().value(SERVICE_ID);
+        if (osNetId == null) {
             // ignore it, it's not the service VM or it's a vSG
             return;
         }
 
-        OpenstackNetwork vNet = openstackService.network(vNetId);
-        if (vNet == null) {
+        OSClient osClient = OSFactory.clientFromAccess(osAccess);
+        Network osNet = osClient.networking().network().get(osNetId);
+        if (osNet == null) {
             log.warn("Failed to get OpenStack network {} for VM {}",
-                     vNetId, host.id());
+                     osNetId, host.id());
             return;
         }
 
@@ -607,7 +639,7 @@
         ruleInstaller.removeBasicConnectionRules(host);
         dhcpService.removeStaticMapping(host.mac());
 
-        CordService service = getCordService(vNet);
+        CordService service = getCordService(osNet);
         if (service == null) {
             return;
         }
@@ -617,7 +649,7 @@
                 ruleInstaller.removeManagementNetworkRules(host, service);
                 break;
             case PRIVATE:
-                if (getHostsWithOpenstackNetwork(vNet).isEmpty()) {
+                if (getHostsWithOpenstackNetwork(osNet).isEmpty()) {
                     arpProxy.removeGateway(service.serviceIp());
                 }
             case PUBLIC:
@@ -723,13 +755,38 @@
                 .stream()
                 .forEach(entry -> {
                     arpProxy.addGateway(entry.getKey(), entry.getValue());
-                    log.info("Added public gateway IP {}, MAC {}",
-                             entry.getKey().toString(), entry.getValue().toString());
+                    log.debug("Added public gateway IP {}, MAC {}",
+                              entry.getKey().toString(), entry.getValue().toString());
                 });
         // TODO notice gateway MAC change to VMs holds this gateway IP
     }
 
     /**
+     * Sets OpenStack access information.
+     * Access is the entity returned when authenticated and provides a singleton client
+     * between multiple threads.
+     *
+     * @param osConfig openstack config
+     */
+    private void setOpenstackAccess(CordVtnConfig.OpenStackConfig osConfig) {
+        log.debug("Get OpenStack access with Endpoint: {} Tenant: {} User: {} Passwd: {}",
+                  osConfig.endpoint(),
+                  osConfig.tenant(),
+                  osConfig.user(),
+                  osConfig.password());
+        try {
+            osAccess = OSFactory.builder()
+                    .endpoint(osConfig.endpoint())
+                    .credentials(osConfig.user(), osConfig.password())
+                    .tenantName(osConfig.tenant())
+                    .authenticate()
+                    .getAccess();
+        } catch (AuthenticationException e) {
+            log.error("Failed to get OpenStack Access");
+        }
+    }
+
+    /**
      * Updates configurations.
      */
     private void readConfiguration() {
@@ -739,9 +796,10 @@
             return;
         }
 
+        setOpenstackAccess(config.openstackConfig());
         setPrivateGatewayMac(config.privateGatewayMac());
         setPublicGatewayMac(config.publicGateways());
-   }
+    }
 
     private class InternalHostListener implements HostListener {
 
diff --git a/apps/cordvtn/src/main/java/org/onosproject/cordvtn/impl/CordVtnRuleInstaller.java b/apps/cordvtn/src/main/java/org/onosproject/cordvtn/impl/CordVtnRuleInstaller.java
index 8652e18..49f3c8f 100644
--- a/apps/cordvtn/src/main/java/org/onosproject/cordvtn/impl/CordVtnRuleInstaller.java
+++ b/apps/cordvtn/src/main/java/org/onosproject/cordvtn/impl/CordVtnRuleInstaller.java
@@ -75,8 +75,8 @@
 import org.onosproject.net.group.GroupDescription;
 import org.onosproject.net.group.GroupKey;
 import org.onosproject.net.group.GroupService;
-import org.onosproject.openstackinterface.OpenstackNetwork;
-import org.onosproject.openstackinterface.OpenstackSubnet;
+import org.openstack4j.model.network.Network;
+import org.openstack4j.model.network.Subnet;
 import org.slf4j.Logger;
 
 import java.util.ArrayList;
@@ -190,30 +190,31 @@
      *
      * @param host host
      * @param tunnelIp tunnel ip
-     * @param vNet openstack network
+     * @param osNet openstack network
      */
-    public void populateBasicConnectionRules(Host host, IpAddress tunnelIp, OpenstackNetwork vNet) {
+    public void populateBasicConnectionRules(Host host, IpAddress tunnelIp, Network osNet) {
         checkNotNull(host);
-        checkNotNull(vNet);
+        checkNotNull(osNet);
 
         DeviceId deviceId = host.location().deviceId();
         PortNumber inPort = host.location().port();
         MacAddress dstMac = host.mac();
         IpAddress hostIp = host.ipAddresses().stream().findFirst().get();
-        long tunnelId = Long.parseLong(vNet.segmentId());
+        long tunnelId = Long.parseLong(osNet.getProviderSegID());
 
-        OpenstackSubnet subnet = vNet.subnets().stream()
+        Subnet osSubnet = osNet.getNeutronSubnets().stream()
                 .findFirst()
                 .orElse(null);
 
-        if (subnet == null) {
+        if (osSubnet == null) {
             log.error("Failed to get subnet for {}", host.id());
             return;
         }
+        Ip4Prefix cidr = Ip4Prefix.valueOf(osSubnet.getCidr());
 
         populateLocalInPortRule(deviceId, inPort, hostIp);
-        populateDirectAccessRule(Ip4Prefix.valueOf(subnet.cidr()), Ip4Prefix.valueOf(subnet.cidr()));
-        populateServiceIsolationRule(Ip4Prefix.valueOf(subnet.cidr()));
+        populateDirectAccessRule(cidr, cidr);
+        populateServiceIsolationRule(cidr);
         populateDstIpRule(deviceId, inPort, dstMac, hostIp, tunnelId, tunnelIp);
         populateTunnelInRule(deviceId, inPort, dstMac, tunnelId);
     }
diff --git a/apps/cordvtn/src/main/webapp/WEB-INF/web.xml b/apps/cordvtn/src/main/webapp/WEB-INF/web.xml
index 37aea15..2dc2c4a 100644
--- a/apps/cordvtn/src/main/webapp/WEB-INF/web.xml
+++ b/apps/cordvtn/src/main/webapp/WEB-INF/web.xml
@@ -47,6 +47,10 @@
             <param-name>javax.ws.rs.Application</param-name>
             <param-value>org.onosproject.cordvtn.rest.CordVtnWebApplication</param-value>
         </init-param>
+        <init-param>
+            <param-name>jersey.config.server.disableAutoDiscovery</param-name>
+            <param-value>true</param-value>
+        </init-param>
         <load-on-startup>1</load-on-startup>
     </servlet>