[ONOS-3662] Add CLI for control plane manager

- Implement CLI for enumerating control plane metrics stats
- Implement ControlResourceTypeCompleter
- Implement DiskResourceNameCompleter
- Implement NetworkResourceNameCompleter
- Implement ControlMessageDeviceIdCompleter
- Extract the control resource type and metrics in a separated
  class for the sake of simplicity.

Change-Id: Ic505191a74bd463091b0e5c75e11f1824bafb816
diff --git a/apps/cpman/api/src/main/java/org/onosproject/cpman/ControlMetricType.java b/apps/cpman/api/src/main/java/org/onosproject/cpman/ControlMetricType.java
index b4626f9..d8a96f1 100644
--- a/apps/cpman/api/src/main/java/org/onosproject/cpman/ControlMetricType.java
+++ b/apps/cpman/api/src/main/java/org/onosproject/cpman/ControlMetricType.java
@@ -41,57 +41,57 @@
     /* Number of CPU cores. */
     NUM_OF_CORES,
 
-    /* Number of CPUs. **/
+    /* Number of CPUs. */
     NUM_OF_CPUS,
 
-    /* CPU Speed. **/
+    /* CPU Speed. */
     CPU_SPEED,
 
-    /* CPU Load. **/
+    /* CPU Load. */
     CPU_LOAD,
 
-    /* Total Amount of CPU Up Time. **/
+    /* Total Amount of CPU Up Time. */
     TOTAL_CPU_TIME,
 
-    /* System CPU Up Time. **/
+    /* System CPU Up Time. */
     SYS_CPU_TIME,
 
-    /* User CPU Up Time. **/
+    /* User CPU Up Time. */
     USER_CPU_TIME,
 
-    /* CPU Idle Time. **/
+    /* CPU Idle Time. */
     CPU_IDLE_TIME,
 
     /* Ratio of Used Memory Amount. */
     MEMORY_USED_RATIO,
 
-    /* Ratio of Free Memory Amount. **/
+    /* Ratio of Free Memory Amount. */
     MEMORY_FREE_RATIO,
 
-    /* Used Memory Amount. **/
+    /* Used Memory Amount. */
     MEMORY_USED,
 
-    /* Free Memory Amount. **/
+    /* Free Memory Amount. */
     MEMORY_FREE,
 
-    /* Total Amount of Memory. **/
+    /* Total Amount of Memory. */
     MEMORY_TOTAL,
 
-    /* Disk Read Bytes. **/
+    /* Disk Read Bytes. */
     DISK_READ_BYTES,
 
-    /* Disk Write Bytes. **/
+    /* Disk Write Bytes. */
     DISK_WRITE_BYTES,
 
-    /* Network Incoming Bytes. **/
+    /* Network Incoming Bytes. */
     NW_INCOMING_BYTES,
 
-    /* Network Outgoing Bytes. **/
+    /* Network Outgoing Bytes. */
     NW_OUTGOING_BYTES,
 
-    /* Network Incoming Packets. **/
+    /* Network Incoming Packets. */
     NW_INCOMING_PACKETS,
 
-    /* Network Outgoing Packets. **/
+    /* Network Outgoing Packets. */
     NW_OUTGOING_PACKETS
 }
diff --git a/apps/cpman/api/src/main/java/org/onosproject/cpman/ControlPlaneMonitorService.java b/apps/cpman/api/src/main/java/org/onosproject/cpman/ControlPlaneMonitorService.java
index 75d4501..f34e82b 100644
--- a/apps/cpman/api/src/main/java/org/onosproject/cpman/ControlPlaneMonitorService.java
+++ b/apps/cpman/api/src/main/java/org/onosproject/cpman/ControlPlaneMonitorService.java
@@ -19,6 +19,9 @@
 import org.onosproject.net.DeviceId;
 
 import java.util.Optional;
+import java.util.Set;
+
+import static org.onosproject.cpman.ControlResource.*;
 
 /**
  * Control Plane Statistics Service Interface.
@@ -71,4 +74,11 @@
      * @return control plane load
      */
     ControlLoad getLoad(NodeId nodeId, ControlMetricType type, String resourceName);
+
+    /**
+     * Obtains a list of names of available resources.
+     *
+     * @return a collection of names of available resources
+     */
+    Set<String> availableResources(Type resourceType);
 }
