Add CLI for listing all openstack instance ports

Change-Id: I05c826102a257c9d924397d22c368d35ff0587cf
diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/cli/InstancePortListCommand.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/cli/InstancePortListCommand.java
new file mode 100644
index 0000000..369b27a
--- /dev/null
+++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/cli/InstancePortListCommand.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2018-present Open Networking Foundation
+ *
+ * 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.openstacknetworking.cli;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.google.common.collect.Lists;
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.openstacknetworking.api.InstancePort;
+import org.onosproject.openstacknetworking.api.InstancePortService;
+
+import java.util.Comparator;
+import java.util.List;
+
+import static com.fasterxml.jackson.databind.SerializationFeature.INDENT_OUTPUT;
+
+/**
+ * Lists OpenStack instance ports.
+ */
+@Command(scope = "onos", name = "openstack-instance-ports",
+        description = "Lists all OpenStack instance ports")
+public class InstancePortListCommand extends AbstractShellCommand {
+
+    private static final String FORMAT = "%-40s%-10s%-25s%-15s%-20s";
+
+    @Override
+    protected void execute() {
+        InstancePortService service = get(InstancePortService.class);
+        List<InstancePort> instancePorts = Lists.newArrayList(service.instancePorts());
+        instancePorts.sort(Comparator.comparing(InstancePort::portId));
+
+        if (outputJson()) {
+            print("%s", json(this, instancePorts));
+        } else {
+            print(FORMAT, "ID", "State", "Device ID", "Port Number", "Fixed IP");
+            for (InstancePort port : instancePorts) {
+                print(FORMAT, port.portId(), port.state(), port.deviceId().toString(),
+                        port.portNumber().toLong(), port.ipAddress().toString());
+            }
+        }
+    }
+
+    private JsonNode json(AbstractShellCommand context, List<InstancePort> ports) {
+        ObjectMapper mapper = new ObjectMapper();
+        ArrayNode result = mapper.enable(INDENT_OUTPUT).createArrayNode();
+        ports.forEach(p -> result.add(context.jsonForEntity(p, InstancePort.class)));
+
+        return result;
+    }
+}
diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/codec/InstancePortCodec.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/codec/InstancePortCodec.java
new file mode 100644
index 0000000..c4b3cdc
--- /dev/null
+++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/codec/InstancePortCodec.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2018-present Open Networking Foundation
+ *
+ * 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.openstacknetworking.codec;
+
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.MacAddress;
+import org.onosproject.codec.CodecContext;
+import org.onosproject.codec.JsonCodec;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.PortNumber;
+import org.onosproject.openstacknetworking.api.InstancePort;
+import org.onosproject.openstacknetworking.impl.DefaultInstancePort;
+import org.slf4j.Logger;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.onlab.util.Tools.nullIsIllegal;
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * Openstack instance port codec used for serializing and de-serializing JSON string.
+ */
+public class InstancePortCodec extends JsonCodec<InstancePort> {
+
+    private final Logger log = getLogger(getClass());
+
+    private static final String NETWORK_ID = "networkId";
+    private static final String PORT_ID = "portId";
+    private static final String MAC_ADDRESS = "macAddress";
+    private static final String IP_ADDRESS = "ipAddress";
+    private static final String DEVICE_ID = "deviceId";
+    private static final String PORT_NUMBER = "portNumber";
+    private static final String STATE = "state";
+
+    private static final String MISSING_MESSAGE = " is required in InstancePort";
+
+    @Override
+    public ObjectNode encode(InstancePort port, CodecContext context) {
+        checkNotNull(port, "Instance port cannot be null");
+
+        return context.mapper().createObjectNode()
+                .put(NETWORK_ID, port.networkId())
+                .put(PORT_ID, port.portId())
+                .put(MAC_ADDRESS, port.macAddress().toString())
+                .put(IP_ADDRESS, port.ipAddress().toString())
+                .put(DEVICE_ID, port.deviceId().toString())
+                .put(PORT_NUMBER, port.portNumber().toString())
+                .put(STATE, port.state().name());
+    }
+
+    @Override
+    public InstancePort decode(ObjectNode json, CodecContext context) {
+        if (json == null || !json.isObject()) {
+            return null;
+        }
+
+        String networkId = nullIsIllegal(json.get(NETWORK_ID).asText(),
+                NETWORK_ID + MISSING_MESSAGE);
+        String portId = nullIsIllegal(json.get(PORT_ID).asText(),
+                PORT_ID + MISSING_MESSAGE);
+        String macAddress = nullIsIllegal(json.get(MAC_ADDRESS).asText(),
+                MAC_ADDRESS + MISSING_MESSAGE);
+        String ipAddress = nullIsIllegal(json.get(IP_ADDRESS).asText(),
+                IP_ADDRESS + MISSING_MESSAGE);
+        String deviceId = nullIsIllegal(json.get(DEVICE_ID).asText(),
+                DEVICE_ID + MISSING_MESSAGE);
+        String portNumber = nullIsIllegal(json.get(PORT_NUMBER).asText(),
+                PORT_NUMBER + MISSING_MESSAGE);
+        String state = nullIsIllegal(json.get(STATE).asText(),
+                STATE + MISSING_MESSAGE);
+
+        return DefaultInstancePort.builder()
+                .networkId(networkId)
+                .portId(portId)
+                .macAddress(MacAddress.valueOf(macAddress))
+                .ipAddress(IpAddress.valueOf(ipAddress))
+                .deviceId(DeviceId.deviceId(deviceId))
+                .portNumber(PortNumber.fromString(portNumber))
+                .state(InstancePort.State.valueOf(state)).build();
+    }
+}
diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/codec/package-info.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/codec/package-info.java
new file mode 100644
index 0000000..39000c0
--- /dev/null
+++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/codec/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2018-present Open Networking Foundation
+ *
+ * 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.
+ */
+
+/**
+ * Implementations of the codec broker and openstack networking entity JSON codecs.
+ */
+package org.onosproject.openstacknetworking.codec;
\ No newline at end of file
diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/web/OpenstackNetworkingCodecRegister.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/web/OpenstackNetworkingCodecRegister.java
new file mode 100644
index 0000000..55077f3
--- /dev/null
+++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/web/OpenstackNetworkingCodecRegister.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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.openstacknetworking.web;
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.onosproject.codec.CodecService;
+import org.onosproject.openstacknetworking.api.InstancePort;
+import org.onosproject.openstacknetworking.codec.InstancePortCodec;
+import org.slf4j.Logger;
+
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * Implementation of the JSON codec brokering service for OpenstackNetworking.
+ */
+@Component(immediate = true)
+public class OpenstackNetworkingCodecRegister {
+
+    private final Logger log = getLogger(getClass());
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected CodecService codecService;
+
+    @Activate
+    protected void activate() {
+
+        codecService.registerCodec(InstancePort.class, new InstancePortCodec());
+
+        log.info("Started");
+
+    }
+
+    @Deactivate
+    protected void deactivate() {
+
+        codecService.unregisterCodec(InstancePort.class);
+
+        log.info("Stopped");
+    }
+}