ONOS-5419 Implementing new VPLS CLI

Change-Id: Id6a7ef785def15f5fcdc8d5ab8f9ab0f9a173065
diff --git a/apps/vpls/src/main/java/org/onosproject/vpls/Vpls.java b/apps/vpls/src/main/java/org/onosproject/vpls/Vpls.java
index 10f8254..c3d6264 100644
--- a/apps/vpls/src/main/java/org/onosproject/vpls/Vpls.java
+++ b/apps/vpls/src/main/java/org/onosproject/vpls/Vpls.java
@@ -11,7 +11,6 @@
  * 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.vpls;
 
diff --git a/apps/vpls/src/main/java/org/onosproject/vpls/cli/VplsAddCommand.java b/apps/vpls/src/main/java/org/onosproject/vpls/cli/VplsAddCommand.java
deleted file mode 100644
index b14d8f5..0000000
--- a/apps/vpls/src/main/java/org/onosproject/vpls/cli/VplsAddCommand.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * 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.vpls.cli;
-
-import org.apache.karaf.shell.commands.Argument;
-import org.apache.karaf.shell.commands.Command;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.vpls.config.VplsConfigService;
-
-import java.util.HashSet;
-
-/**
- * CLI to create VPLSs.
- */
-@Command(scope = "onos", name = "vpls-add", description = "Creates a new VPLS")
-public class VplsAddCommand extends AbstractShellCommand {
-
-    private VplsConfigService vplsConfigService =
-            get(VplsConfigService.class);
-
-    @Argument(index = 0, name = "vplsName", description = "Name of the VPLS",
-            required = true, multiValued = false)
-    private String vplsName = null;
-
-    @Override
-    protected void execute() {
-        // Check if the VPLS name is already configured
-        if (VplsCommandUtils.vplsExists(vplsName)) {
-            print(VplsCommandUtils.VPLS_ALREADY_EXISTS, vplsName);
-            return;
-        }
-
-        vplsConfigService.addVpls(vplsName, new HashSet<>(), null);
-    }
-}
diff --git a/apps/vpls/src/main/java/org/onosproject/vpls/cli/VplsAddIfaceCommand.java b/apps/vpls/src/main/java/org/onosproject/vpls/cli/VplsAddIfaceCommand.java
deleted file mode 100644
index c02b7e6..0000000
--- a/apps/vpls/src/main/java/org/onosproject/vpls/cli/VplsAddIfaceCommand.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * 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.vpls.cli;
-
-import org.apache.karaf.shell.commands.Argument;
-import org.apache.karaf.shell.commands.Command;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.vpls.config.VplsConfigService;
-
-/**
- * CLI to add an interface to a VPLS.
- */
-@Command(scope = "onos", name = "vpls-add-iface",
-        description = "Adds an interface to an existing VPLS")
-public class VplsAddIfaceCommand extends AbstractShellCommand {
-
-    private static VplsConfigService vplsConfigService =
-            get(VplsConfigService.class);
-
-    @Argument(index = 0, name = "vplsName", description = "Name of the VPLS",
-            required = true, multiValued = false)
-    private String vplsName = null;
-
-    @Argument(index = 1, name = "ifaceName", description = "Name of the interface" +
-            " to be added to the VPLS", required = true, multiValued = false)
-    private String ifaceName = null;
-
-    @Override
-    protected void execute() {
-        // Check if the VPLS exists
-        if (!VplsCommandUtils.vplsExists(vplsName)) {
-            print(VplsCommandUtils.VPLS_NOT_FOUND, vplsName);
-            return;
-        }
-
-        // Check if the interface exists
-        if (!VplsCommandUtils.ifaceExists(ifaceName)) {
-            print(VplsCommandUtils.IFACE_NOT_FOUND, ifaceName);
-            return;
-        }
-
-        // Check if the interface is already associated to a VPLS
-        if (VplsCommandUtils.ifaceAlreadyAssociated(ifaceName)) {
-            print(VplsCommandUtils.IFACE_ALREADY_ASSOCIATED,
-                  ifaceName, VplsCommandUtils.vplsNameFromIfaceName(ifaceName));
-            return;
-        }
-
-        vplsConfigService.addIface(vplsName, ifaceName);
-    }
-}
diff --git a/apps/vpls/src/main/java/org/onosproject/vpls/cli/VplsCleanCommand.java b/apps/vpls/src/main/java/org/onosproject/vpls/cli/VplsCleanCommand.java
deleted file mode 100644
index dcae5ee..0000000
--- a/apps/vpls/src/main/java/org/onosproject/vpls/cli/VplsCleanCommand.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * 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.vpls.cli;
-
-import org.apache.karaf.shell.commands.Command;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.vpls.config.VplsConfigService;
-
-/**
- * CLI to clean the VPLS app configuration.
- */
-@Command(scope = "onos", name = "vpls-clean",
-        description = "Cleans the VPLS app configuration")
-public class VplsCleanCommand extends AbstractShellCommand {
-    private VplsConfigService vplsConfigService =
-            get(VplsConfigService.class);
-
-    @Override
-    protected void execute() {
-        vplsConfigService.cleanVplsConfig();
-    }
-}
diff --git a/apps/vpls/src/main/java/org/onosproject/vpls/cli/VplsCommand.java b/apps/vpls/src/main/java/org/onosproject/vpls/cli/VplsCommand.java
new file mode 100644
index 0000000..8263373
--- /dev/null
+++ b/apps/vpls/src/main/java/org/onosproject/vpls/cli/VplsCommand.java
@@ -0,0 +1,374 @@
+/*
+ * 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
+ */
+package org.onosproject.vpls.cli;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.SetMultimap;
+import com.google.common.collect.Sets;
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.incubator.net.intf.Interface;
+import org.onosproject.incubator.net.intf.InterfaceService;
+import org.onosproject.net.EncapsulationType;
+import org.onosproject.vpls.config.VplsConfigService;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+
+import static com.google.common.base.Strings.isNullOrEmpty;
+
+/**
+ * CLI to interact with the VPLS application.
+ */
+@Command(scope = "onos", name = "vpls",
+        description = "Manages the VPLS application")
+public class VplsCommand extends AbstractShellCommand {
+
+    // Color codes and style
+    private static final String BOLD = "\u001B[1m";
+    private static final String COLOR_ERROR = "\u001B[31m";
+    private static final String RESET = "\u001B[0m";
+
+    // Messages and string formatter
+    private static final String ENCAP_NOT_FOUND =
+            COLOR_ERROR + "Encapsulation type " + BOLD + "%s" + RESET +
+                    COLOR_ERROR + " not found" + RESET;
+
+    private static final String IFACE_NOT_FOUND =
+            COLOR_ERROR + "Interface " + BOLD + "%s" + RESET + COLOR_ERROR +
+                    " not found" + RESET;
+
+    private static final String IFACE_ALREADY_ASSOCIATED =
+            COLOR_ERROR + "Interface " + BOLD + "%s" + RESET + COLOR_ERROR +
+                    " already associated to VPLS " + BOLD + "%s" + RESET +
+                    COLOR_ERROR + "" + RESET;
+
+    private static final String SEPARATOR = "----------------";
+
+    private static final String VPLS_ALREADY_EXISTS =
+            COLOR_ERROR + "VPLS " + BOLD + "%s" + RESET + COLOR_ERROR +
+                    " already exists" + RESET;
+
+    private static final String VPLS_COMMAND_NOT_FOUND =
+            COLOR_ERROR + "VPLS command " + BOLD + "%s" + RESET + COLOR_ERROR +
+                    " not found" + RESET;
+
+    private static final String VPLS_DISPLAY = "VPLS name: " + BOLD +
+            "%s" + RESET + "\nAssociated interfaces: %s\nEncapsulation: %s";
+
+    private static final String VPLS_LIST_TITLE =
+            BOLD + "Configured VPLSs" + RESET;
+
+    private static final String VPLS_NOT_FOUND =
+            COLOR_ERROR + "VPLS " + BOLD + "%s" + RESET + COLOR_ERROR +
+                    " not found" + RESET;
+
+    private static final String IFACE_NOT_ASSOCIATED =
+            COLOR_ERROR + "Interface " + BOLD + "%s" + RESET + COLOR_ERROR +
+                    " cannot be removed from VPLS " + BOLD + "%s" + RESET +
+                    COLOR_ERROR + ". The interface is associated to another" +
+                    "VPLS (" + BOLD + "%s" + RESET + COLOR_ERROR + ")" + RESET;
+
+    private static VplsConfigService vplsConfigService =
+            get(VplsConfigService.class);
+    private static InterfaceService interfaceService =
+            get(InterfaceService.class);
+
+    @Argument(index = 0, name = "command", description = "Command name (add|" +
+            "clean|create|delete|list|removeIface|set-encap|show)",
+            required = true, multiValued = false)
+    String command = null;
+
+    @Argument(index = 1, name = "vplsName", description = "The name of the VPLS",
+            required = false, multiValued = false)
+    String vplsName = null;
+
+    @Argument(index = 2, name = "optArg", description = "The interface name for" +
+            "all commands; the encapsulation type for set-encap",
+            required = false, multiValued = false)
+    String optArg = null;
+
+    @Override
+    protected void execute() {
+        VplsCommandEnum enumCommand = VplsCommandEnum.enumFromString(command);
+        if (enumCommand != null) {
+            switch (enumCommand) {
+                case ADD_IFACE:
+                    addIface(vplsName, optArg);
+                    break;
+                case CLEAN:
+                    clean();
+                    break;
+                case CREATE:
+                    create(vplsName);
+                    break;
+                case DELETE:
+                    delete(vplsName);
+                    break;
+                case LIST:
+                    list();
+                    break;
+                case REMOVE_IFACE:
+                    removeIface(vplsName, optArg);
+                    break;
+                case SET_ENCAP:
+                    setEncap(vplsName, optArg);
+                    break;
+                case SHOW:
+                    show(vplsName);
+                    break;
+                default:
+                    print(VPLS_COMMAND_NOT_FOUND, command);
+            }
+        }
+    }
+
+    /**
+     * Adds an inteterface to a VPLS.
+     *
+     * @param vplsName the name of the VLPS
+     * @param ifaceName the name of the interface to add
+     */
+    private void addIface(String vplsName, String ifaceName) {
+        // Check if the VPLS exists
+        if (!vplsExists(vplsName)) {
+            print(VPLS_NOT_FOUND, vplsName);
+            return;
+        }
+        // Check if the interface exists
+        if (!ifaceExists(ifaceName)) {
+            print(IFACE_NOT_FOUND, ifaceName);
+            return;
+        }
+        // Check if the interface is already associated to a VPLS
+        if (isIfaceAssociated(ifaceName)) {
+            print(IFACE_ALREADY_ASSOCIATED,
+                  ifaceName, vplsNameFromIfaceName(ifaceName));
+            return;
+        }
+
+        vplsConfigService.addIface(vplsName, ifaceName);
+    }
+
+    /**
+     * Cleans the VPLS configuration.
+     */
+    private void clean() {
+        vplsConfigService.cleanVplsConfig();
+    }
+
+    /**
+     * Creates a new VPLS.
+     *
+     * @param vplsName the name of the VLPS
+     */
+    private void create(String vplsName) {
+        if (vplsExists(vplsName)) {
+            print(VPLS_ALREADY_EXISTS, vplsName);
+            return;
+        }
+        vplsConfigService.addVpls(vplsName, Sets.newHashSet(), null);
+    }
+
+    /**
+     * Deletes a VPLS.
+     *
+     * @param vplsName the name of the VLPS
+     */
+    private void delete(String vplsName) {
+        if (!vplsExists(vplsName)) {
+            print(VPLS_NOT_FOUND, vplsName);
+            return;
+        }
+        vplsConfigService.removeVpls(vplsName);
+    }
+
+    /**
+     * Lists the configured VPLSs.
+     */
+    private void list() {
+        List<String> vplsNames = Lists.newArrayList(vplsConfigService.vplsNames());
+        Collections.sort(vplsNames);
+
+        print(VPLS_LIST_TITLE);
+        print(SEPARATOR);
+        vplsNames.forEach(vpls -> {
+            print(vpls);
+        });
+    }
+
+    /**
+     * Removes an interface from a VPLS.
+     *
+     * @param vplsName the name of the VLPS
+     * @param ifaceName the name of the interface to remove
+     */
+    private void removeIface(String vplsName, String ifaceName) {
+        if (!vplsExists(vplsName)) {
+            print(VPLS_NOT_FOUND, vplsName);
+            return;
+        }
+        if (!ifaceExists(ifaceName)) {
+            print(IFACE_NOT_FOUND, ifaceName);
+            return;
+        }
+        String vplsNameFromIfaceName = vplsNameFromIfaceName(ifaceName);
+        if (!vplsNameFromIfaceName.equals(vplsName)) {
+            print(IFACE_NOT_ASSOCIATED, ifaceName, vplsName, vplsNameFromIfaceName);
+            return;
+        }
+        vplsConfigService.removeIface(ifaceName);
+    }
+
+    /**
+     * Sets the encapsulation type for a VPLS.
+     *
+     * @param vplsName the name of the VPLS
+     * @param encap the encapsulation type
+     */
+    private void setEncap(String vplsName, String encap) {
+        if (!vplsExists(vplsName)) {
+            print(VPLS_NOT_FOUND, vplsName);
+            return;
+        }
+        EncapsulationType encapType = EncapsulationType.enumFromString(encap);
+        if (encapType.equals(EncapsulationType.NONE) &&
+            !encapType.toString().equals(encap)) {
+            print(ENCAP_NOT_FOUND, encap);
+            return;
+        }
+        vplsConfigService.setEncap(vplsName, encap);
+    }
+
+    /**
+     * Shows the details of one or more VPLSs.
+     *
+     * @param vplsName the name of the VPLS
+     */
+    private void show(String vplsName) {
+        List<String> vplsNames = Lists.newArrayList(vplsConfigService.vplsNames());
+        Collections.sort(vplsNames);
+
+        Map<String, EncapsulationType> encapByVplsName =
+                vplsConfigService.encapByVplsName();
+
+        print(VPLS_LIST_TITLE);
+        print(SEPARATOR);
+        if (!isNullOrEmpty(vplsName)) {
+            // A VPLS name is provided. Check first if the VPLS exists
+            if (vplsExists(vplsName)) {
+                print(VPLS_DISPLAY,
+                      vplsName,
+                      ifacesFromVplsName(vplsName).toString(),
+                      encapByVplsName.get(vplsName).toString());
+            } else {
+                print(VPLS_NOT_FOUND, vplsName);
+            }
+        } else {
+            // No VPLS names are provided. Display all VPLSs configured
+            vplsNames.forEach(v -> {
+                print(VPLS_DISPLAY,
+                      v,
+                      ifacesFromVplsName(v).toString(),
+                      encapByVplsName.get(v).toString());
+                print(SEPARATOR);
+            });
+        }
+    }
+
+    /**
+     * States if a VPLS exists or not.
+     *
+     * @param vplsName the name of the VPLS
+     * @return true if the VPLS exists; false otherwise
+     */
+    private static boolean vplsExists(String vplsName) {
+        return vplsConfigService.vplsNames().contains(vplsName);
+    }
+
+    /**
+     * States if an interface is defined or not in the system.
+     *
+     * @param ifaceName the name of the interface
+     * @return true if the interface is defined; false otherwise
+     */
+    private static boolean ifaceExists(String ifaceName) {
+        return vplsConfigService.allIfaces()
+                .stream()
+                .anyMatch(iface -> iface.name().equals(ifaceName));
+    }
+
+    /**
+     * States if an interface is already associated to a VPLS.
+     *
+     * @param ifaceName the name of the interface
+     * @return true if the interface is already associated to a VPLS; false
+     * otherwise
+     */
+    private static boolean isIfaceAssociated(String ifaceName) {
+        return vplsConfigService.ifaces()
+                .stream()
+                .anyMatch(iface -> iface.name().equals(ifaceName));
+    }
+
+    /**
+     * Returns the name of a VPLS, given the name of an interface associated to
+     * it.
+     *
+     * @param ifaceName the name of the interface
+     * @return the name of the VPLS that has the interface configured; null if
+     * the interface does not exist or is not associated to any VPLS
+     */
+    private static String vplsNameFromIfaceName(String ifaceName) {
+        String vplsName = null;
+
+        Optional<String> optVplsName = vplsConfigService.ifacesByVplsName()
+                .entries()
+                .stream()
+                .filter((entry -> entry.getValue().name().equals(ifaceName)))
+                .map(Map.Entry::getKey)
+                .findFirst();
+
+        if (optVplsName.isPresent()) {
+            vplsName = optVplsName.get();
+        }
+
+        return vplsName;
+    }
+
+    /**
+     * Returns a list of interfaces associated to a VPLS, given a VPLS name.
+     *
+     * @param vplsName the name of the VPLS
+     * @return the set of interfaces associated to the given VPLS; null if the
+     * VPLS is not found
+     */
+    private static Set<String> ifacesFromVplsName(String vplsName) {
+        if (!vplsExists(vplsName)) {
+            return null;
+        }
+        SetMultimap<String, Interface> ifacesByVplsName =
+                vplsConfigService.ifacesByVplsName();
+        Set<String> ifaceNames = Sets.newHashSet();
+
+        ifacesByVplsName.get(vplsName).forEach(iface -> ifaceNames.add(iface.name()));
+
+        return ifaceNames;
+    }
+}
diff --git a/apps/vpls/src/main/java/org/onosproject/vpls/cli/VplsCommandEnum.java b/apps/vpls/src/main/java/org/onosproject/vpls/cli/VplsCommandEnum.java
new file mode 100644
index 0000000..ebdaffc
--- /dev/null
+++ b/apps/vpls/src/main/java/org/onosproject/vpls/cli/VplsCommandEnum.java
@@ -0,0 +1,80 @@
+/*
+ * 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
+ */
+package org.onosproject.vpls.cli;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * Enum representing the VPLS command type.
+ */
+public enum VplsCommandEnum {
+    ADD_IFACE("add-if"),
+    CLEAN("clean"),
+    CREATE("create"),
+    DELETE("delete"),
+    LIST("list"),
+    REMOVE_IFACE("rem-if"),
+    SET_ENCAP("set-encap"),
+    SHOW("show");
+
+    private final String command;
+
+    /**
+     * Creates the enum from a string representing the command.
+     *
+     * @param command the text representing the command
+     */
+    private VplsCommandEnum(final String command) {
+        this.command = command;
+    }
+
+    @Override
+    public String toString() {
+        return command;
+    }
+
+    /**
+     * Returns a list of command string values.
+     *
+     * @return the list of string values corresponding to the enums
+     */
+    public static List<String> toStringList() {
+        return Arrays.stream(values())
+                .map(c -> c.toString())
+                .collect(Collectors.toCollection(ArrayList::new));
+    }
+
+    /**
+     * Alternative method to valueOf. It returns the command type
+     * corresponding to the given string. If the parameter does not match a
+     * constant name, or is null, null is returned.
+     *
+     * @param command the string representing the encapsulation type
+     * @return the EncapsulationType constant corresponding to the string given
+     */
+    public static VplsCommandEnum enumFromString(String command) {
+        if (command != null && !command.isEmpty()) {
+            for (VplsCommandEnum c : values()) {
+                if (command.toString().equalsIgnoreCase(c.toString())) {
+                    return c;
+                }
+            }
+        }
+        return null;
+    }
+}
diff --git a/apps/vpls/src/main/java/org/onosproject/vpls/cli/VplsCommandUtils.java b/apps/vpls/src/main/java/org/onosproject/vpls/cli/VplsCommandUtils.java
deleted file mode 100644
index 2a239b9..0000000
--- a/apps/vpls/src/main/java/org/onosproject/vpls/cli/VplsCommandUtils.java
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * 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.vpls.cli;
-
-import com.google.common.collect.SetMultimap;
-import com.google.common.collect.Sets;
-import org.onosproject.incubator.net.intf.Interface;
-import org.onosproject.incubator.net.intf.InterfaceService;
-import org.onosproject.vpls.config.VplsConfigService;
-
-import java.util.Map;
-import java.util.Optional;
-import java.util.Set;
-
-import static org.onlab.osgi.DefaultServiceDirectory.getService;
-
-/**
- * Util class for VPLS Commands.
- */
-public final class VplsCommandUtils {
-
-    protected static final String VPLS_NAME = "VPLS name %s: ";
-    protected static final String VPLS_DISPLAY = "VPLS name: %s, associated " +
-            "interfaces: %s, encapsulation: %s";
-    protected static final String VPLS_NOT_FOUND = "VPLS %s not found.";
-    protected static final String IFACE_NOT_FOUND = "Interface %s not found.";
-    protected static final String VPLS_ALREADY_EXISTS = "VPLS %s already exists.";
-    protected static final String IFACE_ALREADY_ASSOCIATED =
-            "Interface %s already associated to VPLS %s.";
-    protected static final String IFACE_NOT_ASSOCIATED =
-            "Interface %s is associated to VPLS %s.";
-
-    private static VplsConfigService vplsConfigService =
-            getService(VplsConfigService.class);
-    private static InterfaceService interfaceService =
-            getService(InterfaceService.class);
-
-    private VplsCommandUtils() {}
-
-    /**
-     * States if a VPLS exists or not.
-     *
-     * @param vplsName the name of the VPLS
-     * @return true if the VPLS exists; false otherwise
-     */
-    protected static boolean vplsExists(String vplsName) {
-        return vplsConfigService.vplsNames().contains(vplsName);
-    }
-
-    /**
-     * States if an interface is defined or not in the system.
-     *
-     * @param ifaceName the name of the interface
-     * @return true if the interface is defined; false otherwise
-     */
-    protected static boolean ifaceExists(String ifaceName) {
-        return interfaceService.getInterfaces()
-                .stream()
-                .anyMatch(iface -> iface.name().equals(ifaceName));
-    }
-
-    /**
-     * States if an interface is already associated or not to a VPLS.
-     *
-     * @param ifaceName the name of the interface
-     * @return true if the interface is already associated to a VPLS; false
-     * otherwise
-     */
-    protected static boolean ifaceAlreadyAssociated(String ifaceName) {
-        return vplsConfigService.allIfaces()
-                .stream()
-                .anyMatch(iface -> iface.name().equals(ifaceName));
-    }
-
-    /**
-     * Returns the name of a VPLS, given the name of an interface associated to
-     * it.
-     *
-     * @param ifaceName the name of the interface
-     * @return the name of the VPLS that has the interface configured; null if
-     * the interface does not exist or is not associated to any VPLS
-     */
-    protected static String vplsNameFromIfaceName(String ifaceName) {
-        String vplsName = null;
-
-        Optional<String> optVplsName = vplsConfigService.ifacesByVplsName()
-                .entries()
-                .stream()
-                .filter(iface -> iface.getValue().name().equals(ifaceName))
-                .map(Map.Entry::getKey)
-                .findFirst();
-
-        if (optVplsName.isPresent()) {
-            vplsName = optVplsName.get();
-        }
-
-        return vplsName;
-    }
-
-    /**
-     * Returns a list of interfaces associated to a VPLS, given a VPLS name.
-     *
-     * @param vplsName the name of the VPLS
-     * @return the set of interfaces associated to the given VPLS; null if the
-     * VPLS is not found
-     */
-    protected static Set<String> ifacesFromVplsName(String vplsName) {
-        if (!vplsExists(vplsName)) {
-            return null;
-        }
-
-        SetMultimap<String, Interface> ifacesByVplsName =
-                vplsConfigService.ifacesByVplsName();
-        Set<String> ifaceNames = Sets.newHashSet();
-
-        ifacesByVplsName.get(vplsName).forEach(iface -> ifaceNames.add(iface.name()));
-
-        return ifaceNames;
-    }
-}
diff --git a/apps/vpls/src/main/java/org/onosproject/vpls/cli/VplsDelCommand.java b/apps/vpls/src/main/java/org/onosproject/vpls/cli/VplsDelCommand.java
deleted file mode 100644
index 160e17d..0000000
--- a/apps/vpls/src/main/java/org/onosproject/vpls/cli/VplsDelCommand.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * 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.vpls.cli;
-
-import org.apache.karaf.shell.commands.Argument;
-import org.apache.karaf.shell.commands.Command;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.vpls.config.VplsConfigService;
-
-/**
- * CLI to remove VPLSs.
- */
-@Command(scope = "onos", name = "vpls-del",
-        description = "Deletes an existing VPLS")
-public class VplsDelCommand extends AbstractShellCommand {
-
-    private VplsConfigService vplsConfigService =
-            get(VplsConfigService.class);
-
-    @Argument(index = 0, name = "vplsName", description = "Name of the VPLS",
-            required = true, multiValued = false)
-    private String vplsName = null;
-
-    @Override
-    protected void execute() {
-        if (!VplsCommandUtils.vplsExists(vplsName)) {
-            print(VplsCommandUtils.VPLS_NOT_FOUND, vplsName);
-            return;
-        }
-
-        vplsConfigService.removeVpls(vplsName);
-    }
-}
diff --git a/apps/vpls/src/main/java/org/onosproject/vpls/cli/VplsDelIfaceCommand.java b/apps/vpls/src/main/java/org/onosproject/vpls/cli/VplsDelIfaceCommand.java
deleted file mode 100644
index 296e402..0000000
--- a/apps/vpls/src/main/java/org/onosproject/vpls/cli/VplsDelIfaceCommand.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * 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.vpls.cli;
-
-import org.apache.karaf.shell.commands.Argument;
-import org.apache.karaf.shell.commands.Command;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.vpls.config.VplsConfigService;
-
-/**
- * CLI to remove an interface from an existing VPLS.
- */
-@Command(scope = "onos", name = "vpls-del-iface",
-        description = "Removes an interface from an existing VPLS")
-public class VplsDelIfaceCommand extends AbstractShellCommand {
-
-    private VplsConfigService vplsConfigService =
-            get(VplsConfigService.class);
-
-    @Argument(index = 0, name = "vplsName", description = "Name of the VPLS",
-            required = true, multiValued = false)
-    private String vplsName = null;
-
-    @Argument(index = 1, name = "ifaceName", description = "Name of the interface" +
-            " to be removed from the VPLS", required = true, multiValued = false)
-    private String ifaceName = null;
-
-    @Override
-    protected void execute() {
-        if (!VplsCommandUtils.vplsExists(vplsName)) {
-            print(VplsCommandUtils.VPLS_NOT_FOUND, vplsName);
-            return;
-        }
-
-        if (!VplsCommandUtils.ifaceExists(ifaceName)) {
-            print(VplsCommandUtils.IFACE_NOT_FOUND, ifaceName);
-            return;
-        }
-
-        if (!VplsCommandUtils.ifaceAlreadyAssociated(ifaceName)) {
-            print(VplsCommandUtils.IFACE_NOT_ASSOCIATED,
-                  ifaceName, VplsCommandUtils.vplsNameFromIfaceName(ifaceName));
-            return;
-        }
-
-        vplsConfigService.removeIface(ifaceName);
-    }
-
-}
diff --git a/apps/vpls/src/main/java/org/onosproject/vpls/cli/VplsListCommand.java b/apps/vpls/src/main/java/org/onosproject/vpls/cli/VplsListCommand.java
deleted file mode 100644
index ba9ca5b..0000000
--- a/apps/vpls/src/main/java/org/onosproject/vpls/cli/VplsListCommand.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * 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.vpls.cli;
-
-import org.apache.karaf.shell.commands.Command;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.vpls.config.VplsConfigService;
-
-/**
- * CLI to list VPLSs.
- */
-@Command(scope = "onos", name = "vpls-list", description = "List the VPLSs configured")
-public class VplsListCommand extends AbstractShellCommand {
-    private VplsConfigService vplsConfigService =
-            get(VplsConfigService.class);
-
-    @Override
-    protected void execute() {
-        vplsConfigService.vplsNames().forEach(vpls -> {
-            print(VplsCommandUtils.VPLS_NAME, vpls);
-        });
-    }
-}
diff --git a/apps/vpls/src/main/java/org/onosproject/vpls/cli/VplsSetEncapCommand.java b/apps/vpls/src/main/java/org/onosproject/vpls/cli/VplsSetEncapCommand.java
deleted file mode 100644
index 9f06155..0000000
--- a/apps/vpls/src/main/java/org/onosproject/vpls/cli/VplsSetEncapCommand.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * 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.vpls.cli;
-
-import org.apache.karaf.shell.commands.Argument;
-import org.apache.karaf.shell.commands.Command;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.vpls.config.VplsConfigService;
-
-/**
- * CLI to set encapsulation for a VPLS.
- */
-@Command(scope = "onos", name = "vpls-set-encap",
-        description = "Sets the encapsulation type for a given VPLS. None means" +
-                "no encapsulation has been set")
-public class VplsSetEncapCommand extends AbstractShellCommand {
-
-    private static final String VPLS_NOT_FOUND = "VPLS %s not found.";
-    private VplsConfigService vplsConfigService =
-            get(VplsConfigService.class);
-
-    @Argument(index = 0, name = "vplsName", description = "Name of the VPLS",
-            required = true, multiValued = false)
-    private String vplsName = null;
-
-    @Argument(index = 1, name = "encapsulation", description = "The encapsulation" +
-            "type. For example, VLAN or MPLS. None for no encapsulation",
-            required = true, multiValued = false)
-    String encap = null;
-
-    @Override
-    protected void execute() {
-        if (!VplsCommandUtils.vplsExists(vplsName)) {
-            print(VplsCommandUtils.VPLS_NOT_FOUND, vplsName);
-            return;
-        }
-
-        vplsConfigService.setEncap(vplsName, encap);
-    }
-}
diff --git a/apps/vpls/src/main/java/org/onosproject/vpls/cli/VplsShowCommand.java b/apps/vpls/src/main/java/org/onosproject/vpls/cli/VplsShowCommand.java
deleted file mode 100644
index fbd54b5..0000000
--- a/apps/vpls/src/main/java/org/onosproject/vpls/cli/VplsShowCommand.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * 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.vpls.cli;
-
-import org.apache.karaf.shell.commands.Argument;
-import org.apache.karaf.shell.commands.Command;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.net.EncapsulationType;
-import org.onosproject.vpls.config.VplsConfigService;
-
-import java.util.Map;
-import java.util.Set;
-
-import static com.google.common.base.Strings.isNullOrEmpty;
-
-/**
- * CLI to show VPLS details.
- */
-@Command(scope = "onos", name = "vpls-show",
-        description = "Shows the details of an existing VPLS")
-public class VplsShowCommand extends AbstractShellCommand {
-
-    private VplsConfigService vplsConfigService =
-            get(VplsConfigService.class);
-
-    @Argument(index = 0, name = "vplsName", description = "Name of the VPLS",
-            required = false, multiValued = false)
-    private String vplsName = null;
-
-    @Override
-    protected void execute() {
-        Set<String> vplsNames = vplsConfigService.vplsNames();
-        Map<String, EncapsulationType> encapByVplsName =
-                vplsConfigService.encapByVplsName();
-
-        if (!isNullOrEmpty(vplsName)) {
-            // A VPLS name is provided. Check first if the VPLS exists
-            if (VplsCommandUtils.vplsExists(vplsName)) {
-                print(VplsCommandUtils.VPLS_DISPLAY,
-                      vplsName,
-                      VplsCommandUtils.ifacesFromVplsName(vplsName).toString(),
-                      encapByVplsName.get(vplsName).toString());
-            } else {
-                print(VplsCommandUtils.VPLS_NOT_FOUND, vplsName);
-            }
-        } else {
-            // No VPLS names are provided. Display all VPLSs configured
-            vplsNames.forEach(vplsName -> {
-                print(VplsCommandUtils.VPLS_DISPLAY,
-                      vplsName,
-                      VplsCommandUtils.ifacesFromVplsName(vplsName).toString(),
-                      encapByVplsName.get(vplsName).toString());
-            });
-        }
-    }
-}
diff --git a/apps/vpls/src/main/java/org/onosproject/vpls/cli/completer/VplsAddIfaceCommandCompleter.java b/apps/vpls/src/main/java/org/onosproject/vpls/cli/completer/VplsAddIfaceCommandCompleter.java
deleted file mode 100644
index 9591772..0000000
--- a/apps/vpls/src/main/java/org/onosproject/vpls/cli/completer/VplsAddIfaceCommandCompleter.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * 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.vpls.cli.completer;
-
-import com.google.common.collect.Lists;
-import org.onosproject.cli.AbstractChoicesCompleter;
-import org.onosproject.vpls.config.VplsConfigService;
-
-import java.util.List;
-import static org.onosproject.cli.AbstractShellCommand.get;
-
-/**
- * Completer for "vpls-add-inf" command.
- */
-public class VplsAddIfaceCommandCompleter extends AbstractChoicesCompleter {
-    @Override
-    protected List<String> choices() {
-        VplsConfigService vplsConfigService =
-                get(VplsConfigService.class);
-
-        return Lists.newArrayList(vplsConfigService.vplsNames());
-    }
-}
diff --git a/apps/vpls/src/main/java/org/onosproject/vpls/cli/completer/VplsCommandCompleter.java b/apps/vpls/src/main/java/org/onosproject/vpls/cli/completer/VplsCommandCompleter.java
new file mode 100644
index 0000000..cfe08b7
--- /dev/null
+++ b/apps/vpls/src/main/java/org/onosproject/vpls/cli/completer/VplsCommandCompleter.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2015-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.vpls.cli.completer;
+
+import com.google.common.collect.Lists;
+import org.onosproject.cli.AbstractChoicesCompleter;
+import org.onosproject.vpls.cli.VplsCommandEnum;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * VPLS command completer.
+ */
+public class VplsCommandCompleter extends AbstractChoicesCompleter {
+
+    @Override
+    public List<String> choices() {
+        List<String> argumentList =
+                Lists.newArrayList(getArgumentList().getArguments());
+        String argOne = null;
+        if (argumentList.size() > 1) {
+            argOne = argumentList.get(1);
+        }
+        VplsCommandEnum vplsCommandEnum = VplsCommandEnum.enumFromString(argOne);
+        if (vplsCommandEnum != null) {
+            switch (vplsCommandEnum) {
+                case CREATE:
+                case CLEAN:
+                case LIST:
+                    return Collections.emptyList();
+                default:
+                    VplsCommandEnum.toStringList();
+            }
+        }
+        return VplsCommandEnum.toStringList();
+    }
+}
diff --git a/apps/vpls/src/main/java/org/onosproject/vpls/cli/completer/VplsDelIfaceCommandCompleter.java b/apps/vpls/src/main/java/org/onosproject/vpls/cli/completer/VplsDelIfaceCommandCompleter.java
deleted file mode 100644
index ddaf359..0000000
--- a/apps/vpls/src/main/java/org/onosproject/vpls/cli/completer/VplsDelIfaceCommandCompleter.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * 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.vpls.cli.completer;
-
-import org.onosproject.cli.AbstractChoicesCompleter;
-import org.onosproject.incubator.net.intf.Interface;
-import org.onosproject.vpls.config.VplsConfigService;
-
-import java.util.List;
-import java.util.Set;
-import java.util.stream.Collectors;
-
-import static org.onosproject.cli.AbstractShellCommand.get;
-
-/**
- * Completer for vpls-del-iface command.
- */
-public class VplsDelIfaceCommandCompleter extends AbstractChoicesCompleter {
-
-    @Override
-    protected List<String> choices() {
-        VplsConfigService vplsConfigService =
-                get(VplsConfigService.class);
-        Set<Interface> ifaces = vplsConfigService.allIfaces();
-        return ifaces.stream().map(Interface::name).collect(Collectors.toList());
-    }
-}
diff --git a/apps/vpls/src/main/java/org/onosproject/vpls/cli/completer/VplsDelCommandCompleter.java b/apps/vpls/src/main/java/org/onosproject/vpls/cli/completer/VplsNameCompleter.java
similarity index 76%
rename from apps/vpls/src/main/java/org/onosproject/vpls/cli/completer/VplsDelCommandCompleter.java
rename to apps/vpls/src/main/java/org/onosproject/vpls/cli/completer/VplsNameCompleter.java
index 96ac364..ab2479b 100644
--- a/apps/vpls/src/main/java/org/onosproject/vpls/cli/completer/VplsDelCommandCompleter.java
+++ b/apps/vpls/src/main/java/org/onosproject/vpls/cli/completer/VplsNameCompleter.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2016-present Open Networking Laboratory
+ * Copyright 2015-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.
@@ -13,7 +13,6 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
 package org.onosproject.vpls.cli.completer;
 
 import com.google.common.collect.Lists;
