Changed to use XOS client to get service and port information

XOS client still gets these information from OpenStack temporarily
until XOS provides these APIs

Change-Id: I1ef9302f719a18a7377221f63b84431c2cdface8
diff --git a/apps/xosclient/src/main/java/org/onosproject/xosclient/api/OpenStackAccess.java b/apps/xosclient/src/main/java/org/onosproject/xosclient/api/OpenStackAccess.java
new file mode 100644
index 0000000..259ba55
--- /dev/null
+++ b/apps/xosclient/src/main/java/org/onosproject/xosclient/api/OpenStackAccess.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * 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.xosclient.api;
+
+import com.google.common.base.MoreObjects;
+
+import java.util.Objects;
+
+/**
+ * Object holding OpenStack API access information.
+ */
+// TODO remove this when XOS provides this information
+public class OpenStackAccess {
+
+    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 password
+     */
+    public OpenStackAccess(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;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(endpoint, tenant, user, password);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if ((obj instanceof OpenStackAccess)) {
+            OpenStackAccess that = (OpenStackAccess) obj;
+            if (Objects.equals(endpoint, that.endpoint) &&
+                    Objects.equals(tenant, that.tenant) &&
+                    Objects.equals(user, that.user) &&
+                    Objects.equals(password, that.password)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(getClass())
+                .add("endpoint", endpoint)
+                .add("tenant", tenant)
+                .add("user", user)
+                .add("password", password)
+                .toString();
+    }
+}
diff --git a/apps/xosclient/src/main/java/org/onosproject/xosclient/api/VtnPortApi.java b/apps/xosclient/src/main/java/org/onosproject/xosclient/api/VtnPortApi.java
index 593f32e..e4e56d3 100644
--- a/apps/xosclient/src/main/java/org/onosproject/xosclient/api/VtnPortApi.java
+++ b/apps/xosclient/src/main/java/org/onosproject/xosclient/api/VtnPortApi.java
@@ -44,4 +44,22 @@
      * @return vtn port; null if it fails to get port information
      */
     VtnPort vtnPort(VtnPortId portId);
+
+    /**
+     * Returns port information from OpenStack with port id.
+     *
+     * @param portId port id
+     * @return vtn port; null if it fails to get port information
+     */
+    // TODO remove this when XOS provides port information
+    VtnPort vtnPort(VtnPortId portId, OpenStackAccess osAccess);
+
+    /**
+     * Returns port information from OpenStack with port name.
+     *
+     * @param portName port name
+     * @return vtn port; null if it fails to get port information
+     */
+    // TODO remove this when XOS provides port information
+    VtnPort vtnPort(String portName, OpenStackAccess osAccess);
 }
diff --git a/apps/xosclient/src/main/java/org/onosproject/xosclient/api/VtnServiceApi.java b/apps/xosclient/src/main/java/org/onosproject/xosclient/api/VtnServiceApi.java
index 7ef3de0..11687f7 100644
--- a/apps/xosclient/src/main/java/org/onosproject/xosclient/api/VtnServiceApi.java
+++ b/apps/xosclient/src/main/java/org/onosproject/xosclient/api/VtnServiceApi.java
@@ -52,4 +52,14 @@
      * @return set of service ids
      */
     Set<VtnServiceId> providerServices(VtnServiceId tServiceId);
+
+    /**
+     * Returns VTN service from OpenStack.
+     *
+     * @param serviceId service id
+     * @param osAccess openstack access
+     * @return vtn service
+     */
+    // TODO remove this when XOS provides service information
+    VtnService service(VtnServiceId serviceId, OpenStackAccess osAccess);
 }
diff --git a/apps/xosclient/src/main/java/org/onosproject/xosclient/impl/DefaultVtnPortApi.java b/apps/xosclient/src/main/java/org/onosproject/xosclient/impl/DefaultVtnPortApi.java
index 672c81f..baff814 100644
--- a/apps/xosclient/src/main/java/org/onosproject/xosclient/impl/DefaultVtnPortApi.java
+++ b/apps/xosclient/src/main/java/org/onosproject/xosclient/impl/DefaultVtnPortApi.java
@@ -15,18 +15,33 @@
  */
 package org.onosproject.xosclient.impl;
 
+import com.google.common.collect.Maps;
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.MacAddress;
+import org.onosproject.xosclient.api.OpenStackAccess;
 import org.onosproject.xosclient.api.VtnPort;
 import org.onosproject.xosclient.api.VtnPortApi;
 import org.onosproject.xosclient.api.VtnPortId;
 import org.onosproject.xosclient.api.VtnServiceId;
 import org.onosproject.xosclient.api.XosAccess;
