Adds a CLI to show/clear cached openstack states with neutron DB

Change-Id: I270c27affc669d10236ce94ec7a546a4f85aea88
diff --git a/apps/openstacknetworking/api/src/main/java/org/onosproject/openstacknetworking/api/Constants.java b/apps/openstacknetworking/api/src/main/java/org/onosproject/openstacknetworking/api/Constants.java
index 4110ac8..4410d70 100644
--- a/apps/openstacknetworking/api/src/main/java/org/onosproject/openstacknetworking/api/Constants.java
+++ b/apps/openstacknetworking/api/src/main/java/org/onosproject/openstacknetworking/api/Constants.java
@@ -147,4 +147,12 @@
 
     public static final boolean DEFAULT_HA_STATUS = false;
     public static final IpAddress DEFAULT_ACTIVE_IP_ADDRESS = IpAddress.valueOf("127.0.0.1");
+
+    public static final String SECURITY_GROUP_FORMAT = "%-40s%-20s";
+    public static final String NETWORK_FORMAT = "%-40s%-20s%-20s%-8s";
+    public static final String SUBNET_FORMAT = "%-40s%-20s%-20s";
+    public static final String ROUTER_INTF_FORMAT = "%-40s%-20s%-20s";
+    public static final String PORT_FORMAT = "%-40s%-20s%-20s%-8s";
+    public static final String ROUTER_FORMAT = "%-40s%-20s%-20s%-8s";
+    public static final String FLOATING_IP_FORMAT = "%-40s%-20s%-20s";
 }
diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/cli/OpenstackDiffStateCommand.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/cli/OpenstackDiffStateCommand.java
new file mode 100644
index 0000000..7f8b118
--- /dev/null
+++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/cli/OpenstackDiffStateCommand.java
@@ -0,0 +1,245 @@
+/*
+ * Copyright 2019-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 org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Option;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.openstacknetworking.api.OpenstackNetworkAdminService;
+import org.onosproject.openstacknetworking.api.OpenstackRouterAdminService;
+import org.onosproject.openstacknetworking.api.OpenstackSecurityGroupAdminService;
+import org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil;
+import org.onosproject.openstacknode.api.OpenstackNode;
+import org.onosproject.openstacknode.api.OpenstackNodeService;
+import org.openstack4j.api.OSClient;
+import org.openstack4j.model.common.IdEntity;
+import org.openstack4j.model.network.NetFloatingIP;
+import org.openstack4j.model.network.RouterInterface;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import static org.onosproject.openstacknetworking.api.Constants.FLOATING_IP_FORMAT;
+import static org.onosproject.openstacknetworking.api.Constants.NETWORK_FORMAT;
+import static org.onosproject.openstacknetworking.api.Constants.PORT_FORMAT;
+import static org.onosproject.openstacknetworking.api.Constants.ROUTER_FORMAT;
+import static org.onosproject.openstacknetworking.api.Constants.ROUTER_INTF_FORMAT;
+import static org.onosproject.openstacknetworking.api.Constants.SECURITY_GROUP_FORMAT;
+import static org.onosproject.openstacknetworking.api.Constants.SUBNET_FORMAT;
+import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.printFloatingIp;
+import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.printNetwork;
+import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.printPort;
+import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.printRouter;
+import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.printRouterIntf;
+import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.printSecurityGroup;
+import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.printSubnet;
+import static org.onosproject.openstacknode.api.OpenstackNode.NodeType.CONTROLLER;
+
+/**
+ * Compares cached network state diff against neutron database.
+ */
+@Service
+@Command(scope = "onos", name = "openstack-diff-state",
+        description = "Compares cached network state with neutron database.")
+public class OpenstackDiffStateCommand extends AbstractShellCommand {
+
+    private static final String HTTP_HEADER_ACCEPT = "accept";
+    private static final String HTTP_HEADER_VALUE_JSON = "application/json";
+
+    @Option(name = "-s", aliases = "--show",
+            description = "Shows the differences between cached network state with neutron database.",
+            required = false, multiValued = false)
+    private boolean show = false;
+
+    @Option(name = "-c", aliases = "--clear",
+            description = "Clears the differences between cached network state with neutron database.",
+            required = false, multiValued = false)
+    private boolean clear = false;
+
+    @Override
+    protected void doExecute() {
+        OpenstackSecurityGroupAdminService osSgService =
+                get(OpenstackSecurityGroupAdminService.class);
+        OpenstackNetworkAdminService osNetService =
+                get(OpenstackNetworkAdminService.class);
+        OpenstackRouterAdminService osRouterService =
+                get(OpenstackRouterAdminService.class);
+        OpenstackNodeService osNodeService = get(OpenstackNodeService.class);
+
+        Map<String, String> headerMap = new HashMap<>();
+        headerMap.put(HTTP_HEADER_ACCEPT, HTTP_HEADER_VALUE_JSON);
+
+        Optional<OpenstackNode> node = osNodeService.nodes(CONTROLLER).stream().findFirst();
+        if (!node.isPresent()) {
+            error("Keystone auth info has not been configured. " +
+                    "Please specify auth info via network-cfg.json.");
+            return;
+        }
+
+        OSClient osClient = OpenstackNetworkingUtil.getConnectedClient(node.get());
+
+        if (osClient == null) {
+            return;
+        }
+
+        if (!clear) {
+            show = true;
+        }
+
+        if (show && clear) {
+            error("Either --show (-s) or --clear (-c) option should be specified.");
+        }
+
+        if (show) {
+            print("\nComparing OpenStack floating IPs");
+        } else if (clear) {
+            print("\nClearing OpenStack floating IPs");
+        }
+        Set<String> cachedFips = osRouterService.floatingIps().stream()
+                .map(NetFloatingIP::getId).collect(Collectors.toSet());
+        Set<String> osFips = osClient.headers(headerMap).networking()
+                .floatingip().list().stream().map(NetFloatingIP::getId)
+                .collect(Collectors.toSet());
+
+        print(FLOATING_IP_FORMAT, "ID", "Floating IP", "Fixed IP");
+        getDiff(cachedFips, osFips).forEach(fipId -> {
+            printFloatingIp(osRouterService.floatingIp(fipId));
+            if (clear) {
+                osRouterService.removeFloatingIp(fipId);
+            }
+        });
+
+        Set<String> cachedPorts = osNetService.ports().stream()
+                .map(IdEntity::getId).collect(Collectors.toSet());
+        Set<String> osPorts = osClient.headers(headerMap).networking()
+                .port().list().stream().map(IdEntity::getId)
+                .collect(Collectors.toSet());
+
+        if (show) {
+            print("\nComparing OpenStack router interfaces");
+        } else if (clear) {
+            print("\nClearing OpenStack router interfaces");
+        }
+        print(ROUTER_INTF_FORMAT, "ID", "Tenant ID", "Subnet ID");
+        getDiff(cachedPorts, osPorts).forEach(portId -> {
+            RouterInterface ri = osRouterService.routerInterface(portId);
+            if (ri != null) {
+                printRouterIntf(ri);
+                if (clear) {
+                    osRouterService.removeRouterInterface(portId);
+                }
+            }
+        });
+
+        if (show) {
+            print("\nComparing OpenStack ports");
+        } else if (clear) {
+            print("\nClearing OpenStack ports");
+        }
+        print(PORT_FORMAT, "ID", "Network", "MAC", "Fixed IPs");
+        getDiff(cachedPorts, osPorts).forEach(portId -> {
+            printPort(osNetService.port(portId), osNetService);
+            if (clear) {
+                osNetService.removePort(portId);
+            }
+        });
+
+        if (show) {
+            print("\nComparing OpenStack routers");
+        } else if (clear) {
+            print("\nClearing OpenStack routers");
+        }
+        Set<String> cachedRouters = osRouterService.routers().stream()
+                .map(IdEntity::getId).collect(Collectors.toSet());
+        Set<String> osRouters = osClient.headers(headerMap).networking()
+                .router().list().stream().map(IdEntity::getId)
+                .collect(Collectors.toSet());
+
+        print(ROUTER_FORMAT, "ID", "Name", "External", "Internal");
+        getDiff(cachedRouters, osRouters).forEach(routerId -> {
+            printRouter(osRouterService.router(routerId), osNetService);
+            if (clear) {
+                osRouterService.removeRouter(routerId);
+            }
+        });
+
+        if (show) {
+            print("\nComparing OpenStack subnets");
+        } else if (clear) {
+            print("\nClearing OpenStack subnets");
+        }
+        Set<String> cachedSubnets = osNetService.subnets().stream()
+                .map(IdEntity::getId).collect(Collectors.toSet());
+        Set<String> osSubnets = osClient.headers(headerMap).networking()
+                .subnet().list().stream().map(IdEntity::getId)
+                .collect(Collectors.toSet());
+
+        print(SUBNET_FORMAT, "ID", "Network", "CIDR");
+        getDiff(cachedSubnets, osSubnets).forEach(subnetId -> {
+            printSubnet(osNetService.subnet(subnetId), osNetService);
+            if (clear) {
+                osNetService.removeSubnet(subnetId);
+            }
+        });
+
+        if (show) {
+            print("\nComparing OpenStack networks");
+        } else if (clear) {
+            print("\nClearing OpenStack networks");
+        }
+        Set<String> cachedNets = osNetService.networks().stream()
+                .map(IdEntity::getId).collect(Collectors.toSet());
+        Set<String> osNets = osClient.headers(headerMap).networking()
+                .network().list().stream().map(IdEntity::getId)
+                .collect(Collectors.toSet());
+
+        print(NETWORK_FORMAT, "ID", "Name", "VNI", "Subnets");
+        getDiff(cachedNets, osNets).forEach(netId -> {
+            printNetwork(osNetService.network(netId));
+            if (clear) {
+                osNetService.removeNetwork(netId);
+            }
+        });
+
+        if (show) {
+            print("\nComparing OpenStack security groups");
+        } else if (clear) {
+            print("\nClearing OpenStack security groups");
+        }
+        Set<String> cachedSgs = osSgService.securityGroups().stream()
+                .map(IdEntity::getId).collect(Collectors.toSet());
+        Set<String> osSgs = osClient.headers(headerMap).networking()
+                .securitygroup().list().stream().map(IdEntity::getId)
+                .collect(Collectors.toSet());
+
+        print(SECURITY_GROUP_FORMAT, "ID", "Name");
+        getDiff(cachedSgs, osSgs).forEach(sgId -> {
+            printSecurityGroup(osSgService.securityGroup(sgId));
+            if (clear) {
+                osSgService.removeSecurityGroup(sgId);
+            }
+        });
+    }
+
+    private Set<String> getDiff(Set<String> orig, Set<String> comp) {
+        return orig.stream().filter(id -> !comp.contains(id))
+                .collect(Collectors.toSet());
+    }
+}
diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/cli/OpenstackPortListCommand.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/cli/OpenstackPortListCommand.java
index e3398da..131c809 100644
--- a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/cli/OpenstackPortListCommand.java
+++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/cli/OpenstackPortListCommand.java
@@ -33,7 +33,6 @@
 import java.util.List;
 import java.util.stream.Collectors;
 