\ No newline at end of file
diff --git a/apps/cpman/api/src/main/java/org/onosproject/cpman/ControlResource.java b/apps/cpman/api/src/main/java/org/onosproject/cpman/ControlResource.java
new file mode 100644
index 0000000..d79b65e
--- /dev/null
+++ b/apps/cpman/api/src/main/java/org/onosproject/cpman/ControlResource.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2016 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.cpman;
+
+import com.google.common.collect.ImmutableSet;
+
+import java.util.Set;
+
+import static org.onosproject.cpman.ControlMetricType.CPU_IDLE_TIME;
+import static org.onosproject.cpman.ControlMetricType.CPU_LOAD;
+import static org.onosproject.cpman.ControlMetricType.DISK_READ_BYTES;
+import static org.onosproject.cpman.ControlMetricType.DISK_WRITE_BYTES;
+import static org.onosproject.cpman.ControlMetricType.FLOW_MOD_PACKET;
+import static org.onosproject.cpman.ControlMetricType.FLOW_REMOVED_PACKET;
+import static org.onosproject.cpman.ControlMetricType.INBOUND_PACKET;
+import static org.onosproject.cpman.ControlMetricType.MEMORY_FREE;
+import static org.onosproject.cpman.ControlMetricType.MEMORY_FREE_RATIO;
+import static org.onosproject.cpman.ControlMetricType.MEMORY_USED;
+import static org.onosproject.cpman.ControlMetricType.MEMORY_USED_RATIO;
+import static org.onosproject.cpman.ControlMetricType.NW_INCOMING_BYTES;
+import static org.onosproject.cpman.ControlMetricType.NW_INCOMING_PACKETS;
+import static org.onosproject.cpman.ControlMetricType.NW_OUTGOING_BYTES;
+import static org.onosproject.cpman.ControlMetricType.NW_OUTGOING_PACKETS;
+import static org.onosproject.cpman.ControlMetricType.OUTBOUND_PACKET;
+import static org.onosproject.cpman.ControlMetricType.REPLY_PACKET;
+import static org.onosproject.cpman.ControlMetricType.REQUEST_PACKET;
+import static org.onosproject.cpman.ControlMetricType.SYS_CPU_TIME;
+import static org.onosproject.cpman.ControlMetricType.TOTAL_CPU_TIME;
+import static org.onosproject.cpman.ControlMetricType.USER_CPU_TIME;
+
+/**
+ * A set of resource type used in control plane.
+ */
+public final class ControlResource {
+
+    private ControlResource() {}
+
+    /**
+     * Control resource type.
+     */
+    public enum Type {
+        /* CPU resource */
+        CPU,
+
+        /* Memory resource */
+        MEMORY,
+
+        /* Disk resource */
+        DISK,
+
+        /* Network resource */
+        NETWORK,
+
+        /* Control message resource */
+        CONTROL_MESSAGE
+    }
+
+    /* A collection of CPU related metric types */
+    public static final Set<ControlMetricType> CPU_METRICS =
+                        ImmutableSet.of(CPU_IDLE_TIME, CPU_LOAD, SYS_CPU_TIME,
+                                        USER_CPU_TIME, TOTAL_CPU_TIME);
+
+    /* A collection of memory related metric types */
+    public static final Set<ControlMetricType> MEMORY_METRICS =
+                        ImmutableSet.of(MEMORY_FREE, MEMORY_FREE_RATIO, MEMORY_USED,
+                                        MEMORY_USED_RATIO);
+
+    /* A collection of disk related metric types */
+    public static final Set<ControlMetricType> DISK_METRICS =
+                        ImmutableSet.of(DISK_READ_BYTES, DISK_WRITE_BYTES);
+
+    /* A collection of network related metric types */
+    public static final Set<ControlMetricType> NETWORK_METRICS =
+                        ImmutableSet.of(NW_INCOMING_BYTES, NW_OUTGOING_BYTES,
+                                        NW_INCOMING_PACKETS, NW_OUTGOING_PACKETS);
+
+    /* A collection of control message related metric types */
+    public static final Set<ControlMetricType> CONTROL_MESSAGE_METRICS =
+                        ImmutableSet.of(INBOUND_PACKET, OUTBOUND_PACKET, FLOW_MOD_PACKET,
+                                        FLOW_REMOVED_PACKET, REQUEST_PACKET, REPLY_PACKET);
+}
diff --git a/apps/cpman/app/pom.xml b/apps/cpman/app/pom.xml
index 8a3bc9a..b495b09 100644
--- a/apps/cpman/app/pom.xml
+++ b/apps/cpman/app/pom.xml
@@ -58,13 +58,14 @@
             <artifactId>onos-cli</artifactId>
             <version>${project.version}</version>
         </dependency>
-
         <dependency>
             <groupId>org.apache.karaf.shell</groupId>
             <artifactId>org.apache.karaf.shell.console</artifactId>
-            <scope>compile</scope>
         </dependency>
-
+        <dependency>
+            <groupId>org.apache.felix</groupId>
+            <artifactId>org.apache.felix.scr.annotations</artifactId>
+        </dependency>
         <dependency>
             <groupId>org.onosproject</groupId>
             <artifactId>onlab-junit</artifactId>
@@ -180,6 +181,7 @@
                             com.fasterxml.jackson.core,
                             org.apache.karaf.shell.commands,
                             org.apache.karaf.shell.console,
+                            org.apache.karaf.shell.console.completer,
                             com.google.common.*,
                             org.onlab.packet.*,
                             org.onlab.rest.*,