+import org.openstack4j.api.OSClient;
+import org.openstack4j.model.network.IP;
+import org.openstack4j.model.network.Port;
+import org.openstack4j.openstack.OSFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
+import java.util.Map;
 import java.util.Set;
 
+import static com.google.common.base.Preconditions.checkNotNull;
+
 /**
  * Provides CORD VTN port APIs.
  */
-public class DefaultVtnPortApi extends XosApi implements VtnPortApi {
+public final class DefaultVtnPortApi extends XosApi implements VtnPortApi {
+
+    private final Logger log = LoggerFactory.getLogger(getClass());
 
     /**
      * Default constructor.
@@ -55,4 +70,72 @@
         // TODO implement this when XOS provides this information
         return null;
     }
+
+    @Override
+    // TODO remove this when XOS provides this information
+    public VtnPort vtnPort(String portName, OpenStackAccess osAccess) {
+        checkNotNull(osAccess);
+
+        OSClient osClient = getOpenStackClient(osAccess);
+        Port osPort = osClient.networking().port().list()
+                .stream()
+                .filter(p -> p.getId().contains(portName.substring(3)))
+                .findFirst().orElse(null);
+        if (osPort == null) {
+            log.warn("Failed to get OpenStack port for {}", portName);
+            return null;
+        }
+        return getVtnPort(osPort);
+    }
+
+    @Override
+    // TODO remove this when XOS provides this information
+    public VtnPort vtnPort(VtnPortId portId, OpenStackAccess osAccess) {
+        checkNotNull(osAccess);
+
+        OSClient osClient = getOpenStackClient(osAccess);
+        Port osPort = osClient.networking().port().get(portId.id());
+        if (osPort == null) {
+            log.warn("Failed to get OpenStack port {}", portId);
+            return null;
+        }
+        return getVtnPort(osPort);
+    }
+
+    // TODO remove this when XOS provides this information
+    private VtnPort getVtnPort(Port osPort) {
+        checkNotNull(osPort);
+
+        // assumes all vtn port has single IP address
+        IP ipAddr = osPort.getFixedIps().stream().findFirst().orElse(null);
+        if (ipAddr == null) {
+            log.warn("Failed to get IP address for {}", osPort);
+            return null;
+        }
+
+        Map<IpAddress, MacAddress> addressPairs = Maps.newHashMap();
+        osPort.getAllowedAddressPairs().stream().forEach(
+                pair -> addressPairs.put(IpAddress.valueOf(pair.getIpAddress()),
+                                         MacAddress.valueOf(pair.getMacAddress())));
+
+        return new VtnPort(VtnPortId.of(osPort.getId()),
+                           osPort.getName(),
+                           VtnServiceId.of(osPort.getNetworkId()),
+                           MacAddress.valueOf(osPort.getMacAddress()),
+                           IpAddress.valueOf(ipAddr.getIpAddress()),
+                           addressPairs);
+    }
+
+    // TODO remove this when XOS provides this information
+    private OSClient getOpenStackClient(OpenStackAccess osAccess) {
+        checkNotNull(osAccess);
+
+        // creating a client every time must be inefficient, but this method
+        // will be removed once XOS provides equivalent APIs
+        return OSFactory.builder()
+                .endpoint(osAccess.endpoint())
+                .credentials(osAccess.user(), osAccess.password())
+                .tenantName(osAccess.tenant())
+                .authenticate();
+    }
 }
diff --git a/apps/xosclient/src/main/java/org/onosproject/xosclient/impl/DefaultVtnServiceApi.java b/apps/xosclient/src/main/java/org/onosproject/xosclient/impl/DefaultVtnServiceApi.java
index 94d8bbc..b83333c 100644
--- a/apps/xosclient/src/main/java/org/onosproject/xosclient/impl/DefaultVtnServiceApi.java
+++ b/apps/xosclient/src/main/java/org/onosproject/xosclient/impl/DefaultVtnServiceApi.java
@@ -17,12 +17,22 @@
 
 import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.common.base.Strings;
 import com.google.common.collect.Sets;
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.IpPrefix;
+import org.onosproject.xosclient.api.OpenStackAccess;
+import org.onosproject.xosclient.api.VtnService.NetworkType;
+import org.onosproject.xosclient.api.VtnService.ServiceType;
 import org.onosproject.xosclient.api.VtnServiceApi;
 import org.onosproject.xosclient.api.XosAccess;
 import org.onosproject.xosclient.api.VtnService;
 import org.onosproject.xosclient.api.VtnServiceId;
 
+import org.openstack4j.api.OSClient;
+import org.openstack4j.model.network.Network;
+import org.openstack4j.model.network.Subnet;
+import org.openstack4j.openstack.OSFactory;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -30,6 +40,9 @@
 import java.util.Set;
 
 import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkArgument;
+import static org.onosproject.xosclient.api.VtnService.NetworkType.*;
+import static org.onosproject.xosclient.api.VtnService.ServiceType.*;
 
 /**
  * Provides CORD VTN service and service dependency APIs.
@@ -113,4 +126,76 @@
         }
         return tServices;
     }
+
+    @Override
+    // TODO remove this when XOS provides this information
+    public VtnService service(VtnServiceId serviceId, OpenStackAccess osAccess) {
+        checkNotNull(osAccess);
+
+        OSClient osClient = getOpenStackClient(osAccess);
+        Network osNet = osClient.networking().network().get(serviceId.id());
+        if (osNet == null) {
+            log.warn("Failed to get OpenStack network {}", serviceId);
+            return null;
+        }
+
+        // assumes all cord service networks has single subnet
+        Subnet osSubnet = osNet.getNeutronSubnets().stream()
+                .findFirst().orElse(null);
+        if (osSubnet == null) {
+            log.warn("Failed to get OpenStack subnet of network {}", serviceId);
+            return null;
+        }
+
+        return new VtnService(serviceId,
+                              osNet.getName(),
+                              serviceType(osNet.getName()),
+                              networkType(osNet.getName()),
+                              Long.parseLong(osNet.getProviderSegID()),
+                              IpPrefix.valueOf(osSubnet.getCidr()),
+                              IpAddress.valueOf(osSubnet.getGateway()),
+                              providerServices(serviceId),
+                              tenantServices(serviceId));
+    }
+
+    // TODO remove this when XOS provides this information
+    private OSClient getOpenStackClient(OpenStackAccess osAccess) {
+        checkNotNull(osAccess);
+
+        // creating a client every time must be inefficient, but this method
+        // will be removed once XOS provides equivalent APIs
+        return OSFactory.builder()
+                .endpoint(osAccess.endpoint())
+                .credentials(osAccess.user(), osAccess.password())
+                .tenantName(osAccess.tenant())
+                .authenticate();
+    }
+
+    // TODO remove this when XOS provides this information
+    private NetworkType networkType(String netName) {
+        checkArgument(!Strings.isNullOrEmpty(netName));
+
+        String name = netName.toUpperCase();
+        if (name.contains(PUBLIC.toString())) {
+            return PUBLIC;
+        } else if (name.contains(MANAGEMENT.toString())) {
+            return MANAGEMENT;
+        } else {
+            return PRIVATE;
+        }
+    }
+
+    // TODO remove this when XOS provides this information
+    private ServiceType serviceType(String netName) {
+        checkArgument(!Strings.isNullOrEmpty(netName));
+
+        String name = netName.toUpperCase();
+        if (name.contains(VSG.toString())) {
+            return VSG;
+        } else if (name.contains(OLT_AGENT.toString())) {
+            return OLT_AGENT;
+        } else {
+            return DUMMY;
+        }
+    }
 }
diff --git a/apps/xosclient/src/main/java/org/onosproject/xosclient/impl/XosApi.java b/apps/xosclient/src/main/java/org/onosproject/xosclient/impl/XosApi.java
index 85f312d..4a9ec09 100644
--- a/apps/xosclient/src/main/java/org/onosproject/xosclient/impl/XosApi.java
+++ b/apps/xosclient/src/main/java/org/onosproject/xosclient/impl/XosApi.java
@@ -81,13 +81,15 @@
     public String restGet(String path) {
         WebTarget wt = client.target(access.endpoint() + baseUrl).path(path);
         Invocation.Builder builder = wt.request(JSON_UTF_8.toString());
-
-        Response response = builder.get();
-        if (response.getStatus() != HTTP_OK) {
-            log.warn("Failed to get resource {}", access.endpoint() + baseUrl + path);
+        try {
+            Response response = builder.get();
+            if (response.getStatus() != HTTP_OK) {
+                log.warn("Failed to get resource {}", access.endpoint() + baseUrl + path);
+                return EMPTY_JSON_STRING;
+            }
+        } catch (javax.ws.rs.ProcessingException e) {
             return EMPTY_JSON_STRING;
         }
-
         return builder.get(String.class);
     }
 }