@@ -25,14 +24,13 @@
 import static org.onosproject.cli.AbstractShellCommand.get;
 
 /**
- * Completer for "vpls-del" command.
+ * VPLS name completer.
  */
-public class VplsDelCommandCompleter extends AbstractChoicesCompleter {
+public class VplsNameCompleter extends AbstractChoicesCompleter {
 
     @Override
-    protected List<String> choices() {
-        VplsConfigService vplsConfigService =
-                get(VplsConfigService.class);
+    public List<String> choices() {
+        VplsConfigService vplsConfigService = get(VplsConfigService.class);
         return Lists.newArrayList(vplsConfigService.vplsNames());
     }
 }
diff --git a/apps/vpls/src/main/java/org/onosproject/vpls/cli/completer/VplsOptArgCompleter.java b/apps/vpls/src/main/java/org/onosproject/vpls/cli/completer/VplsOptArgCompleter.java
new file mode 100644
index 0000000..5b60352
--- /dev/null
+++ b/apps/vpls/src/main/java/org/onosproject/vpls/cli/completer/VplsOptArgCompleter.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2015-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.vpls.cli.completer;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+import org.apache.karaf.shell.console.completer.ArgumentCompleter;
+import org.onosproject.cli.AbstractChoicesCompleter;
+import org.onosproject.incubator.net.intf.Interface;
+import org.onosproject.net.EncapsulationType;
+import org.onosproject.vpls.cli.VplsCommandEnum;
+import org.onosproject.vpls.config.VplsConfigService;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import static org.onosproject.cli.AbstractShellCommand.get;
+
+/**
+ * VPLS optional argument completer.
+ */
+public class VplsOptArgCompleter extends AbstractChoicesCompleter {
+
+    @Override
+    public List<String> choices() {
+        VplsConfigService vplsConfigService = get(VplsConfigService.class);
+        List<String> argumentList =
+                Lists.newArrayList(getArgumentList().getArguments());
+        String argOne = argumentList.get(1);
+        VplsCommandEnum vplsCommandEnum = VplsCommandEnum.enumFromString(argOne);
+        if (vplsCommandEnum != null) {
+            switch (vplsCommandEnum) {
+                case ADD_IFACE:
+                    return availableIfaces(vplsConfigService);
+                case SET_ENCAP:
+                    return encap();
+                case REMOVE_IFACE:
+                    return vplsIfaces(vplsConfigService);
+                default:
+                    return Collections.emptyList();
+            }
+        }
+        return Collections.emptyList();
+    }
+
+    /**
+     * Returns the list of interfaces not yet assigned to any VPLS.
+     *
+     * @return the list of interfaces not yet assigned to any VPLS
+     */
+    private List<String> availableIfaces(VplsConfigService vplsConfigService) {
+        List<String> ifacesAvailable = Lists.newArrayList();
+        Set<Interface> allIfaces = Sets.newHashSet(vplsConfigService.allIfaces());
+        Set<Interface> usedIfaces = Sets.newHashSet(vplsConfigService.ifaces());
+
+        allIfaces.removeAll(usedIfaces);
+        allIfaces.forEach(iface -> ifacesAvailable.add(iface.name()));
+
+        return ifacesAvailable;
+    }
+
+    /**
+     * Returns the list of supported encapsulation types.
+     *
+     * @return the list of supported encapsualtion types
+     */
+    private List<String> encap() {
+        return Arrays.stream(EncapsulationType.values())
+                                              .map(Enum::toString)
+                                              .collect(Collectors.toList());
+    }
+
+    /**
+     * Returns the list of interfaces associated to a VPLS.
+     *
+     * @return the list of interfaces associated to a VPLS
+     */
+    private List<String> vplsIfaces(VplsConfigService vplsConfigService) {
+        ArgumentCompleter.ArgumentList list = getArgumentList();
+        String vplsName = list.getArguments()[2];
+
+        List<String> vplsIfaces = Lists.newArrayList();
+
+        Set<Interface> connectPoints = vplsConfigService.ifaces(vplsName);
+        connectPoints.forEach(iface -> vplsIfaces.add(iface.name()));
+
+        return vplsIfaces;
+    }
+}
diff --git a/apps/vpls/src/main/java/org/onosproject/vpls/cli/completer/VplsSetEncapCommandCompleter.java b/apps/vpls/src/main/java/org/onosproject/vpls/cli/completer/VplsSetEncapCommandCompleter.java
deleted file mode 100644
index 8ae7df2..0000000
--- a/apps/vpls/src/main/java/org/onosproject/vpls/cli/completer/VplsSetEncapCommandCompleter.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * 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.vpls.cli.completer;
-
-import com.google.common.collect.Lists;
-import org.onosproject.cli.AbstractChoicesCompleter;
-import org.onosproject.vpls.config.VplsConfigService;
-
-import java.util.List;
-
-import static org.onosproject.cli.AbstractShellCommand.get;
-
-/**
- * Completer for "vpls-set-encap" command.
- */
-public class VplsSetEncapCommandCompleter extends AbstractChoicesCompleter {
-    @Override
-    protected List<String> choices() {
-        VplsConfigService vplsConfigService =
-                get(VplsConfigService.class);
-
-        return Lists.newArrayList(vplsConfigService.vplsNames());
-    }
-}
diff --git a/apps/vpls/src/main/java/org/onosproject/vpls/cli/completer/VplsShowCommandCompleter.java b/apps/vpls/src/main/java/org/onosproject/vpls/cli/completer/VplsShowCommandCompleter.java
deleted file mode 100644
index 397d5c9..0000000
--- a/apps/vpls/src/main/java/org/onosproject/vpls/cli/completer/VplsShowCommandCompleter.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * 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.vpls.cli.completer;
-
-import com.google.common.collect.Lists;
-import org.onosproject.cli.AbstractChoicesCompleter;
-import org.onosproject.vpls.config.VplsConfigService;
-
-import java.util.List;
-
-import static org.onosproject.cli.AbstractShellCommand.get;
-
-/**
- * Completer for vpls-show command.
- */
-public class VplsShowCommandCompleter extends AbstractChoicesCompleter {
-
-    @Override
-    protected List<String> choices() {
-        VplsConfigService vplsConfigService =
-                get(VplsConfigService.class);
-        return Lists.newArrayList(vplsConfigService.vplsNames());
-    }
-}
diff --git a/apps/vpls/src/main/java/org/onosproject/vpls/config/VplsConfigService.java b/apps/vpls/src/main/java/org/onosproject/vpls/config/VplsConfigService.java
index 7500a08..2d2a576 100644
--- a/apps/vpls/src/main/java/org/onosproject/vpls/config/VplsConfigService.java
+++ b/apps/vpls/src/main/java/org/onosproject/vpls/config/VplsConfigService.java
@@ -91,24 +91,25 @@
     // TODO Remove this function after the intent framework race condition has been fixed
 
     /**
-     * Retrieves the interfaces from the VPLS configuration.
+     * Retrieves the interfaces without IP configured, so compatible with VPLS,
+     * from the interface service.
      *
-     * @return a set of interfaces contained in the VPLS configuration
+     * @return the set of interfaces configured, compatible with VPLS
      */
     Set<Interface> allIfaces();
 
     /**
-     * Retrieves the interfaces from the VPLS configuration.
+     * Retrieves the interfaces associated to a VPLS.
      *
-     * @return a set of interfaces belonging to the VPLS
+     * @return the set of interfaces associated to a VPLS
      */
     Set<Interface> ifaces();
 
     /**
-     * Retrieves the interfaces belonging to the VPLS.
+     * Retrieves the interfaces associated to the VPLS specified.
      *
      * @param vplsName the name of the VPLS
-     * @return a set of interfaces belonging to the VPLS
+     * @return the set of interfaces associated to the VPLS specified
      */
     Set<Interface> ifaces(String vplsName);
 
@@ -125,7 +126,7 @@
      * @return a set of VPLS names
      */
     Set<String> vplsNamesOld();
-    // TODO Removes this function after intent framework fix race condition
+    // TODO Removes this function after the race condition gets fixed in IF
 
     /**
      * Returns the VPLS names and associated interfaces from the configuration.
diff --git a/apps/vpls/src/main/java/org/onosproject/vpls/config/impl/VplsConfigImpl.java b/apps/vpls/src/main/java/org/onosproject/vpls/config/impl/VplsConfigImpl.java
index 658a27d..ad1c707 100644
--- a/apps/vpls/src/main/java/org/onosproject/vpls/config/impl/VplsConfigImpl.java
+++ b/apps/vpls/src/main/java/org/onosproject/vpls/config/impl/VplsConfigImpl.java
@@ -207,16 +207,19 @@
 
     @Override
     public Set<Interface> allIfaces() {
-        Set<Interface> allVplsInterfaces = new HashSet<>();
-        interfaceService.getInterfaces().forEach(allVplsInterfaces::add);
-        return allVplsInterfaces;
+        Set<Interface> interfaces = new HashSet<>();
+        interfaceService.getInterfaces().stream()
+                .filter(iface -> iface.ipAddressesList() == null ||
+                        iface.ipAddressesList().isEmpty())
+                .forEach(interfaces::add);
+        return interfaces;
     }
 
     @Override
     public Set<Interface> ifaces() {
-        Set<Interface> allVplsInterfaces = new HashSet<>();
-        vplsIfaces.values().forEach(allVplsInterfaces::add);
-        return allVplsInterfaces;
+        Set<Interface> interfaces = new HashSet<>();
+        vplsIfaces.values().forEach(interfaces::add);
+        return interfaces;
     }
 
     @Override
diff --git a/apps/vpls/src/main/resources/OSGI-INF/blueprint/shell-config.xml b/apps/vpls/src/main/resources/OSGI-INF/blueprint/shell-config.xml
index 3aa3bd3..ef9fd7e 100644
--- a/apps/vpls/src/main/resources/OSGI-INF/blueprint/shell-config.xml
+++ b/apps/vpls/src/main/resources/OSGI-INF/blueprint/shell-config.xml
@@ -1,5 +1,5 @@
 <!--
-  ~ Copyright 2016-present Open Networking Laboratory
+  ~ Copyright 2014-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.
@@ -11,61 +11,24 @@
   ~ 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.
+        ~ 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.vpls.cli.VplsAddCommand"/>
-    </command>
-    <command>
-      <action class="org.onosproject.vpls.cli.VplsAddIfaceCommand"/>
-      <completers>
-        <ref component-id="VplsAddIfaceCommandCompleter"/>
-        <null/>
-      </completers>
-    </command>
-    <command>
-      <action class="org.onosproject.vpls.cli.VplsDelCommand"/>
-      <completers>
-        <ref component-id="VplsDelCommandCompleter"/>
-        <null/>
-      </completers>
-    </command>
-    <command>
-      <action class="org.onosproject.vpls.cli.VplsDelIfaceCommand"/>
-      <completers>
-        <ref component-id="VplsDelIfaceCommandCompleter"/>
-        <null/>
-      </completers>
-    </command>
-    <command>
-      <action class="org.onosproject.vpls.cli.VplsListCommand"/>
-    </command>
-    <command>
-      <action class="org.onosproject.vpls.cli.VplsSetEncapCommand"/>
-      <completers>
-        <ref component-id="VplsSetEncapCommandCompleter"/>
-        <null/>
-      </completers>
-    </command>
-    <command>
-      <action class="org.onosproject.vpls.cli.VplsShowCommand"/>
-      <completers>
-        <ref component-id="VplsShowCommandCompleter"/>
-        <null/>
-      </completers>
-    </command>
-    <command>
-      <action class="org.onosproject.vpls.cli.VplsCleanCommand"/>
-    </command>
-  </command-bundle>
+    <command-bundle xmlns="http://karaf.apache.org/xmlns/shell/v1.1.0">
+        <command>
+            <action class="org.onosproject.vpls.cli.VplsCommand"/>
+            <completers>
+                <ref component-id="vplsCommandCompleter"/>
+                <ref component-id="vplsNameCompleter"/>
+                <ref component-id="vplsOptArgCompleter"/>
+                <ref component-id="nullCompleter"/>
+            </completers>
+        </command>
+    </command-bundle>
 
-  <bean id="VplsAddIfaceCommandCompleter" class="org.onosproject.vpls.cli.completer.VplsAddIfaceCommandCompleter"/>
-  <bean id="VplsDelCommandCompleter" class="org.onosproject.vpls.cli.completer.VplsDelCommandCompleter"/>
-  <bean id="VplsDelIfaceCommandCompleter" class="org.onosproject.vpls.cli.completer.VplsDelIfaceCommandCompleter"/>
-  <bean id="VplsSetEncapCommandCompleter" class="org.onosproject.vpls.cli.completer.VplsSetEncapCommandCompleter"/>
-  <bean id="VplsShowCommandCompleter" class="org.onosproject.vpls.cli.completer.VplsShowCommandCompleter"/>
+    <bean id="vplsCommandCompleter" class="org.onosproject.vpls.cli.completer.VplsCommandCompleter"/>
+    <bean id="vplsNameCompleter" class="org.onosproject.vpls.cli.completer.VplsNameCompleter"/>
+    <bean id="vplsOptArgCompleter" class="org.onosproject.vpls.cli.completer.VplsOptArgCompleter"/>
+    <bean id="nullCompleter" class="org.apache.karaf.shell.console.completer.NullCompleter"/>
 </blueprint>
\ No newline at end of file