diff --git a/apps/cpman/app/src/main/java/org/onosproject/cpman/cli/ControlMessageDeviceIdCompleter.java b/apps/cpman/app/src/main/java/org/onosproject/cpman/cli/ControlMessageDeviceIdCompleter.java
new file mode 100644
index 0000000..ab063a0
--- /dev/null
+++ b/apps/cpman/app/src/main/java/org/onosproject/cpman/cli/ControlMessageDeviceIdCompleter.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2016 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.cpman.cli;
+
+import org.apache.karaf.shell.console.completer.ArgumentCompleter;
+import org.apache.karaf.shell.console.completer.StringsCompleter;
+import org.onosproject.cli.AbstractCompleter;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.cpman.ControlPlaneMonitorService;
+
+import java.util.List;
+import java.util.Set;
+import java.util.SortedSet;
+
+import static org.onosproject.cpman.ControlResource.Type;
+
+/**
+ * Device identification completer for control plane manager.
+ */
+public class ControlMessageDeviceIdCompleter extends AbstractCompleter {
+    @Override
+    public int complete(String buffer, int cursor, List<String> candidates) {
+        // delegate string completer
+        StringsCompleter delegate = new StringsCompleter();
+
+        // Resource type is the second argument.
+        ArgumentCompleter.ArgumentList list = getArgumentList();
+        String type = list.getArguments()[1];
+
+        if (Type.CONTROL_MESSAGE.toString().toLowerCase().equals(type)) {
+            ControlPlaneMonitorService monitorService =
+                    AbstractShellCommand.get(ControlPlaneMonitorService.class);
+
+            Set<String> set = monitorService.availableResources(Type.CONTROL_MESSAGE);
+
+            SortedSet<String> strings = delegate.getStrings();
+            if (set != null) {
+                set.forEach(s -> strings.add(s));
+            }
+        }
+        return delegate.complete(buffer, cursor, candidates);
+    }
+}
diff --git a/apps/cpman/app/src/main/java/org/onosproject/cpman/cli/ControlMetricsStatsListCommand.java b/apps/cpman/app/src/main/java/org/onosproject/cpman/cli/ControlMetricsStatsListCommand.java
new file mode 100644
index 0000000..2b061d2
--- /dev/null
+++ b/apps/cpman/app/src/main/java/org/onosproject/cpman/cli/ControlMetricsStatsListCommand.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2016 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.cpman.cli;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.cluster.ClusterService;
+import org.onosproject.cluster.NodeId;
+import org.onosproject.cpman.ControlLoad;
+import org.onosproject.cpman.ControlMetricType;
+import org.onosproject.cpman.ControlPlaneMonitorService;
+import org.onosproject.net.DeviceId;
+
+import java.util.Optional;
+import java.util.Set;
+
+import static org.onosproject.cpman.ControlResource.CONTROL_MESSAGE_METRICS;
+import static org.onosproject.cpman.ControlResource.CPU_METRICS;
+import static org.onosproject.cpman.ControlResource.DISK_METRICS;
+import static org.onosproject.cpman.ControlResource.MEMORY_METRICS;
+import static org.onosproject.cpman.ControlResource.NETWORK_METRICS;
+
+/**
+ * Lists all stats information of control plane metrics.
+ */
+@Command(scope = "onos", name = "cpman-stats-list",
+        description = "Lists control metrics statistics")
+public class ControlMetricsStatsListCommand extends AbstractShellCommand {
+
+    private static final String FMT = "metricType=%s, latestValue=%d, " +
+            "averageValue=%d, latestTime=%s";
+    private static final String INVALID_TYPE = "Invalid control resource type.";
+
+    @Argument(index = 0, name = "type",
+            description = "Resource type (cpu|memory|disk|network|control_message)",
+            required = true, multiValued = false)
+    String type = null;
+
+    @Argument(index = 1, name = "name", description = "Resource name (or Device Id)",
+            required = false, multiValued = false)
+    String name = null;
+
+    @Override
+    protected void execute() {
+        ControlPlaneMonitorService service = get(ControlPlaneMonitorService.class);
+        ClusterService clusterService = get(ClusterService.class);
+        NodeId nodeId = clusterService.getLocalNode().id();
+        switch (type) {
+            case "cpu":
+                printMetricsStats(service, nodeId, CPU_METRICS);
+                break;
+            case "memory":
+                printMetricsStats(service, nodeId, MEMORY_METRICS);
+                break;
+            case "disk":
+                printMetricsStats(service, nodeId, DISK_METRICS, name);
+                break;
+            case "network":
+                printMetricsStats(service, nodeId, NETWORK_METRICS, name);
+                break;
+            case "control_message":
+                if (name != null) {
+                    printMetricsStats(service, nodeId, CONTROL_MESSAGE_METRICS, DeviceId.deviceId(name));
+                }
+                break;
+            default:
+                print(INVALID_TYPE);
+                break;
+        }
+    }
+
+    private void printMetricsStats(ControlPlaneMonitorService service, NodeId nodeId,
+                                   Set<ControlMetricType> typeSet) {
+        printMetricsStats(service, nodeId, typeSet, null, null);
+    }
+
+    private void printMetricsStats(ControlPlaneMonitorService service, NodeId nodeId,
+                                   Set<ControlMetricType> typeSet, String name) {
+        printMetricsStats(service, nodeId, typeSet, name, null);
+    }
+
+    private void printMetricsStats(ControlPlaneMonitorService service, NodeId nodeId,
+                                   Set<ControlMetricType> typeSet, DeviceId did) {
+        printMetricsStats(service, nodeId, typeSet, null, did);
+    }
+
+    private void printMetricsStats(ControlPlaneMonitorService service, NodeId nodeId,
+                                   Set<ControlMetricType> typeSet, String name, DeviceId did) {
+        if (name == null && did == null) {
+            typeSet.forEach(s -> print(s, service.getLoad(nodeId, s, Optional.ofNullable(null))));
+        } else if (name == null && did != null) {
+            typeSet.forEach(s -> print(s, service.getLoad(nodeId, s, Optional.of(did))));
+        } else if (name != null && did == null) {
+            typeSet.forEach(s -> print(s, service.getLoad(nodeId, s, name)));
+        }
+    }
+
+    private void print(ControlMetricType type, ControlLoad cl) {
+        if (cl != null) {
+            print(FMT, type.toString(), cl.latest(), cl.average(), cl.time());
+        }
+    }
+}
diff --git a/apps/cpman/app/src/main/java/org/onosproject/cpman/cli/ControlResourceTypeCompleter.java b/apps/cpman/app/src/main/java/org/onosproject/cpman/cli/ControlResourceTypeCompleter.java
new file mode 100644
index 0000000..cc3b225
--- /dev/null
+++ b/apps/cpman/app/src/main/java/org/onosproject/cpman/cli/ControlResourceTypeCompleter.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2016 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.cpman.cli;
+
+import com.google.common.collect.ImmutableList;
+import org.onosproject.cli.AbstractChoicesCompleter;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+import static org.onosproject.cpman.ControlResource.Type;
+
+/**
+ * Control resource type completer.
+ */
+public class ControlResourceTypeCompleter extends AbstractChoicesCompleter {
+
+    private static final List<Type> RESOURCE_TYPES =
+            ImmutableList.of(Type.CPU, Type.MEMORY, Type.DISK, Type.NETWORK,
+                    Type.CONTROL_MESSAGE);
+
+    @Override
+    protected List<String> choices() {
+        return RESOURCE_TYPES.stream().map(type ->
+                type.toString().toLowerCase()).collect(Collectors.toList());
+    }
+}
diff --git a/apps/cpman/app/src/main/java/org/onosproject/cpman/cli/DiskResourceNameCompleter.java b/apps/cpman/app/src/main/java/org/onosproject/cpman/cli/DiskResourceNameCompleter.java
new file mode 100644
index 0000000..f67d629
--- /dev/null
+++ b/apps/cpman/app/src/main/java/org/onosproject/cpman/cli/DiskResourceNameCompleter.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2016 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.cpman.cli;
+
+import org.apache.karaf.shell.console.completer.ArgumentCompleter;
+import org.apache.karaf.shell.console.completer.StringsCompleter;
+import org.onosproject.cli.AbstractCompleter;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.cpman.ControlPlaneMonitorService;
+
+import java.util.List;
+import java.util.Set;
+import java.util.SortedSet;
+
+import static org.onosproject.cpman.ControlResource.Type;
+/**
+ * Disk resource name completer.
+ */
+public class DiskResourceNameCompleter extends AbstractCompleter {
+    @Override
+    public int complete(String buffer, int cursor, List<String> candidates) {
+        // delegate string completer
+        StringsCompleter delegate = new StringsCompleter();
+
+        // Resource type is the second argument.
+        ArgumentCompleter.ArgumentList list = getArgumentList();
+        String type = list.getArguments()[1];
+
+        if (Type.DISK.toString().toLowerCase().equals(type)) {
+            ControlPlaneMonitorService monitorService =
+                    AbstractShellCommand.get(ControlPlaneMonitorService.class);
+
+            Set<String> set = monitorService.availableResources(Type.DISK);
+            SortedSet<String> strings = delegate.getStrings();
+
+            if (set != null) {
+                set.forEach(s -> strings.add(s));
+            }
+        }
+        return delegate.complete(buffer, cursor, candidates);
+    }
+}
diff --git a/apps/cpman/app/src/main/java/org/onosproject/cpman/cli/NetworkResourceNameCompleter.java b/apps/cpman/app/src/main/java/org/onosproject/cpman/cli/NetworkResourceNameCompleter.java
new file mode 100644
index 0000000..576d8ee
--- /dev/null
+++ b/apps/cpman/app/src/main/java/org/onosproject/cpman/cli/NetworkResourceNameCompleter.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2016 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.cpman.cli;
+
+import org.apache.karaf.shell.console.completer.ArgumentCompleter;
+import org.apache.karaf.shell.console.completer.StringsCompleter;
+import org.onosproject.cli.AbstractCompleter;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.cpman.ControlPlaneMonitorService;
+
+import java.util.List;
+import java.util.Set;
+import java.util.SortedSet;
+
+import static org.onosproject.cpman.ControlResource.Type;
+
+/**
+ * Network resource name completer.
+ */
+public class NetworkResourceNameCompleter extends AbstractCompleter {
+    @Override
+    public int complete(String buffer, int cursor, List<String> candidates) {
+        // delegate string completer
+        StringsCompleter delegate = new StringsCompleter();
+
+        // Resource type is the second argument.
+        ArgumentCompleter.ArgumentList list = getArgumentList();
+        String type = list.getArguments()[1];
+
+        if (Type.NETWORK.toString().toLowerCase().equals(type)) {
+            ControlPlaneMonitorService monitorService =
+                    AbstractShellCommand.get(ControlPlaneMonitorService.class);
+
+            Set<String> set = monitorService.availableResources(Type.NETWORK);
+            SortedSet<String> strings = delegate.getStrings();
+
+            if (set != null) {
+                set.forEach(s -> strings.add(s));
+            }
+        }
+
+        return delegate.complete(buffer, cursor, candidates);
+    }
+}
diff --git a/apps/cpman/app/src/main/java/org/onosproject/cpman/cli/package-info.java b/apps/cpman/app/src/main/java/org/onosproject/cpman/cli/package-info.java
new file mode 100644
index 0000000..adcb6cf
--- /dev/null
+++ b/apps/cpman/app/src/main/java/org/onosproject/cpman/cli/package-info.java
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2016 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.
+ */
+/**
+ * CLI implementation for control plane manager.
+ */
+package org.onosproject.cpman.cli;
\ No newline at end of file
diff --git a/apps/cpman/app/src/main/java/org/onosproject/cpman/impl/ControlPlaneMonitor.java b/apps/cpman/app/src/main/java/org/onosproject/cpman/impl/ControlPlaneMonitor.java
index 66b4a57..77e8e89 100644
--- a/apps/cpman/app/src/main/java/org/onosproject/cpman/impl/ControlPlaneMonitor.java
+++ b/apps/cpman/app/src/main/java/org/onosproject/cpman/impl/ControlPlaneMonitor.java
@@ -16,6 +16,8 @@
 package org.onosproject.cpman.impl;
 
 import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
 import org.apache.felix.scr.annotations.Activate;
 import org.apache.felix.scr.annotations.Component;
 import org.apache.felix.scr.annotations.Deactivate;