-import static org.onosproject.cli.AbstractShellCommand.get;
 import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.modelEntityToJson;
 import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.prettyJson;
 
@@ -71,8 +70,9 @@
                         .map(IP::getIpAddress)
                         .collect(Collectors.toList());
                 Network osNet = service.network(port.getNetworkId());
+                String netName = osNet == null ? "N/A" : osNet.getName();
                 print(FORMAT, port.getId(),
-                        osNet.getName(),
+                        netName,
                         port.getMacAddress(),
                         fixedIps.isEmpty() ? "" : fixedIps);
             }
diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/cli/OpenstackSubnetListCommand.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/cli/OpenstackSubnetListCommand.java
index da378b0..4a4a3c5 100644
--- a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/cli/OpenstackSubnetListCommand.java
+++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/cli/OpenstackSubnetListCommand.java
@@ -22,13 +22,13 @@
 import org.apache.karaf.shell.api.action.lifecycle.Service;
 import org.onosproject.cli.AbstractShellCommand;
 import org.onosproject.openstacknetworking.api.OpenstackNetworkService;
+import org.openstack4j.model.network.Network;
 import org.openstack4j.model.network.Subnet;
 import org.openstack4j.openstack.networking.domain.NeutronSubnet;
 
 import java.util.Comparator;
 import java.util.List;
 