@@ -37,29 +39,9 @@
 import java.util.Map;
 import java.util.Optional;
 import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
+import java.util.stream.Collectors;
 
-import static org.onosproject.cpman.ControlMetricType.CPU_IDLE_TIME;
-import static org.onosproject.cpman.ControlMetricType.CPU_LOAD;
-import static org.onosproject.cpman.ControlMetricType.DISK_READ_BYTES;
-import static org.onosproject.cpman.ControlMetricType.DISK_WRITE_BYTES;
-import static org.onosproject.cpman.ControlMetricType.FLOW_MOD_PACKET;
-import static org.onosproject.cpman.ControlMetricType.FLOW_REMOVED_PACKET;
-import static org.onosproject.cpman.ControlMetricType.INBOUND_PACKET;
-import static org.onosproject.cpman.ControlMetricType.MEMORY_FREE;
-import static org.onosproject.cpman.ControlMetricType.MEMORY_FREE_RATIO;
-import static org.onosproject.cpman.ControlMetricType.MEMORY_USED;
-import static org.onosproject.cpman.ControlMetricType.MEMORY_USED_RATIO;
-import static org.onosproject.cpman.ControlMetricType.NW_INCOMING_BYTES;
-import static org.onosproject.cpman.ControlMetricType.NW_INCOMING_PACKETS;
-import static org.onosproject.cpman.ControlMetricType.NW_OUTGOING_BYTES;
-import static org.onosproject.cpman.ControlMetricType.NW_OUTGOING_PACKETS;
-import static org.onosproject.cpman.ControlMetricType.OUTBOUND_PACKET;
-import static org.onosproject.cpman.ControlMetricType.REPLY_PACKET;
-import static org.onosproject.cpman.ControlMetricType.REQUEST_PACKET;
-import static org.onosproject.cpman.ControlMetricType.SYS_CPU_TIME;
-import static org.onosproject.cpman.ControlMetricType.TOTAL_CPU_TIME;
-import static org.onosproject.cpman.ControlMetricType.USER_CPU_TIME;
+import static org.onosproject.cpman.ControlResource.*;
 
 /**
  * Control plane monitoring service class.
@@ -78,45 +60,34 @@
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected ClusterService clusterService;
 
-    private static final String CPU = "Cpu";
-    private static final String MEMORY = "Memory";
-    private static final String CTRL_MSG = "ControlMessage";
-    private static final String DISK = "Disk";
-    private static final String NETWORK = "Network";
+    private static final Set RESOURCE_TYPE_SET =
+            ImmutableSet.of(Type.CONTROL_MESSAGE, Type.DISK, Type.NETWORK);
 
-    private static final Set<ControlMetricType> CPU_METRICS =
-            ImmutableSet.of(CPU_IDLE_TIME, CPU_LOAD, SYS_CPU_TIME,
-                    USER_CPU_TIME, TOTAL_CPU_TIME);
-    private static final Set<ControlMetricType> MEMORY_METRICS =
-            ImmutableSet.of(MEMORY_FREE, MEMORY_FREE_RATIO, MEMORY_USED,
-                    MEMORY_USED_RATIO);
-    private static final Set<ControlMetricType> DISK_METRICS =
-            ImmutableSet.of(DISK_READ_BYTES, DISK_WRITE_BYTES);
-    private static final Set<ControlMetricType> NETWORK_METRICS =
-            ImmutableSet.of(NW_INCOMING_BYTES, NW_OUTGOING_BYTES,
-                    NW_INCOMING_PACKETS, NW_OUTGOING_PACKETS);
-    private static final Set<ControlMetricType> CTRL_MSGS =
-            ImmutableSet.of(INBOUND_PACKET, OUTBOUND_PACKET, FLOW_MOD_PACKET,
-                    FLOW_REMOVED_PACKET, REQUEST_PACKET, REPLY_PACKET);
     private Map<ControlMetricType, Double> cpuBuf;
     private Map<ControlMetricType, Double> memoryBuf;
     private Map<String, Map<ControlMetricType, Double>> diskBuf;
     private Map<String, Map<ControlMetricType, Double>> networkBuf;
     private Map<DeviceId, Map<ControlMetricType, Double>> ctrlMsgBuf;
 
+    private Map<Type, Set<String>> availableResourceMap;
+    private Set<DeviceId> availableDeviceIdSet;
+
     @Activate
     public void activate() {
-        cpuMetrics = genMDbBuilder(CPU, CPU_METRICS);
-        memoryMetrics = genMDbBuilder(MEMORY, MEMORY_METRICS);
-        controlMessageMap = new ConcurrentHashMap<>();
-        diskMetricsMap = new ConcurrentHashMap<>();
-        networkMetricsMap = new ConcurrentHashMap<>();
+        cpuMetrics = genMDbBuilder(Type.CPU, CPU_METRICS);
+        memoryMetrics = genMDbBuilder(Type.MEMORY, MEMORY_METRICS);
+        controlMessageMap = Maps.newConcurrentMap();
+        diskMetricsMap = Maps.newConcurrentMap();
+        networkMetricsMap = Maps.newConcurrentMap();
 
-        cpuBuf = new ConcurrentHashMap<>();
-        memoryBuf = new ConcurrentHashMap<>();
-        diskBuf = new ConcurrentHashMap<>();
-        networkBuf = new ConcurrentHashMap<>();
-        ctrlMsgBuf = new ConcurrentHashMap<>();
+        cpuBuf = Maps.newConcurrentMap();
+        memoryBuf = Maps.newConcurrentMap();
+        diskBuf = Maps.newConcurrentMap();
+        networkBuf = Maps.newConcurrentMap();
+        ctrlMsgBuf = Maps.newConcurrentMap();
+
+        availableResourceMap = Maps.newConcurrentMap();
+        availableDeviceIdSet = Sets.newConcurrentHashSet();
 
         log.info("Started");
     }
@@ -140,10 +111,14 @@
         if (deviceId.isPresent()) {
 
             // insert a new device entry if we cannot find any
-            ctrlMsgBuf.putIfAbsent(deviceId.get(), new ConcurrentHashMap<>());
+            ctrlMsgBuf.putIfAbsent(deviceId.get(), Maps.newConcurrentMap());
 
             // update control message metrics
-            if (CTRL_MSGS.contains(cm.metricType())) {
+            if (CONTROL_MESSAGE_METRICS.contains(cm.metricType())) {
+
+                if (!availableDeviceIdSet.contains(deviceId.get())) {
+                    availableDeviceIdSet.add(deviceId.get());
+                }
 
                 // we will accumulate the metric value into buffer first
                 ctrlMsgBuf.get(deviceId.get()).putIfAbsent(cm.metricType(),
@@ -151,7 +126,8 @@
 
                 // if buffer contains all control message metrics,
                 // we simply set and update the values into MetricsDatabase.
-                if (ctrlMsgBuf.get(deviceId.get()).keySet().containsAll(CTRL_MSGS)) {
+                if (ctrlMsgBuf.get(deviceId.get()).keySet()
+                        .containsAll(CONTROL_MESSAGE_METRICS)) {
                     updateControlMessages(ctrlMsgBuf.get(deviceId.get()), deviceId.get());
                     ctrlMsgBuf.get(deviceId.get()).clear();
                 }
@@ -185,7 +161,14 @@
                              String resourceName) {
         // update disk metrics
         if (DISK_METRICS.contains(cm.metricType())) {
-            diskBuf.putIfAbsent(resourceName, new ConcurrentHashMap<>());
+            diskBuf.putIfAbsent(resourceName, Maps.newConcurrentMap());
+
+            availableResourceMap.putIfAbsent(Type.DISK, Sets.newHashSet());
+            availableResourceMap.computeIfPresent(Type.DISK, (k, v) -> {
+                v.add(resourceName);
+                return v;
+            });
+
             diskBuf.get(resourceName).putIfAbsent(cm.metricType(),
                     (double) cm.metricValue().getLoad());
             if (diskBuf.get(resourceName).keySet().containsAll(DISK_METRICS)) {
@@ -196,7 +179,14 @@
 
         // update network metrics
         if (NETWORK_METRICS.contains(cm.metricType())) {
-            networkBuf.putIfAbsent(resourceName, new ConcurrentHashMap<>());
+            networkBuf.putIfAbsent(resourceName, Maps.newConcurrentMap());
+
+            availableResourceMap.putIfAbsent(Type.NETWORK, Sets.newHashSet());
+            availableResourceMap.computeIfPresent(Type.NETWORK, (k, v) -> {
+                v.add(resourceName);
+                return v;
+            });
+
             networkBuf.get(resourceName).putIfAbsent(cm.metricType(),
                     (double) cm.metricValue().getLoad());
             if (networkBuf.get(resourceName).keySet().containsAll(NETWORK_METRICS)) {
@@ -213,7 +203,8 @@
         if (clusterService.getLocalNode().equals(node)) {
 
             if (deviceId.isPresent()) {
-                if (CTRL_MSGS.contains(type)) {
+                if (CONTROL_MESSAGE_METRICS.contains(type) &&
+                        availableDeviceIdSet.contains(deviceId.get())) {
                     return new DefaultControlLoad(controlMessageMap.get(deviceId.get()), type);
                 }
             } else {
@@ -238,11 +229,13 @@
     public ControlLoad getLoad(NodeId nodeId, ControlMetricType type,
                                String resourceName) {
         if (clusterService.getLocalNode().id().equals(nodeId)) {
-            if (DISK_METRICS.contains(type)) {
+            if (DISK_METRICS.contains(type) &&
+                    availableResources(Type.DISK).contains(resourceName)) {
                 return new DefaultControlLoad(diskMetricsMap.get(resourceName), type);
             }
 
-            if (NETWORK_METRICS.contains(type)) {
+            if (NETWORK_METRICS.contains(type) &&
+                    availableResources(Type.NETWORK).contains(resourceName)) {
                 return new DefaultControlLoad(networkMetricsMap.get(resourceName), type);
             }
         } else {
@@ -252,34 +245,49 @@
         return null;
     }
 
-    private MetricsDatabase genMDbBuilder(String metricName,
+    @Override
+    public Set<String> availableResources(Type resourceType) {
+        if (RESOURCE_TYPE_SET.contains(resourceType)) {
+            if (Type.CONTROL_MESSAGE.equals(resourceType)) {
+                return availableDeviceIdSet.stream().map(id ->
+                        id.toString()).collect(Collectors.toSet());
+            } else {
+                return availableResourceMap.get(resourceType);
+            }
+        }
+        return null;
+    }
+
+    private MetricsDatabase genMDbBuilder(Type resourceType,
                                           Set<ControlMetricType> metricTypes) {
         MetricsDatabase.Builder builder = new DefaultMetricsDatabase.Builder();
-        builder.withMetricName(metricName);
+        builder.withMetricName(resourceType.toString());
         metricTypes.forEach(type -> builder.addMetricType(type.toString()));
         return builder.build();
     }
 
     private void updateNetworkMetrics(Map<ControlMetricType, Double> metricMap,
                                       String resName) {
-        networkMetricsMap.putIfAbsent(resName, genMDbBuilder(NETWORK, NETWORK_METRICS));
+        networkMetricsMap.putIfAbsent(resName,
+                genMDbBuilder(Type.NETWORK, NETWORK_METRICS));
         networkMetricsMap.get(resName).updateMetrics(convertMap(metricMap));
     }
 
     private void updateDiskMetrics(Map<ControlMetricType, Double> metricMap,
                                    String resName) {
-        diskMetricsMap.putIfAbsent(resName, genMDbBuilder(DISK, DISK_METRICS));
+        diskMetricsMap.putIfAbsent(resName, genMDbBuilder(Type.DISK, DISK_METRICS));
         diskMetricsMap.get(resName).updateMetrics(convertMap(metricMap));
     }
 
     private void updateControlMessages(Map<ControlMetricType, Double> metricMap,
                                        DeviceId devId) {
-        controlMessageMap.putIfAbsent(devId, genMDbBuilder(CTRL_MSG, CTRL_MSGS));
+        controlMessageMap.putIfAbsent(devId,
+                genMDbBuilder(Type.CONTROL_MESSAGE, CONTROL_MESSAGE_METRICS));
         controlMessageMap.get(devId).updateMetrics(convertMap(metricMap));
     }
 
     private Map convertMap(Map<ControlMetricType, Double> map) {
-        Map newMap = new ConcurrentHashMap<>();
+        Map newMap = Maps.newConcurrentMap();
         map.forEach((k, v) -> newMap.putIfAbsent(k.toString(), v));
         return newMap;
     }
diff --git a/apps/cpman/app/src/main/java/org/onosproject/cpman/impl/DefaultMetricsDatabase.java b/apps/cpman/app/src/main/java/org/onosproject/cpman/impl/DefaultMetricsDatabase.java
index db8be14..31a19da 100644
--- a/apps/cpman/app/src/main/java/org/onosproject/cpman/impl/DefaultMetricsDatabase.java
+++ b/apps/cpman/app/src/main/java/org/onosproject/cpman/impl/DefaultMetricsDatabase.java
@@ -231,7 +231,7 @@
     }
 
     public static final class Builder implements MetricsDatabase.Builder {
-        private static final int RESOLUTION = 60; // seconds
+        private static final int RESOLUTION_IN_SECOND = 60;
         private static final String STORING_METHOD = "MEMORY";
         private static final DsType SOURCE_TYPE = DsType.GAUGE;
         private static final String DB_PATH = "CPMAN";
@@ -259,7 +259,7 @@
             this.metricName = metricName;
 
             // define the resolution of monitored metrics
-            rrdDef = new RrdDef(DB_PATH + "_" + metricName, RESOLUTION);
+            rrdDef = new RrdDef(DB_PATH + "_" + metricName, RESOLUTION_IN_SECOND);
             return this;
         }
 
@@ -279,7 +279,7 @@
                 IntStream.range(0, dsDefs.size()).forEach(i -> dsDefArray[i] = dsDefs.get(i));
 
                 rrdDef.addDatasource(dsDefArray);
-                rrdDef.setStep(RESOLUTION);
+                rrdDef.setStep(RESOLUTION_IN_SECOND);
 
                 // raw archive, no aggregation is required
                 ArcDef rawArchive = new ArcDef(CONSOL_FUNCTION, XFF_VALUE,
@@ -296,7 +296,7 @@
         }
 
         private DsDef defineSchema(String metricType) {
-            return new DsDef(metricType, SOURCE_TYPE, RESOLUTION,
+            return new DsDef(metricType, SOURCE_TYPE, RESOLUTION_IN_SECOND,
                     MIN_VALUE, MAX_VALUE);
         }
     }
diff --git a/apps/cpman/app/src/main/resources/OSGI-INF/blueprint/shell-config.xml b/apps/cpman/app/src/main/resources/OSGI-INF/blueprint/shell-config.xml
new file mode 100644
index 0000000..095211f
--- /dev/null
+++ b/apps/cpman/app/src/main/resources/OSGI-INF/blueprint/shell-config.xml
@@ -0,0 +1,34 @@
+<!--
+  ~ Copyright 2016 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.
+  -->
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
+
+    <command-bundle xmlns="http://karaf.apache.org/xmlns/shell/v1.1.0">
+        <command>
+            <action class="org.onosproject.cpman.cli.ControlMetricsStatsListCommand"/>
+            <completers>
+                <ref component-id="controlResourceTypeCompleter"/>
+                <ref component-id="networkResourceNameCompleter"/>
+                <ref component-id="diskResourceNameCompleter"/>
+                <ref component-id="controlMessageDeviceIdCompleter"/>
+            </completers>
+        </command>
+    </command-bundle>
+
+    <bean id="controlResourceTypeCompleter" class="org.onosproject.cpman.cli.ControlResourceTypeCompleter"/>
+    <bean id="networkResourceNameCompleter" class="org.onosproject.cpman.cli.NetworkResourceNameCompleter"/>
+    <bean id="diskResourceNameCompleter" class="org.onosproject.cpman.cli.DiskResourceNameCompleter"/>
+    <bean id="controlMessageDeviceIdCompleter" class="org.onosproject.cpman.cli.ControlMessageDeviceIdCompleter"/>
+</blueprint>
\ No newline at end of file
diff --git a/apps/cpman/app/src/test/java/org/onosproject/cpman/impl/ControlPlaneMonitorTest.java b/apps/cpman/app/src/test/java/org/onosproject/cpman/impl/ControlPlaneMonitorTest.java
index 7c1afef..1ec963d 100644
--- a/apps/cpman/app/src/test/java/org/onosproject/cpman/impl/ControlPlaneMonitorTest.java
+++ b/apps/cpman/app/src/test/java/org/onosproject/cpman/impl/ControlPlaneMonitorTest.java
@@ -28,6 +28,7 @@
 import org.onosproject.net.DeviceId;
 
 import java.util.Optional;
+import java.util.Set;
 
 import static org.easymock.EasyMock.anyObject;
 import static org.easymock.EasyMock.createMock;
@@ -35,27 +36,8 @@
 import static org.easymock.EasyMock.replay;
 import static org.hamcrest.Matchers.is;
 import static org.junit.Assert.assertThat;
-import static org.onosproject.cpman.ControlMetricType.CPU_IDLE_TIME;
-import static org.onosproject.cpman.ControlMetricType.CPU_LOAD;
-import static org.onosproject.cpman.ControlMetricType.DISK_READ_BYTES;
-import static org.onosproject.cpman.ControlMetricType.DISK_WRITE_BYTES;
-import static org.onosproject.cpman.ControlMetricType.FLOW_MOD_PACKET;
-import static org.onosproject.cpman.ControlMetricType.FLOW_REMOVED_PACKET;
-import static org.onosproject.cpman.ControlMetricType.INBOUND_PACKET;
-import static org.onosproject.cpman.ControlMetricType.MEMORY_FREE;
-import static org.onosproject.cpman.ControlMetricType.MEMORY_FREE_RATIO;
-import static org.onosproject.cpman.ControlMetricType.MEMORY_USED;
-import static org.onosproject.cpman.ControlMetricType.MEMORY_USED_RATIO;
-import static org.onosproject.cpman.ControlMetricType.NW_INCOMING_BYTES;
-import static org.onosproject.cpman.ControlMetricType.NW_INCOMING_PACKETS;
-import static org.onosproject.cpman.ControlMetricType.NW_OUTGOING_BYTES;
-import static org.onosproject.cpman.ControlMetricType.NW_OUTGOING_PACKETS;
-import static org.onosproject.cpman.ControlMetricType.OUTBOUND_PACKET;
-import static org.onosproject.cpman.ControlMetricType.REPLY_PACKET;
-import static org.onosproject.cpman.ControlMetricType.REQUEST_PACKET;
-import static org.onosproject.cpman.ControlMetricType.SYS_CPU_TIME;
-import static org.onosproject.cpman.ControlMetricType.TOTAL_CPU_TIME;
-import static org.onosproject.cpman.ControlMetricType.USER_CPU_TIME;
+
+import static org.onosproject.cpman.ControlResource.*;
 
 /**
  * Unit test of control plane monitoring service.
@@ -67,23 +49,12 @@
     private ClusterService mockClusterService;
     private ControllerNode mockControllerNode;
     private NodeId nodeId;
-    private static final ImmutableSet<ControlMetricType> CPU_METRICS =
-            ImmutableSet.of(CPU_IDLE_TIME, CPU_LOAD, SYS_CPU_TIME,
-                    USER_CPU_TIME, TOTAL_CPU_TIME);
-    private static final ImmutableSet<ControlMetricType> MEMORY_METRICS =
-            ImmutableSet.of(MEMORY_FREE, MEMORY_FREE_RATIO, MEMORY_USED,
-                    MEMORY_USED_RATIO);
-    private static final ImmutableSet<ControlMetricType> DISK_METRICS =
-            ImmutableSet.of(DISK_READ_BYTES, DISK_WRITE_BYTES);
-    private static final ImmutableSet<ControlMetricType> NETWORK_METRICS =
-            ImmutableSet.of(NW_INCOMING_BYTES, NW_OUTGOING_BYTES,
-                    NW_INCOMING_PACKETS, NW_OUTGOING_PACKETS);
-    private static final ImmutableSet<ControlMetricType> CTRL_MSGS =
-            ImmutableSet.of(INBOUND_PACKET, OUTBOUND_PACKET, FLOW_MOD_PACKET,
-                    FLOW_REMOVED_PACKET, REQUEST_PACKET, REPLY_PACKET);
 
+    /**
+     * Sets up the services required by control plane monitor.
+     */
     @Before