-import static org.onosproject.cli.AbstractShellCommand.get;
 import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.modelEntityToJson;
 import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.prettyJson;
 
@@ -55,13 +55,15 @@
                                                 "NetworkName", "HostRoutes");
 
             for (Subnet subnet: subnets) {
+                Network osNet = service.network(subnet.getNetworkId());
+                String netName = osNet == null ? "N/A" : osNet.getName();
                 print(FORMAT,
                         subnet.getId(),
                         subnet.getName(),
                         subnet.getCidr(),
                         subnet.getGateway(),
                         subnet.getNetworkId(),
-                        service.network(subnet.getNetworkId()).getName(),
+                        netName,
                         subnet.getHostRoutes());
             }
         }
diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/cli/OpenstackSyncStateCommand.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/cli/OpenstackSyncStateCommand.java
index 5d3001d..29d167f 100644
--- a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/cli/OpenstackSyncStateCommand.java
+++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/cli/OpenstackSyncStateCommand.java
@@ -15,7 +15,6 @@
  */
 package org.onosproject.openstacknetworking.cli;
 
-import com.google.common.base.Strings;
 import org.apache.karaf.shell.api.action.Command;
 import org.apache.karaf.shell.api.action.lifecycle.Service;
 import org.onosproject.cli.AbstractShellCommand;
@@ -26,21 +25,25 @@
 import org.onosproject.openstacknode.api.OpenstackNode;
 import org.onosproject.openstacknode.api.OpenstackNodeService;
 import org.openstack4j.api.OSClient;
-import org.openstack4j.model.network.IP;
-import org.openstack4j.model.network.NetFloatingIP;
-import org.openstack4j.model.network.Network;
-import org.openstack4j.model.network.Port;
-import org.openstack4j.model.network.Router;
-import org.openstack4j.model.network.Subnet;
 
 import java.util.HashMap;
-import java.util.List;
 import java.util.Map;
 import java.util.Objects;
 import java.util.Optional;
-import java.util.stream.Collectors;
 
+import static org.onosproject.openstacknetworking.api.Constants.FLOATING_IP_FORMAT;
+import static org.onosproject.openstacknetworking.api.Constants.NETWORK_FORMAT;
+import static org.onosproject.openstacknetworking.api.Constants.PORT_FORMAT;
+import static org.onosproject.openstacknetworking.api.Constants.ROUTER_FORMAT;
+import static org.onosproject.openstacknetworking.api.Constants.SECURITY_GROUP_FORMAT;
+import static org.onosproject.openstacknetworking.api.Constants.SUBNET_FORMAT;
 import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.addRouterIface;