-    public void setup() throws Exception {
+    public void setup() {
         monitor = new ControlPlaneMonitor();
         monitor.activate();
 
@@ -134,13 +105,13 @@
         assertThat(monitor.getLoad(nodeId, cmt, Optional.ofNullable(null)).latest(), is(mv.getLoad()));
     }
 
-    private void testUpdateMetricWithResource(ControlMetricType cmt, MetricValue mv, String resoureName) {
+    private void testUpdateMetricWithResource(ControlMetricType cmt, MetricValue mv, String resourceName) {
         ControlMetric cm = new ControlMetric(cmt, mv);
-        monitor.updateMetric(cm, UPDATE_INTERVAL, resoureName);
+        monitor.updateMetric(cm, UPDATE_INTERVAL, resourceName);
     }
 
-    private void testLoadMetricWithResource(ControlMetricType cmt, MetricValue mv, String resoureName) {
-        assertThat(monitor.getLoad(nodeId, cmt, resoureName).latest(), is(mv.getLoad()));
+    private void testLoadMetricWithResource(ControlMetricType cmt, MetricValue mv, String resourceName) {
+        assertThat(monitor.getLoad(nodeId, cmt, resourceName).latest(), is(mv.getLoad()));
     }
 
     private void testUpdateMetricWithId(ControlMetricType cmt, MetricValue mv, DeviceId did) {
@@ -152,6 +123,9 @@
         assertThat(monitor.getLoad(nodeId, cmt, Optional.of(did)).latest(), is(mv.getLoad()));
     }
 
+    /**
+     * Tests cpu metric update and load function.
+     */
     @Test
     public void testCpuMetric() {
         MetricValue mv = new MetricValue.Builder().load(30).add();
@@ -160,6 +134,9 @@
         CPU_METRICS.forEach(cmt -> testLoadMetricWithoutId(cmt, mv));
     }
 
+    /**
+     * Tests memory metric update and load function.
+     */
     @Test
     public void testMemoryMetric() {
         MetricValue mv = new MetricValue.Builder().load(40).add();
@@ -168,11 +145,14 @@
         MEMORY_METRICS.forEach(cmt -> testLoadMetricWithoutId(cmt, mv));
     }
 
+    /**
+     * Tests disk metric update and load function.
+     */
     @Test
     public void testDiskMetric() {
         MetricValue mv = new MetricValue.Builder().load(50).add();
 
-        ImmutableSet<String> set = ImmutableSet.of("disk1", "disk2");
+        Set<String> set = ImmutableSet.of("disk1", "disk2");
 
         set.forEach(disk -> DISK_METRICS.forEach(cmt ->
                 testUpdateMetricWithResource(cmt, mv, disk)));
@@ -181,11 +161,14 @@
                 testLoadMetricWithResource(cmt, mv, disk)));
     }
 
+    /**
+     * Tests network metric update and load function.
+     */
     @Test
     public void testNetworkMetric() {
         MetricValue mv = new MetricValue.Builder().load(10).add();
 
-        ImmutableSet<String> set = ImmutableSet.of("eth0", "eth1");
+        Set<String> set = ImmutableSet.of("eth0", "eth1");
 
         set.forEach(network -> NETWORK_METRICS.forEach(cmt ->
                 testUpdateMetricWithResource(cmt, mv, network)));
@@ -194,17 +177,40 @@
                 testLoadMetricWithResource(cmt, mv, network)));
     }
 