+import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.printFloatingIp;
+import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.printNetwork;
+import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.printPort;
+import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.printRouter;
+import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.printSecurityGroup;
+import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.printSubnet;
 import static org.onosproject.openstacknode.api.OpenstackNode.NodeType.CONTROLLER;
 
 /**
@@ -51,13 +54,6 @@
         description = "Synchronizes all OpenStack network states")
 public class OpenstackSyncStateCommand extends AbstractShellCommand {
 
-    private static final String SECURITY_GROUP_FORMAT = "%-40s%-20s";
-    private static final String NETWORK_FORMAT = "%-40s%-20s%-20s%-8s";
-    private static final String SUBNET_FORMAT = "%-40s%-20s%-20s";
-    private static final String PORT_FORMAT = "%-40s%-20s%-20s%-8s";
-    private static final String ROUTER_FORMAT = "%-40s%-20s%-20s%-8s";
-    private static final String FLOATING_IP_FORMAT = "%-40s%-20s%-20s";
-
     private static final String DEVICE_OWNER_GW = "network:router_gateway";
     private static final String DEVICE_OWNER_IFACE = "network:router_interface";
 
@@ -98,7 +94,7 @@
             } else {
                 osSgAdminService.createSecurityGroup(osSg);
             }
-            print(SECURITY_GROUP_FORMAT, osSg.getId(), osSg.getName());
+            printSecurityGroup(osSg);
         });
 
 
@@ -165,65 +161,4 @@
             printFloatingIp(osFloating);
         });
     }
-
-    private void printNetwork(Network osNet) {
-        final String strNet = String.format(NETWORK_FORMAT,
-                osNet.getId(),
-                osNet.getName(),
-                osNet.getProviderSegID(),
-                osNet.getSubnets());
-        print(strNet);
-    }
-
-    private void printSubnet(Subnet osSubnet, OpenstackNetworkAdminService osNetService) {
-        final String strSubnet = String.format(SUBNET_FORMAT,
-                osSubnet.getId(),
-                osNetService.network(osSubnet.getNetworkId()).getName(),
-                osSubnet.getCidr());
-        print(strSubnet);
-    }
-
-    private void printPort(Port osPort, OpenstackNetworkAdminService osNetService) {
-        List<String> fixedIps = osPort.getFixedIps().stream()
-                .map(IP::getIpAddress)
-                .collect(Collectors.toList());
-        final String strPort = String.format(PORT_FORMAT,
-                osPort.getId(),
-                osNetService.network(osPort.getNetworkId()).getName(),
-                osPort.getMacAddress(),
-                fixedIps.isEmpty() ? "" : fixedIps);
-        print(strPort);
-    }
-
-    private void printRouter(Router osRouter, OpenstackNetworkAdminService osNetService) {
-        List<String> externals = osNetService.ports().stream()
-                .filter(osPort -> Objects.equals(osPort.getDeviceId(), osRouter.getId()) &&
-                        Objects.equals(osPort.getDeviceOwner(), DEVICE_OWNER_GW))
-                .flatMap(osPort -> osPort.getFixedIps().stream())
-                .map(IP::getIpAddress)
-                .collect(Collectors.toList());
-
-        List<String> internals = osNetService.ports().stream()
-                .filter(osPort -> Objects.equals(osPort.getDeviceId(), osRouter.getId()) &&
-                        Objects.equals(osPort.getDeviceOwner(), DEVICE_OWNER_IFACE))
-                .flatMap(osPort -> osPort.getFixedIps().stream())
-                .map(IP::getIpAddress)
-                .collect(Collectors.toList());
-
-        final String strRouter = String.format(ROUTER_FORMAT,
-                osRouter.getId(),
-                osRouter.getName(),
-                externals.isEmpty() ? "" : externals,
-                internals.isEmpty() ? "" : internals);
-        print(strRouter);
-    }
-
-    private void printFloatingIp(NetFloatingIP floatingIp) {
-        final String strFloating = String.format(FLOATING_IP_FORMAT,
-                floatingIp.getId(),
-                floatingIp.getFloatingIpAddress(),
-                Strings.isNullOrEmpty(floatingIp.getFixedIpAddress()) ?
-                        "" : floatingIp.getFixedIpAddress());
-        print(strFloating);
-    }
 }
diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/util/OpenstackNetworkingUtil.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/util/OpenstackNetworkingUtil.java
index 8837a65..615de0e 100644
--- a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/util/OpenstackNetworkingUtil.java
+++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/util/OpenstackNetworkingUtil.java
@@ -85,11 +85,13 @@
 import org.openstack4j.model.ModelEntity;
 import org.openstack4j.model.common.Identifier;
 import org.openstack4j.model.network.ExternalGateway;
+import org.openstack4j.model.network.IP;
 import org.openstack4j.model.network.NetFloatingIP;
 import org.openstack4j.model.network.Network;
 import org.openstack4j.model.network.Port;
 import org.openstack4j.model.network.Router;
 import org.openstack4j.model.network.RouterInterface;
+import org.openstack4j.model.network.SecurityGroup;
 import org.openstack4j.model.network.Subnet;
 import org.openstack4j.openstack.OSFactory;
 import org.openstack4j.openstack.networking.domain.NeutronRouterInterface;
@@ -118,12 +120,14 @@
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.Iterator;
+import java.util.List;
 import java.util.Map;
 import java.util.Objects;
 import java.util.Optional;
 import java.util.Set;
 import java.util.TreeMap;
 import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
 
 import static com.fasterxml.jackson.databind.SerializationFeature.INDENT_OUTPUT;
 import static com.google.common.base.Preconditions.checkNotNull;
@@ -133,15 +137,22 @@
 import static org.onlab.packet.Ip4Address.valueOf;
 import static org.onosproject.net.AnnotationKeys.PORT_NAME;
 import static org.onosproject.openstacknetworking.api.Constants.DEFAULT_GATEWAY_MAC_STR;
+import static org.onosproject.openstacknetworking.api.Constants.FLOATING_IP_FORMAT;
+import static org.onosproject.openstacknetworking.api.Constants.NETWORK_FORMAT;
 import static org.onosproject.openstacknetworking.api.Constants.OPENSTACK_NETWORKING_REST_PATH;
 import static org.onosproject.openstacknetworking.api.Constants.PCISLOT;
 import static org.onosproject.openstacknetworking.api.Constants.PCI_VENDOR_INFO;
+import static org.onosproject.openstacknetworking.api.Constants.PORT_FORMAT;
 import static org.onosproject.openstacknetworking.api.Constants.PORT_NAME_PREFIX_VM;
 import static org.onosproject.openstacknetworking.api.Constants.PORT_NAME_VHOST_USER_PREFIX_VM;
 import static org.onosproject.openstacknetworking.api.Constants.REST_PASSWORD;
 import static org.onosproject.openstacknetworking.api.Constants.REST_PORT;
 import static org.onosproject.openstacknetworking.api.Constants.REST_USER;
 import static org.onosproject.openstacknetworking.api.Constants.REST_UTF8;
+import static org.onosproject.openstacknetworking.api.Constants.ROUTER_FORMAT;
+import static org.onosproject.openstacknetworking.api.Constants.ROUTER_INTF_FORMAT;
+import static org.onosproject.openstacknetworking.api.Constants.SECURITY_GROUP_FORMAT;
+import static org.onosproject.openstacknetworking.api.Constants.SUBNET_FORMAT;
 import static org.onosproject.openstacknetworking.api.Constants.UNSUPPORTED_VENDOR;
 import static org.onosproject.openstacknetworking.api.Constants.portNamePrefixMap;
 import static org.openstack4j.core.transport.ObjectMapperSingleton.getContext;
@@ -184,6 +195,11 @@
     private static final String COMMA = ",";
     private static final String TUN_ID = "tun_id=";
 
+    private static final String DEVICE_OWNER_GW = "network:router_gateway";
+    private static final String DEVICE_OWNER_IFACE = "network:router_interface";
+
+    private static final String NOT_AVAILABLE = "N/A";
+
     private static final long TIMEOUT_MS = 5000;
     private static final long WAIT_OUTPUT_STREAM_SECOND = 2;
     private static final int SSH_PORT = 22;
@@ -483,6 +499,124 @@
     }
 
     /**
+     * Prints openstack security group.
+     *
+     * @param osSg  openstack security group
+     */
+    public static void printSecurityGroup(SecurityGroup osSg) {
+        print(SECURITY_GROUP_FORMAT, osSg.getId(), osSg.getName());
+    }
+
+    /**
+     * Prints openstack network.
+     *
+     * @param osNet openstack network
+     */
+    public static void printNetwork(Network osNet) {
+        final String strNet = String.format(NETWORK_FORMAT,
+                osNet.getId(),
+                osNet.getName(),
+                osNet.getProviderSegID(),
+                osNet.getSubnets());
+        print(strNet);
+    }
+
+    /**
+     * Prints openstack subnet.
+     *
+     * @param osSubnet      openstack subnet
+     * @param osNetService  openstack network service
+     */
+    public static void printSubnet(Subnet osSubnet,
+                                   OpenstackNetworkService osNetService) {
+        final Network network = osNetService.network(osSubnet.getNetworkId());
+        final String netName = network == null ? NOT_AVAILABLE : network.getName();
+        final String strSubnet = String.format(SUBNET_FORMAT,
+                osSubnet.getId(),
+                netName,
+                osSubnet.getCidr());
+        print(strSubnet);
+    }
+
+    /**
+     * Prints openstack port.
+     *
+     * @param osPort        openstack port
+     * @param osNetService  openstack network service
+     */
+    public static void printPort(Port osPort,
+                                 OpenstackNetworkService osNetService) {
+        List<String> fixedIps = osPort.getFixedIps().stream()
+                .map(IP::getIpAddress)
+                .collect(Collectors.toList());
+        final Network network = osNetService.network(osPort.getNetworkId());
+        final String netName = network == null ? NOT_AVAILABLE : network.getName();
+        final String strPort = String.format(PORT_FORMAT,
+                osPort.getId(),
+                netName,
+                osPort.getMacAddress(),
+                fixedIps.isEmpty() ? "" : fixedIps);
+        print(strPort);
+    }
+
+    /**
+     * Prints openstack router.
+     *
+     * @param osRouter      openstack router
+     * @param osNetService  openstack network service
+     */
+    public static void printRouter(Router osRouter,
+                                   OpenstackNetworkService osNetService) {
+        List<String> externals = osNetService.ports().stream()
+                .filter(osPort -> Objects.equals(osPort.getDeviceId(), osRouter.getId()) &&
+                        Objects.equals(osPort.getDeviceOwner(), DEVICE_OWNER_GW))
+                .flatMap(osPort -> osPort.getFixedIps().stream())
+                .map(IP::getIpAddress)
+                .collect(Collectors.toList());
+
+        List<String> internals = osNetService.ports().stream()
+                .filter(osPort -> Objects.equals(osPort.getDeviceId(), osRouter.getId()) &&
+                        Objects.equals(osPort.getDeviceOwner(), DEVICE_OWNER_IFACE))
+                .flatMap(osPort -> osPort.getFixedIps().stream())
+                .map(IP::getIpAddress)
+                .collect(Collectors.toList());
+
+        final String strRouter = String.format(ROUTER_FORMAT,
+                osRouter.getId(),
+                osRouter.getName(),
+                externals.isEmpty() ? "" : externals,
+                internals.isEmpty() ? "" : internals);
+        print(strRouter);
+    }
+
+    /**
+     * Prints openstack router interface.
+     *
+     * @param osRouterIntf  openstack router interface
+     */
+    public static void printRouterIntf(RouterInterface osRouterIntf) {
+        final String strRouterIntf = String.format(ROUTER_INTF_FORMAT,
+                osRouterIntf.getId(),
+                osRouterIntf.getTenantId(),
+                osRouterIntf.getSubnetId());
+        print(strRouterIntf);
+    }
+
+    /**
+     * Prints openstack floating IP.
+     *
+     * @param floatingIp    floating IP
+     */
+    public static void printFloatingIp(NetFloatingIP floatingIp) {
+        final String strFloating = String.format(FLOATING_IP_FORMAT,
+                floatingIp.getId(),
+                floatingIp.getFloatingIpAddress(),
+                Strings.isNullOrEmpty(floatingIp.getFixedIpAddress()) ?
+                        "" : floatingIp.getFixedIpAddress());
+        print(strFloating);
+    }
+
+    /**
      * Obtains the property value with specified property key name.
      *
      * @param properties    a collection of properties
@@ -1443,4 +1577,8 @@
         }
         return gw;
     }
+
+    private static void print(String format, Object... args) {
+        System.out.println(String.format(format, args));
+    }
 }
\ No newline at end of file