+    /**
+     * Tests control message update and load function.
+     */
     @Test
-    public void testUpdateControlMessage() {
+    public void testControlMessage() {
         MetricValue mv = new MetricValue.Builder().load(10).add();
+        Set<DeviceId> set = ImmutableSet.of(DeviceId.deviceId("of:0000000000000001"),
+                                            DeviceId.deviceId("of:0000000000000002"));
 
-        ImmutableSet<String> set = ImmutableSet.of("of:0000000000000001",
-                                                   "of:0000000000000002");
+        set.forEach(devId -> CONTROL_MESSAGE_METRICS.forEach(cmt ->
+                testUpdateMetricWithId(cmt, mv, devId)));
 
-        set.forEach(ctrlMsg -> CTRL_MSGS.forEach(cmt ->
-                testUpdateMetricWithId(cmt, mv, DeviceId.deviceId(ctrlMsg))));
+        set.forEach(devId -> CONTROL_MESSAGE_METRICS.forEach(cmt ->
+                testLoadMetricWithId(cmt, mv, devId)));
+    }
 
-        set.forEach(ctrlMsg -> CTRL_MSGS.forEach(cmt ->
-                testLoadMetricWithId(cmt, mv, DeviceId.deviceId(ctrlMsg))));
+    /**
+     * Tests available resource update and load function.
+     */
+    @Test
+    public void testAvailableResources() {
+        MetricValue mv = new MetricValue.Builder().load(50).add();
+
+        Set<String> diskSet = ImmutableSet.of("disk1", "disk2");
+
+        diskSet.forEach(disk -> DISK_METRICS.forEach(cmt ->
+                testUpdateMetricWithResource(cmt, mv, disk)));
+
+        Set<String> networkSet = ImmutableSet.of("eth0", "eth1");
+
+        networkSet.forEach(network -> NETWORK_METRICS.forEach(cmt ->
+                testUpdateMetricWithResource(cmt, mv, network)));
+
+        assertThat(monitor.availableResources(Type.DISK), is(diskSet));
+        assertThat(monitor.availableResources(Type.NETWORK), is(networkSet));
     }
 }
diff --git a/apps/cpman/app/src/test/java/org/onosproject/cpman/impl/MetricsDatabaseTest.java b/apps/cpman/app/src/test/java/org/onosproject/cpman/impl/MetricsDatabaseTest.java
index 6058227..713c7d8 100644
--- a/apps/cpman/app/src/test/java/org/onosproject/cpman/impl/MetricsDatabaseTest.java
+++ b/apps/cpman/app/src/test/java/org/onosproject/cpman/impl/MetricsDatabaseTest.java
@@ -39,7 +39,7 @@
     private static final String MEMORY_USED_PERC = "usedPerc";
 
     /**
-     * Initializes the MetricsDatabase instance.
+     * Initializes metrics database instance.
      */
     @Before
     public void setUp() {