summaryrefslogtreecommitdiffstats
path: root/framework/src/onos/cli/src/main/java
diff options
context:
space:
mode:
authorAshlee Young <ashlee@onosfw.com>2015-09-09 22:15:21 -0700
committerAshlee Young <ashlee@onosfw.com>2015-09-09 22:15:21 -0700
commit13d05bc8458758ee39cb829098241e89616717ee (patch)
tree22a4d1ce65f15952f07a3df5af4b462b4697cb3a /framework/src/onos/cli/src/main/java
parent6139282e1e93c2322076de4b91b1c85d0bc4a8b3 (diff)
ONOS checkin based on commit tag e796610b1f721d02f9b0e213cf6f7790c10ecd60
Change-Id: Ife8810491034fe7becdba75dda20de4267bd15cd
Diffstat (limited to 'framework/src/onos/cli/src/main/java')
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/AbstractChoicesCompleter.java38
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/AbstractCompleter.java39
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/AbstractShellCommand.java167
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/BalanceMastersCommand.java33
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/CliComponent.java39
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/Comparators.java126
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/MastersListCommand.java92
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/MetricNameCompleter.java34
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/MetricsListCommand.java167
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/NodeAddCommand.java50
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/NodeIdCompleter.java48
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/NodeRemoveCommand.java40
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/NodesListCommand.java88
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/PlaceholderCompleter.java40
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/RolesCommand.java101
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/StartStopCompleter.java34
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/SummaryCommand.java89
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/UiViewListCommand.java60
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/UpDownCompleter.java34
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/app/AllApplicationNamesCompleter.java54
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/app/ApplicationCommand.java103
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/app/ApplicationCommandCompleter.java34
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/app/ApplicationIdListCommand.java66
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/app/ApplicationIdWithIntentNameCompleter.java47
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/app/ApplicationNameCompleter.java77
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/app/ApplicationsListCommand.java100
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/app/package-info.java20
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/cfg/ComponentConfigCommand.java182
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/cfg/ComponentConfigCommandCompleter.java43
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/cfg/ComponentNameCompleter.java44
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/cfg/ComponentPropertyNameCompleter.java55
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/cfg/NetworkConfigCommand.java107
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/cfg/NetworkConfigRegistryCommand.java51
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/cfg/package-info.java20
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/AddHostToHostIntentCommand.java69
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/AddMeter.java68
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/AddMplsIntent.java91
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/AddMultiPointToSinglePointIntentCommand.java79
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/AddOpticalIntentCommand.java125
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/AddPointToPointIntentCommand.java73
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/AddSinglePointToMultiPointIntentCommand.java80
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/AddTestFlowsCommand.java170
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/AddressBindingsListCommand.java69
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/AnnotateDeviceCommand.java104
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/ClusterDevicesCommand.java63
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/ClusterIdCompleter.java50
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/ClusterLinksCommand.java54
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/ClustersListCommand.java66
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/ConnectPointCompleter.java54
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/ConnectivityIntentCommand.java403
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/CountersListCommand.java107
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/DeviceIdCompleter.java49
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/DevicePortStatsCommand.java192
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/DevicePortsListCommand.java149
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/DeviceRemoveCommand.java40
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/DeviceRoleCommand.java55
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/DevicesListCommand.java97
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/DriverNameCompleter.java44
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/DriversListCommand.java81
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/EdgePortsListCommand.java50
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/EthType.java84
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/EthTypeCompleter.java42
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/ExtHeader.java87
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/ExtHeaderCompleter.java42
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/FlowObjectiveCompositionCommand.java45
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/FlowRuleStatusCompleter.java45
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/FlowsListCommand.java169
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/GetStatistics.java85
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/GlobalLabelApplyCommand.java54
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/GlobalLabelCommand.java42
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/GlobalLabelPoolCreateCommand.java47
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/GlobalLabelPoolDestoryCommand.java31
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/GlobalLabelReleaseCommand.java48
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/GroupsListCommand.java134
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/HostIdCompleter.java50
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/HostRemoveCommand.java40
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/HostsListCommand.java90
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/Icmp6Code.java102
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/Icmp6CodeCompleter.java42
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/Icmp6Type.java100
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/Icmp6TypeCompleter.java42
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/IntentCycleCommand.java206
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/IntentKeyCompleter.java49
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/IntentPurgeCommand.java40
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/IntentPushTestCommand.java232
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/IntentRemoveCommand.java170
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/IntentsListCommand.java398
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/InterfacesListCommand.java52
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/IpProtocol.java80
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/IpProtocolCompleter.java42
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/LabelApplyCommand.java59
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/LabelPoolCreateCommand.java48
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/LabelPoolDestroyCommand.java36
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/LabelReleaseCommand.java59
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/LabelResourceCommand.java50
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/LeaderCommand.java194
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/LinkDstCompleter.java59
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/LinkResourceTestCommand.java123
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/LinkSrcCompleter.java48
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/LinksListCommand.java110
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/MapsListCommand.java84
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/Meters.java58
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/PartitionsListCommand.java109
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/PathListCommand.java97
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/RandomIntentCommand.java103
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/ResourceAllocationsCommand.java64
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/ResourceAvailableCommand.java80
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/RoleCompleter.java42
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/TopologyCommand.java122
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/TransactionsCommand.java98
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/TunnelBorrowCommand.java212
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/TunnelCreateCommand.java205
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/TunnelQueryCommand.java224
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/TunnelQuerySubscriptionCommand.java53
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/TunnelRemoveCommand.java203
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/TunnelReturnCommand.java198
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/TunnelUpdateCommand.java61
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/WipeOutCommand.java109
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/package-info.java21
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/package-info.java20
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/security/ReviewApplicationNameCompleter.java58
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/security/ReviewCommand.java122
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/security/package-info.java20
123 files changed, 10643 insertions, 0 deletions
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/AbstractChoicesCompleter.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/AbstractChoicesCompleter.java
new file mode 100644
index 00000000..b846fdeb
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/AbstractChoicesCompleter.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2015 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.cli;
+
+import org.apache.karaf.shell.console.completer.StringsCompleter;
+
+import java.util.List;
+import java.util.SortedSet;
+
+/**
+ * Abstraction of a completer with preset choices.
+ */
+public abstract class AbstractChoicesCompleter extends AbstractCompleter {
+
+ protected abstract List<String> choices();
+
+ @Override
+ public int complete(String buffer, int cursor, List<String> candidates) {
+ StringsCompleter delegate = new StringsCompleter();
+ SortedSet<String> strings = delegate.getStrings();
+ choices().forEach(strings::add);
+ return delegate.complete(buffer, cursor, candidates);
+ }
+
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/AbstractCompleter.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/AbstractCompleter.java
new file mode 100644
index 00000000..f232596c
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/AbstractCompleter.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2015 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.cli;
+
+import org.apache.felix.service.command.CommandSession;
+import org.apache.karaf.shell.console.CommandSessionHolder;
+import org.apache.karaf.shell.console.Completer;
+import org.apache.karaf.shell.console.completer.ArgumentCompleter;
+
+/**
+ * Abstract argument completer.
+ */
+public abstract class AbstractCompleter implements Completer {
+
+ /**
+ * Returns the argument list.
+ *
+ * @return argument list
+ */
+ protected ArgumentCompleter.ArgumentList getArgumentList() {
+ CommandSession session = CommandSessionHolder.getSession();
+ return (ArgumentCompleter.ArgumentList)
+ session.get(ArgumentCompleter.ARGUMENTS_LIST);
+ }
+
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/AbstractShellCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/AbstractShellCommand.java
new file mode 100644
index 00000000..8945d62a
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/AbstractShellCommand.java
@@ -0,0 +1,167 @@
+/*
+ * Copyright 2014-2015 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.cli;
+
+import org.apache.karaf.shell.commands.Option;
+import org.apache.karaf.shell.console.AbstractAction;
+import org.onlab.osgi.DefaultServiceDirectory;
+import org.onlab.osgi.ServiceNotFoundException;
+import org.onosproject.codec.CodecContext;
+import org.onosproject.codec.CodecService;
+import org.onosproject.codec.JsonCodec;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.CoreService;
+import org.onosproject.net.Annotations;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+/**
+ * Base abstraction of Karaf shell commands.
+ */
+public abstract class AbstractShellCommand extends AbstractAction implements CodecContext {
+
+ @Option(name = "-j", aliases = "--json", description = "Output JSON",
+ required = false, multiValued = false)
+ private boolean json = false;
+
+ /**
+ * Returns the reference to the implementation of the specified service.
+ *
+ * @param serviceClass service class
+ * @param <T> type of service
+ * @return service implementation
+ * @throws org.onlab.osgi.ServiceNotFoundException if service is unavailable
+ */
+ public static <T> T get(Class<T> serviceClass) {
+ return DefaultServiceDirectory.getService(serviceClass);
+ }
+
+ /**
+ * Returns application ID for the CLI.
+ *
+ * @return command-line application identifier
+ */
+ protected ApplicationId appId() {
+ return get(CoreService.class)
+ .registerApplication("org.onosproject.cli");
+ }
+
+ /**
+ * Prints the arguments using the specified format.
+ *
+ * @param format format string; see {@link String#format}
+ * @param args arguments
+ */
+ public void print(String format, Object... args) {
+ System.out.println(String.format(format, args));
+ }
+
+ /**
+ * Prints the arguments using the specified format to error stream.
+ *
+ * @param format format string; see {@link String#format}
+ * @param args arguments
+ */
+ public void error(String format, Object... args) {
+ System.err.println(String.format(format, args));
+ }
+
+ /**
+ * Produces a string image of the specified key/value annotations.
+ *
+ * @param annotations key/value annotations
+ * @return string image with ", k1=v1, k2=v2, ..." pairs
+ */
+ public static String annotations(Annotations annotations) {
+ StringBuilder sb = new StringBuilder();
+ for (String key : annotations.keys()) {
+ sb.append(", ").append(key).append('=').append(annotations.value(key));
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Produces a JSON object from the specified key/value annotations.
+ *
+ * @param mapper ObjectMapper to use while converting to JSON
+ * @param annotations key/value annotations
+ * @return JSON object
+ */
+ public static ObjectNode annotations(ObjectMapper mapper, Annotations annotations) {
+ ObjectNode result = mapper.createObjectNode();
+ for (String key : annotations.keys()) {
+ result.put(key, annotations.value(key));
+ }
+ return result;
+ }
+
+ /**
+ * Executes this command.
+ */
+ protected abstract void execute();
+
+ /**
+ * Indicates whether JSON format should be output.
+ *
+ * @return true if JSON is requested
+ */
+ protected boolean outputJson() {
+ return json;
+ }
+
+ @Override
+ protected Object doExecute() throws Exception {
+ try {
+ execute();
+ } catch (ServiceNotFoundException e) {
+ error(e.getMessage());
+ }
+ return null;
+ }
+
+
+
+ private final ObjectMapper mapper = new ObjectMapper();
+
+ @Override
+ public ObjectMapper mapper() {
+ return mapper;
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public <T> JsonCodec<T> codec(Class<T> entityClass) {
+ return get(CodecService.class).getCodec(entityClass);
+ }
+
+ @Override
+ public <T> T getService(Class<T> serviceClass) {
+ return get(serviceClass);
+ }
+
+ /**
+ * Generates a Json representation of an object.
+ *
+ * @param entity object to generate JSON for
+ * @param entityClass class to format with - this chooses which codec to use
+ * @param <T> Type of the object being formatted
+ * @return JSON object representation
+ */
+ public <T> ObjectNode jsonForEntity(T entity, Class<T> entityClass) {
+ return codec(entityClass).encode(entity, this);
+ }
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/BalanceMastersCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/BalanceMastersCommand.java
new file mode 100644
index 00000000..9a35ce34
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/BalanceMastersCommand.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2014 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.cli;
+
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.mastership.MastershipAdminService;
+
+/**
+ * Forces device mastership rebalancing.
+ */
+@Command(scope = "onos", name = "balance-masters",
+ description = "Forces device mastership rebalancing")
+public class BalanceMastersCommand extends AbstractShellCommand {
+
+ @Override
+ protected void execute() {
+ get(MastershipAdminService.class).balanceRoles();
+ }
+
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/CliComponent.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/CliComponent.java
new file mode 100644
index 00000000..6ae816bd
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/CliComponent.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2015 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.cli;
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.onosproject.core.CoreService;
+
+/**
+ * OSGI Component for the ONOS CLI.
+ */
+
+@Component(immediate = true)
+public class CliComponent {
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected CoreService coreService;
+
+ @Activate
+ public void activate() {
+ coreService
+ .registerApplication("org.onosproject.cli");
+ }
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/Comparators.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/Comparators.java
new file mode 100644
index 00000000..0ab6845f
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/Comparators.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright 2014-2015 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.cli;
+
+import org.onosproject.cluster.ControllerNode;
+import org.onosproject.core.Application;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.incubator.net.intf.Interface;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.Element;
+import org.onosproject.net.ElementId;
+import org.onosproject.net.Port;
+import org.onosproject.net.flow.FlowRule;
+import org.onosproject.net.group.Group;
+import org.onosproject.net.host.PortAddresses;
+import org.onosproject.net.topology.TopologyCluster;
+
+import java.util.Comparator;
+
+/**
+ * Various comparators.
+ */
+public final class Comparators {
+
+ // Ban construction
+ private Comparators() {
+ }
+
+ public static final Comparator<ApplicationId> APP_ID_COMPARATOR = new Comparator<ApplicationId>() {
+ @Override
+ public int compare(ApplicationId id1, ApplicationId id2) {
+ return id1.id() - id2.id();
+ }
+ };
+
+ public static final Comparator<Application> APP_COMPARATOR = new Comparator<Application>() {
+ @Override
+ public int compare(Application app1, Application app2) {
+ return app1.id().id() - app2.id().id();
+ }
+ };
+
+ public static final Comparator<ElementId> ELEMENT_ID_COMPARATOR = new Comparator<ElementId>() {
+ @Override
+ public int compare(ElementId id1, ElementId id2) {
+ return id1.toString().compareTo(id2.toString());
+ }
+ };
+
+ public static final Comparator<Element> ELEMENT_COMPARATOR = new Comparator<Element>() {
+ @Override
+ public int compare(Element e1, Element e2) {
+ return e1.id().toString().compareTo(e2.id().toString());
+ }
+ };
+
+ public static final Comparator<FlowRule> FLOW_RULE_COMPARATOR = new Comparator<FlowRule>() {
+ @Override
+ public int compare(FlowRule f1, FlowRule f2) {
+ return Long.valueOf(f1.id().value()).compareTo(f2.id().value());
+ }
+ };
+
+ public static final Comparator<Group> GROUP_COMPARATOR = new Comparator<Group>() {
+ @Override
+ public int compare(Group g1, Group g2) {
+ return Long.valueOf(g1.id().id()).compareTo(Long.valueOf(g2.id().id()));
+ }
+ };
+
+ public static final Comparator<Port> PORT_COMPARATOR = new Comparator<Port>() {
+ @Override
+ public int compare(Port p1, Port p2) {
+ long delta = p1.number().toLong() - p2.number().toLong();
+ return delta == 0 ? 0 : (delta < 0 ? -1 : +1);
+ }
+ };
+
+ public static final Comparator<TopologyCluster> CLUSTER_COMPARATOR = new Comparator<TopologyCluster>() {
+ @Override
+ public int compare(TopologyCluster c1, TopologyCluster c2) {
+ return c1.id().index() - c2.id().index();
+ }
+ };
+
+ public static final Comparator<ControllerNode> NODE_COMPARATOR = new Comparator<ControllerNode>() {
+ @Override
+ public int compare(ControllerNode ci1, ControllerNode ci2) {
+ return ci1.id().toString().compareTo(ci2.id().toString());
+ }
+ };
+
+ public static final Comparator<ConnectPoint> CONNECT_POINT_COMPARATOR = new Comparator<ConnectPoint>() {
+ @Override
+ public int compare(ConnectPoint o1, ConnectPoint o2) {
+ int compareId = ELEMENT_ID_COMPARATOR.compare(o1.elementId(), o2.elementId());
+ return (compareId != 0) ?
+ compareId :
+ Long.signum(o1.port().toLong() - o2.port().toLong());
+ }
+ };
+
+ public static final Comparator<PortAddresses> ADDRESSES_COMPARATOR = new Comparator<PortAddresses>() {
+ @Override
+ public int compare(PortAddresses arg0, PortAddresses arg1) {
+ return CONNECT_POINT_COMPARATOR.compare(arg0.connectPoint(), arg1.connectPoint());
+ }
+ };
+
+ public static final Comparator<Interface> INTERFACES_COMPARATOR = (intf1, intf2) ->
+ CONNECT_POINT_COMPARATOR.compare(intf1.connectPoint(), intf2.connectPoint());
+
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/MastersListCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/MastersListCommand.java
new file mode 100644
index 00000000..8675a3c8
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/MastersListCommand.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2014 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.cli;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.google.common.collect.Lists;
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cluster.ClusterService;
+import org.onosproject.cluster.ControllerNode;
+import org.onosproject.mastership.MastershipService;
+import org.onosproject.net.DeviceId;
+
+import java.util.Collections;
+import java.util.List;
+
+import static com.google.common.collect.Lists.newArrayList;
+
+/**
+ * Lists device mastership information.
+ */
+@Command(scope = "onos", name = "masters",
+ description = "Lists device mastership information")
+public class MastersListCommand extends AbstractShellCommand {
+
+ @Override
+ protected void execute() {
+ ClusterService service = get(ClusterService.class);
+ MastershipService mastershipService = get(MastershipService.class);
+ List<ControllerNode> nodes = newArrayList(service.getNodes());
+ Collections.sort(nodes, Comparators.NODE_COMPARATOR);
+
+ if (outputJson()) {
+ print("%s", json(service, mastershipService, nodes));
+ } else {
+ for (ControllerNode node : nodes) {
+ List<DeviceId> ids = Lists.newArrayList(mastershipService.getDevicesOf(node.id()));
+ Collections.sort(ids, Comparators.ELEMENT_ID_COMPARATOR);
+ print("%s: %d devices", node.id(), ids.size());
+ for (DeviceId deviceId : ids) {
+ print(" %s", deviceId);
+ }
+ }
+ }
+ }
+
+ // Produces JSON structure.
+ private JsonNode json(ClusterService service, MastershipService mastershipService,
+ List<ControllerNode> nodes) {
+ ObjectMapper mapper = new ObjectMapper();
+ ArrayNode result = mapper.createArrayNode();
+ ControllerNode self = service.getLocalNode();
+ for (ControllerNode node : nodes) {
+ List<DeviceId> ids = Lists.newArrayList(mastershipService.getDevicesOf(node.id()));
+ result.add(mapper.createObjectNode()
+ .put("id", node.id().toString())
+ .put("size", ids.size())
+ .set("devices", json(mapper, ids)));
+ }
+ return result;
+ }
+
+ /**
+ * Produces a JSON array containing the specified device identifiers.
+ *
+ * @param mapper object mapper
+ * @param ids collection of device identifiers
+ * @return JSON array
+ */
+ public static JsonNode json(ObjectMapper mapper, Iterable<DeviceId> ids) {
+ ArrayNode result = mapper.createArrayNode();
+ for (DeviceId deviceId : ids) {
+ result.add(deviceId.toString());
+ }
+ return result;
+ }
+
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/MetricNameCompleter.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/MetricNameCompleter.java
new file mode 100644
index 00000000..f05181f5
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/MetricNameCompleter.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2015 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.cli;
+
+import org.onlab.metrics.MetricsService;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Metric name completer.
+ */
+public class MetricNameCompleter extends AbstractChoicesCompleter {
+
+ @Override
+ protected List<String> choices() {
+ MetricsService metricsService = AbstractShellCommand.get(MetricsService.class);
+ return new ArrayList<String>(metricsService.getMetrics().keySet());
+ }
+
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/MetricsListCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/MetricsListCommand.java
new file mode 100644
index 00000000..9b80485b
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/MetricsListCommand.java
@@ -0,0 +1,167 @@
+/*
+ * Copyright 2014 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.cli;
+
+import com.codahale.metrics.Counter;
+import com.codahale.metrics.Gauge;
+import com.codahale.metrics.Histogram;
+import com.codahale.metrics.Meter;
+import com.codahale.metrics.Metric;
+import com.codahale.metrics.MetricFilter;
+import com.codahale.metrics.Snapshot;
+import com.codahale.metrics.Timer;
+import com.google.common.base.Strings;
+import com.google.common.collect.Ordering;
+import com.google.common.collect.TreeMultimap;
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.joda.time.LocalDateTime;
+import org.onlab.metrics.MetricsService;
+
+import java.util.Comparator;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import static java.lang.String.format;
+
+/**
+ * Prints metrics in the system.
+ */
+@Command(scope = "onos", name = "metrics",
+ description = "Prints metrics in the system")
+public class MetricsListCommand extends AbstractShellCommand {
+
+ @Argument(index = 0, name = "metricName", description = "Name of Metric",
+ required = false, multiValued = false)
+ String metricName = null;
+
+ @Override
+ protected void execute() {
+ MetricsService metricsService = get(MetricsService.class);
+
+ MetricFilter filter = metricName != null ? (name, metric) -> name.equals(metricName) : MetricFilter.ALL;
+
+ TreeMultimap<String, Metric> matched = listMetrics(metricsService, filter);
+ matched.asMap().forEach((name, metrics) -> {
+ for (Metric metric : metrics) {
+ printMetric(name, metric);
+ }
+ });
+ }
+
+ /**
+ * Print metric object.
+ *
+ * @param name metric name
+ * @param metric metric object
+ */
+ private void printMetric(String name, Metric metric) {
+ final String heading;
+
+ if (metric instanceof Counter) {
+ heading = format("-- %s : [%s] --", name, "Counter");
+ print(heading);
+ Counter counter = (Counter) metric;
+ print(" count = %d", counter.getCount());
+
+ } else if (metric instanceof Gauge) {
+ heading = format("-- %s : [%s] --", name, "Gauge");
+ print(heading);
+ @SuppressWarnings("rawtypes")
+ Gauge gauge = (Gauge) metric;
+ final Object value = gauge.getValue();
+ if (name.endsWith("EpochMs") && value instanceof Long) {
+ print(" value = %s (%s)", value, new LocalDateTime(value));
+ } else {
+ print(" value = %s", value);
+ }
+
+ } else if (metric instanceof Histogram) {
+ heading = format("-- %s : [%s] --", name, "Histogram");
+ print(heading);
+ final Histogram histogram = (Histogram) metric;
+ final Snapshot snapshot = histogram.getSnapshot();
+ print(" count = %d", histogram.getCount());
+ print(" min = %d", snapshot.getMin());
+ print(" max = %d", snapshot.getMax());
+ print(" mean = %f", snapshot.getMean());
+ print(" stddev = %f", snapshot.getStdDev());
+
+ } else if (metric instanceof Meter) {
+ heading = format("-- %s : [%s] --", name, "Meter");
+ print(heading);
+ final Meter meter = (Meter) metric;
+ print(" count = %d", meter.getCount());
+ print(" mean rate = %f", meter.getMeanRate());
+ print(" 1-minute rate = %f", meter.getOneMinuteRate());
+ print(" 5-minute rate = %f", meter.getFiveMinuteRate());
+ print(" 15-minute rate = %f", meter.getFifteenMinuteRate());
+
+ } else if (metric instanceof Timer) {
+ heading = format("-- %s : [%s] --", name, "Timer");
+ print(heading);
+ final Timer timer = (Timer) metric;
+ final Snapshot snapshot = timer.getSnapshot();
+ print(" count = %d", timer.getCount());
+ print(" mean rate = %f per second", timer.getMeanRate());
+ print(" 1-minute rate = %f per second", timer.getOneMinuteRate());
+ print(" 5-minute rate = %f per second", timer.getFiveMinuteRate());
+ print(" 15-minute rate = %f per second", timer.getFifteenMinuteRate());
+ print(" min = %f ms", nanoToMs(snapshot.getMin()));
+ print(" max = %f ms", nanoToMs(snapshot.getMax()));
+ print(" mean = %f ms", nanoToMs(snapshot.getMean()));
+ print(" stddev = %f ms", nanoToMs(snapshot.getStdDev()));
+ } else {
+ heading = format("-- %s : [%s] --", name, metric.getClass().getCanonicalName());
+ print(heading);
+ print("Unknown Metric type:{}", metric.getClass().getCanonicalName());
+ }
+ print(Strings.repeat("-", heading.length()));
+ }
+
+ @SuppressWarnings("rawtypes")
+ private TreeMultimap<String, Metric> listMetrics(MetricsService metricsService, MetricFilter filter) {
+ TreeMultimap<String, Metric> metrics = TreeMultimap.create(Comparator.naturalOrder(), Ordering.arbitrary());
+
+ Map<String, Counter> counters = metricsService.getCounters(filter);
+ for (Entry<String, Counter> entry : counters.entrySet()) {
+ metrics.put(entry.getKey(), entry.getValue());
+ }
+ Map<String, Gauge> gauges = metricsService.getGauges(filter);
+ for (Entry<String, Gauge> entry : gauges.entrySet()) {
+ metrics.put(entry.getKey(), entry.getValue());
+ }
+ Map<String, Histogram> histograms = metricsService.getHistograms(filter);
+ for (Entry<String, Histogram> entry : histograms.entrySet()) {
+ metrics.put(entry.getKey(), entry.getValue());
+ }
+ Map<String, Meter> meters = metricsService.getMeters(filter);
+ for (Entry<String, Meter> entry : meters.entrySet()) {
+ metrics.put(entry.getKey(), entry.getValue());
+ }
+ Map<String, Timer> timers = metricsService.getTimers(filter);
+ for (Entry<String, Timer> entry : timers.entrySet()) {
+ metrics.put(entry.getKey(), entry.getValue());
+ }
+
+ return metrics;
+ }
+
+ private double nanoToMs(double nano) {
+ return nano / 1_000_000D;
+ }
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/NodeAddCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/NodeAddCommand.java
new file mode 100644
index 00000000..37f59918
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/NodeAddCommand.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2014-2015 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.cli;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cluster.ClusterAdminService;
+import org.onosproject.cluster.DefaultControllerNode;
+import org.onosproject.cluster.NodeId;
+import org.onlab.packet.IpAddress;
+
+/**
+ * Adds a new controller cluster node.
+ */
+@Command(scope = "onos", name = "add-node",
+ description = "Adds a new controller cluster node")
+public class NodeAddCommand extends AbstractShellCommand {
+
+ @Argument(index = 0, name = "nodeId", description = "Node ID",
+ required = true, multiValued = false)
+ String nodeId = null;
+
+ @Argument(index = 1, name = "ip", description = "Node IP address",
+ required = true, multiValued = false)
+ String ip = null;
+
+ @Argument(index = 2, name = "tcpPort", description = "Node TCP listen port",
+ required = false, multiValued = false)
+ int tcpPort = DefaultControllerNode.DEFAULT_PORT;
+
+ @Override
+ protected void execute() {
+ ClusterAdminService service = get(ClusterAdminService.class);
+ service.addNode(new NodeId(nodeId), IpAddress.valueOf(ip), tcpPort);
+ }
+
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/NodeIdCompleter.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/NodeIdCompleter.java
new file mode 100644
index 00000000..8e6db7f4
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/NodeIdCompleter.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2014 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.cli;
+
+import org.apache.karaf.shell.console.Completer;
+import org.apache.karaf.shell.console.completer.StringsCompleter;
+import org.onosproject.cluster.ClusterService;
+import org.onosproject.cluster.ControllerNode;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.SortedSet;
+
+/**
+ * Node ID completer.
+ */
+public class NodeIdCompleter implements Completer {
+ @Override
+ public int complete(String buffer, int cursor, List<String> candidates) {
+ // Delegate string completer
+ StringsCompleter delegate = new StringsCompleter();
+
+ // Fetch our service and feed it's offerings to the string completer
+ ClusterService service = AbstractShellCommand.get(ClusterService.class);
+ Iterator<ControllerNode> it = service.getNodes().iterator();
+ SortedSet<String> strings = delegate.getStrings();
+ while (it.hasNext()) {
+ strings.add(it.next().id().toString());
+ }
+
+ // Now let the completer do the work for figuring out what to offer.
+ return delegate.complete(buffer, cursor, candidates);
+ }
+
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/NodeRemoveCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/NodeRemoveCommand.java
new file mode 100644
index 00000000..c2dbb546
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/NodeRemoveCommand.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2014 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.cli;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cluster.ClusterAdminService;
+import org.onosproject.cluster.NodeId;
+
+/**
+ * Removes a controller cluster node.
+ */
+@Command(scope = "onos", name = "remove-node",
+ description = "Removes a new controller cluster node")
+public class NodeRemoveCommand extends AbstractShellCommand {
+
+ @Argument(index = 0, name = "nodeId", description = "Node ID",
+ required = true, multiValued = false)
+ String nodeId = null;
+
+ @Override
+ protected void execute() {
+ ClusterAdminService service = get(ClusterAdminService.class);
+ service.removeNode(new NodeId(nodeId));
+ }
+
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/NodesListCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/NodesListCommand.java
new file mode 100644
index 00000000..50e8d534
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/NodesListCommand.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2014-2015 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.cli;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.apache.karaf.shell.commands.Command;
+import org.joda.time.DateTime;
+import org.onlab.util.Tools;
+import org.onosproject.cluster.ClusterService;
+import org.onosproject.cluster.ControllerNode;
+
+import java.util.Collections;
+import java.util.List;
+
+import static com.google.common.collect.Lists.newArrayList;
+
+
+/**
+ * Lists all controller cluster nodes.
+ */
+@Command(scope = "onos", name = "nodes",
+ description = "Lists all controller cluster nodes")
+public class NodesListCommand extends AbstractShellCommand {
+
+ private static final String FMT =
+ "id=%s, address=%s:%s, state=%s, updated=%s %s";
+
+ @Override
+ protected void execute() {
+ ClusterService service = get(ClusterService.class);
+ List<ControllerNode> nodes = newArrayList(service.getNodes());
+ Collections.sort(nodes, Comparators.NODE_COMPARATOR);
+ if (outputJson()) {
+ print("%s", json(service, nodes));
+ } else {
+ ControllerNode self = service.getLocalNode();
+ for (ControllerNode node : nodes) {
+ DateTime lastUpdated = service.getLastUpdated(node.id());
+ String timeAgo = "Never";
+ if (lastUpdated != null) {
+ timeAgo = Tools.timeAgo(lastUpdated.getMillis());
+ }
+ print(FMT, node.id(), node.ip(), node.tcpPort(),
+ service.getState(node.id()),
+ timeAgo,
+ node.equals(self) ? "*" : "");
+ }
+ }
+ }
+
+ // Produces JSON structure.
+ private JsonNode json(ClusterService service, List<ControllerNode> nodes) {
+ ObjectMapper mapper = new ObjectMapper();
+ ArrayNode result = mapper.createArrayNode();
+ ControllerNode self = service.getLocalNode();
+ for (ControllerNode node : nodes) {
+ ControllerNode.State nodeState = service.getState(node.id());
+ ObjectNode newNode = mapper.createObjectNode()
+ .put("id", node.id().toString())
+ .put("ip", node.ip().toString())
+ .put("tcpPort", node.tcpPort())
+ .put("self", node.equals(self));
+
+ if (nodeState != null) {
+ newNode.put("state", nodeState.toString());
+ }
+ result.add(newNode);
+ }
+ return result;
+ }
+
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/PlaceholderCompleter.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/PlaceholderCompleter.java
new file mode 100644
index 00000000..dbd2a971
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/PlaceholderCompleter.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2015 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.cli;
+
+import org.apache.karaf.shell.console.completer.StringsCompleter;
+
+import java.util.List;
+import java.util.SortedSet;
+
+/**
+ * A completer that can be used as a placeholder for arguments that don't
+ * need/want completers.
+ */
+public class PlaceholderCompleter extends AbstractCompleter {
+
+ @Override
+ public int complete(String s, int i, List<String> list) {
+ // Populate a string completer with what the user has typed so far
+ StringsCompleter delegate = new StringsCompleter();
+ SortedSet<String> strings = delegate.getStrings();
+ if (s != null) {
+ strings.add(s);
+ }
+ return delegate.complete(s, i, list);
+ }
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/RolesCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/RolesCommand.java
new file mode 100644
index 00000000..bc1e9102
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/RolesCommand.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2014 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.cli;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cluster.NodeId;
+import org.onosproject.cluster.RoleInfo;
+import org.onosproject.mastership.MastershipService;
+import org.onosproject.net.Device;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.device.DeviceService;
+
+import java.util.List;
+
+import static org.onosproject.cli.net.DevicesListCommand.getSortedDevices;
+
+/**
+ * Lists mastership roles of nodes for each device.
+ */
+@Command(scope = "onos", name = "roles",
+ description = "Lists mastership roles of nodes for each device.")
+public class RolesCommand extends AbstractShellCommand {
+
+ private static final String FMT_HDR = "%s: master=%s, standbys=[ %s]";
+
+ @Override
+ protected void execute() {
+ DeviceService deviceService = get(DeviceService.class);
+ MastershipService roleService = get(MastershipService.class);
+
+ if (outputJson()) {
+ print("%s", json(roleService, getSortedDevices(deviceService)));
+ } else {
+ for (Device d : getSortedDevices(deviceService)) {
+ DeviceId did = d.id();
+ printRoles(roleService, did);
+ }
+ }
+ }
+
+ // Produces JSON structure with role information for the given devices.
+ private JsonNode json(MastershipService service, List<Device> sortedDevices) {
+ ObjectMapper mapper = new ObjectMapper();
+ ArrayNode results = mapper.createArrayNode();
+ for (Device device : sortedDevices) {
+ results.add(json(service, mapper, device));
+ }
+ return results;
+ }
+
+ // Produces JSON structure with role information for the given device.
+ private JsonNode json(MastershipService service, ObjectMapper mapper,
+ Device device) {
+ NodeId master = service.getMasterFor(device.id());
+ ObjectNode result = mapper.createObjectNode()
+ .put("id", device.id().toString())
+ .put("master", master != null ? master.toString() : "none");
+ RoleInfo nodes = service.getNodesFor(device.id());
+ ArrayNode standbys = mapper.createArrayNode();
+ for (NodeId nid : nodes.backups()) {
+ standbys.add(nid.toString());
+ }
+ result.set("standbys", standbys);
+ return result;
+ }
+
+ /**
+ * Prints the role information for a device.
+ *
+ * @param service mastership service
+ * @param deviceId the ID of the device
+ */
+ protected void printRoles(MastershipService service, DeviceId deviceId) {
+ RoleInfo nodes = service.getNodesFor(deviceId);
+ StringBuilder builder = new StringBuilder();
+ for (NodeId nid : nodes.backups()) {
+ builder.append(nid).append(" ");
+ }
+
+ print(FMT_HDR, deviceId,
+ nodes.master() == null ? "NONE" : nodes.master(),
+ builder.toString());
+ }
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/StartStopCompleter.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/StartStopCompleter.java
new file mode 100644
index 00000000..b9d9b0f8
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/StartStopCompleter.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2015 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.cli;
+
+import com.google.common.collect.ImmutableList;
+
+import java.util.List;
+
+/**
+ * Start/stop command completer.
+ */
+public class StartStopCompleter extends AbstractChoicesCompleter {
+
+ public static final String START = "start";
+ public static final String STOP = "stop";
+
+ @Override
+ public List<String> choices() {
+ return ImmutableList.of(START, STOP);
+ }
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/SummaryCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/SummaryCommand.java
new file mode 100644
index 00000000..65f4cf97
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/SummaryCommand.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2014-2015 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.cli;
+
+import java.util.Set;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cluster.ControllerNode;
+import org.onosproject.core.CoreService;
+import org.onosproject.cluster.ClusterService;
+import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.flow.FlowRuleService;
+import org.onosproject.net.host.HostService;
+import org.onosproject.net.intent.IntentService;
+import org.onosproject.net.link.LinkService;
+import org.onosproject.net.topology.Topology;
+import org.onosproject.net.topology.TopologyService;
+
+/**
+ * Provides summary of ONOS model.
+ */
+@Command(scope = "onos", name = "summary",
+ description = "Provides summary of ONOS model")
+public class SummaryCommand extends AbstractShellCommand {
+
+ /**
+ * Count the active ONOS controller nodes.
+ *
+ * @param nodes set of all of the controller nodes in the cluster
+ * @return count of active nodes
+ */
+ private int activeNodes(Set<ControllerNode> nodes) {
+ int nodeCount = 0;
+
+ for (final ControllerNode node : nodes) {
+ final ControllerNode.State nodeState =
+ get(ClusterService.class).getState(node.id());
+ if (nodeState == ControllerNode.State.ACTIVE) {
+ nodeCount++;
+ }
+ }
+ return nodeCount;
+ }
+
+ @Override
+ protected void execute() {
+ TopologyService topologyService = get(TopologyService.class);
+ Topology topology = topologyService.currentTopology();
+ if (outputJson()) {
+ print("%s", new ObjectMapper().createObjectNode()
+ .put("node", get(ClusterService.class).getLocalNode().ip().toString())
+ .put("version", get(CoreService.class).version().toString())
+ .put("nodes", get(ClusterService.class).getNodes().size())
+ .put("devices", topology.deviceCount())
+ .put("links", topology.linkCount())
+ .put("hosts", get(HostService.class).getHostCount())
+ .put("SCC(s)", topology.clusterCount())
+ .put("flows", get(FlowRuleService.class).getFlowRuleCount())
+ .put("intents", get(IntentService.class).getIntentCount()));
+ } else {
+ print("node=%s, version=%s",
+ get(ClusterService.class).getLocalNode().ip(),
+ get(CoreService.class).version().toString());
+ print("nodes=%d, devices=%d, links=%d, hosts=%d, SCC(s)=%s, flows=%d, intents=%d",
+ activeNodes(get(ClusterService.class).getNodes()),
+ get(DeviceService.class).getDeviceCount(),
+ get(LinkService.class).getLinkCount(),
+ get(HostService.class).getHostCount(),
+ topologyService.getClusters(topology).size(),
+ get(FlowRuleService.class).getFlowRuleCount(),
+ get(IntentService.class).getIntentCount());
+ }
+ }
+
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/UiViewListCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/UiViewListCommand.java
new file mode 100644
index 00000000..33a85e68
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/UiViewListCommand.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2015 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.cli;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.ui.UiExtension;
+import org.onosproject.ui.UiExtensionService;
+
+import java.util.List;
+
+/**
+ * Lists all UI views.
+ */
+@Command(scope = "onos", name = "ui-views",
+ description = "Lists all UI views")
+public class UiViewListCommand extends AbstractShellCommand {
+
+ private static final String FMT = "id=%s, category=%s, label=%s, icon=%s";
+
+ @Override
+ protected void execute() {
+ UiExtensionService service = get(UiExtensionService.class);
+ if (outputJson()) {
+ print("%s", json(service.getExtensions()));
+ } else {
+ service.getExtensions().forEach(ext -> ext.views()
+ .forEach(v -> print(FMT, v.id(), v.category().label(),
+ v.label(), v.iconId())));
+ }
+ }
+
+ private JsonNode json(List<UiExtension> extensions) {
+ ObjectMapper mapper = new ObjectMapper();
+ ArrayNode node = mapper.createArrayNode();
+ extensions.forEach(ext -> ext.views()
+ .forEach(v -> node.add(mapper.createObjectNode()
+ .put("id", v.id())
+ .put("category", v.category().label())
+ .put("label", v.label())
+ .put("icon", v.iconId()))));
+ return node;
+ }
+
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/UpDownCompleter.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/UpDownCompleter.java
new file mode 100644
index 00000000..9d8eda5c
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/UpDownCompleter.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2015 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.cli;
+
+import com.google.common.collect.ImmutableList;
+
+import java.util.List;
+
+/**
+ * Up/down command completer.
+ */
+public class UpDownCompleter extends AbstractChoicesCompleter {
+
+ public static final String UP = "up";
+ public static final String DOWN = "down";
+
+ @Override
+ public List<String> choices() {
+ return ImmutableList.of(UP, DOWN);
+ }
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/app/AllApplicationNamesCompleter.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/app/AllApplicationNamesCompleter.java
new file mode 100644
index 00000000..9006369b
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/app/AllApplicationNamesCompleter.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2015 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.cli.app;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Spliterator;
+import java.util.Spliterators;
+import java.util.stream.StreamSupport;
+
+import org.onosproject.app.ApplicationService;
+import org.onosproject.cli.AbstractChoicesCompleter;
+import org.onosproject.core.Application;
+
+import static java.util.stream.Collectors.toList;
+import static org.onosproject.app.ApplicationState.INSTALLED;
+import static org.onosproject.cli.AbstractShellCommand.get;
+
+/**
+ * All installed application name completer.
+ */
+public class AllApplicationNamesCompleter extends AbstractChoicesCompleter {
+ @Override
+ public List<String> choices() {
+
+ // Fetch the service and return the list of app names
+ ApplicationService service = get(ApplicationService.class);
+ Iterator<Application> it = service.getApplications().iterator();
+
+ // Filter the list of apps, selecting only the installed ones.
+ // Add each app name to the list of choices.
+ return
+ StreamSupport.stream(
+ Spliterators.spliteratorUnknownSize(it, Spliterator.ORDERED), false)
+ .filter(app -> service.getState(app.id()) == INSTALLED)
+ .map(app -> app.id().name())
+ .collect(toList());
+
+ }
+
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/app/ApplicationCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/app/ApplicationCommand.java
new file mode 100644
index 00000000..9d40c660
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/app/ApplicationCommand.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2015 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.cli.app;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.app.ApplicationAdminService;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.core.ApplicationId;
+
+import java.io.IOException;
+import java.net.URL;
+
+/**
+ * Manages application inventory.
+ */
+@Command(scope = "onos", name = "app",
+ description = "Manages application inventory")
+public class ApplicationCommand extends AbstractShellCommand {
+
+ static final String INSTALL = "install";
+ static final String UNINSTALL = "uninstall";
+ static final String ACTIVATE = "activate";
+ static final String DEACTIVATE = "deactivate";
+
+ @Argument(index = 0, name = "command",
+ description = "Command name (install|activate|deactivate|uninstall)",
+ required = true, multiValued = false)
+ String command = null;
+
+ @Argument(index = 1, name = "names", description = "Application name(s) or URL(s)",
+ required = true, multiValued = true)
+ String[] names = null;
+
+ @Override
+ protected void execute() {
+ ApplicationAdminService service = get(ApplicationAdminService.class);
+ if (command.equals(INSTALL)) {
+ for (String name : names) {
+ if (!installApp(service, name)) {
+ return;
+ }
+ }
+
+ } else {
+ for (String name : names) {
+ if (!manageApp(service, name)) {
+ return;
+ }
+ }
+ }
+ }
+
+ // Installs the application from input of the specified URL
+ private boolean installApp(ApplicationAdminService service, String url) {
+ try {
+ if (url.equals("-")) {
+ service.install(System.in);
+ } else {
+ service.install(new URL(url).openStream());
+ }
+ } catch (IOException e) {
+ error("Unable to get URL: %s", url);
+ return false;
+ }
+ return true;
+ }
+
+ // Manages the specified application.
+ private boolean manageApp(ApplicationAdminService service, String name) {
+ ApplicationId appId = service.getId(name);
+ if (appId == null) {
+ print("No such application: %s", name);
+ return false;
+ }
+
+ if (command.equals(UNINSTALL)) {
+ service.uninstall(appId);
+ } else if (command.equals(ACTIVATE)) {
+ service.activate(appId);
+ } else if (command.equals(DEACTIVATE)) {
+ service.deactivate(appId);
+ } else {
+ print("Unsupported command: %s", command);
+ return false;
+ }
+ return true;
+ }
+
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/app/ApplicationCommandCompleter.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/app/ApplicationCommandCompleter.java
new file mode 100644
index 00000000..51611ff5
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/app/ApplicationCommandCompleter.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2015 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.cli.app;
+
+import com.google.common.collect.ImmutableList;
+import org.onosproject.cli.AbstractChoicesCompleter;
+
+import java.util.List;
+
+import static org.onosproject.cli.app.ApplicationCommand.*;
+
+/**
+ * Application command completer.
+ */
+public class ApplicationCommandCompleter extends AbstractChoicesCompleter {
+ @Override
+ public List<String> choices() {
+ return ImmutableList.of(INSTALL, UNINSTALL, ACTIVATE, DEACTIVATE);
+ }
+
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/app/ApplicationIdListCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/app/ApplicationIdListCommand.java
new file mode 100644
index 00000000..3088a94c
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/app/ApplicationIdListCommand.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2014-2015 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.cli.app;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.cli.Comparators;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.CoreService;
+
+import java.util.Collections;
+import java.util.List;
+
+import static com.google.common.collect.Lists.newArrayList;
+
+/**
+ * Lists application ID information.
+ */
+@Command(scope = "onos", name = "app-ids",
+ description = "Lists application ID information")
+public class ApplicationIdListCommand extends AbstractShellCommand {
+
+ @Override
+ protected void execute() {
+ CoreService service = get(CoreService.class);
+ List<ApplicationId> ids = newArrayList(service.getAppIds());
+ Collections.sort(ids, Comparators.APP_ID_COMPARATOR);
+
+ if (outputJson()) {
+ print("%s", json(ids));
+ } else {
+ for (ApplicationId id : ids) {
+ print("id=%d, name=%s", id.id(), id.name());
+ }
+ }
+ }
+
+ // ApplicationId
+ private JsonNode json(List<ApplicationId> ids) {
+ ObjectMapper mapper = new ObjectMapper();
+ ArrayNode result = mapper.createArrayNode();
+ for (ApplicationId id : ids) {
+ result.add(mapper.createObjectNode()
+ .put("id", id.id())
+ .put("name", id.name()));
+ }
+ return result;
+ }
+
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/app/ApplicationIdWithIntentNameCompleter.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/app/ApplicationIdWithIntentNameCompleter.java
new file mode 100644
index 00000000..2539ca72
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/app/ApplicationIdWithIntentNameCompleter.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2015 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.cli.app;
+
+import java.util.List;
+import java.util.SortedSet;
+
+import org.apache.karaf.shell.console.Completer;
+import org.apache.karaf.shell.console.completer.StringsCompleter;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.net.intent.IntentService;
+
+/**
+ * Application name completer.
+ */
+public class ApplicationIdWithIntentNameCompleter implements Completer {
+ @Override
+ public int complete(String buffer, int cursor, List<String> candidates) {
+ // Delegate string completer
+ StringsCompleter delegate = new StringsCompleter();
+
+ // Fetch our service and feed it's offerings to the string completer
+ IntentService service = AbstractShellCommand.get(IntentService.class);
+ SortedSet<String> strings = delegate.getStrings();
+
+ service.getIntents()
+ .forEach(intent ->
+ strings.add(intent.appId().name()));
+
+ // Now let the completer do the work for figuring out what to offer.
+ return delegate.complete(buffer, cursor, candidates);
+ }
+
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/app/ApplicationNameCompleter.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/app/ApplicationNameCompleter.java
new file mode 100644
index 00000000..17461696
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/app/ApplicationNameCompleter.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2015 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.cli.app;
+
+import org.apache.karaf.shell.console.completer.ArgumentCompleter;
+import org.apache.karaf.shell.console.completer.StringsCompleter;
+import org.onosproject.app.ApplicationService;
+import org.onosproject.app.ApplicationState;
+import org.onosproject.cli.AbstractCompleter;
+import org.onosproject.core.Application;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.SortedSet;
+
+import static org.onosproject.app.ApplicationState.ACTIVE;
+import static org.onosproject.app.ApplicationState.INSTALLED;
+import static org.onosproject.cli.AbstractShellCommand.get;
+
+/**
+ * Application name completer.
+ */
+public class ApplicationNameCompleter extends AbstractCompleter {
+ @Override
+ public int complete(String buffer, int cursor, List<String> candidates) {
+ // Delegate string completer
+ StringsCompleter delegate = new StringsCompleter();
+
+ // Command name is the second argument.
+ ArgumentCompleter.ArgumentList list = getArgumentList();
+ String cmd = list.getArguments()[1];
+
+ // Grab apps already on the command (to prevent tab-completed duplicates)
+ // FIXME: This does not work.
+// final Set previousApps;
+// if (list.getArguments().length > 2) {
+// previousApps = Sets.newHashSet(
+// Arrays.copyOfRange(list.getArguments(), 2, list.getArguments().length));
+// } else {
+// previousApps = Collections.emptySet();
+// }
+
+ // Fetch our service and feed it's offerings to the string completer
+ ApplicationService service = get(ApplicationService.class);
+ Iterator<Application> it = service.getApplications().iterator();
+ SortedSet<String> strings = delegate.getStrings();
+ while (it.hasNext()) {
+ Application app = it.next();
+ ApplicationState state = service.getState(app.id());
+// if (previousApps.contains(app.id().name())) {
+// continue;
+// }
+ if (cmd.equals("uninstall") ||
+ (cmd.equals("activate") && state == INSTALLED) ||
+ (cmd.equals("deactivate") && state == ACTIVE)) {
+ strings.add(app.id().name());
+ }
+ }
+
+ // Now let the completer do the work for figuring out what to offer.
+ return delegate.complete(buffer, cursor, candidates);
+ }
+
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/app/ApplicationsListCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/app/ApplicationsListCommand.java
new file mode 100644
index 00000000..17cf89e2
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/app/ApplicationsListCommand.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2015 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.cli.app;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.commands.Option;
+import org.onosproject.app.ApplicationService;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.cli.Comparators;
+import org.onosproject.core.Application;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+
+import static com.google.common.collect.Lists.newArrayList;
+import static org.onosproject.app.ApplicationState.ACTIVE;
+
+/**
+ * Lists application information.
+ */
+@Command(scope = "onos", name = "apps",
+ description = "Lists application information")
+public class ApplicationsListCommand extends AbstractShellCommand {
+
+ private static final String FMT =
+ "%s id=%d, name=%s, version=%s, origin=%s, description=%s, " +
+ "features=%s, featuresRepo=%s, permissions=%s";
+
+ private static final String SHORT_FMT =
+ "%s %3d %-32s %-8s %s";
+
+ @Option(name = "-s", aliases = "--short", description = "Show short output only",
+ required = false, multiValued = false)
+ private boolean shortOnly = false;
+
+ @Option(name = "-a", aliases = "--active", description = "Show active only",
+ required = false, multiValued = false)
+ private boolean activeOnly = false;
+
+
+ @Override
+ protected void execute() {
+ ApplicationService service = get(ApplicationService.class);
+ List<Application> apps = newArrayList(service.getApplications());
+ Collections.sort(apps, Comparators.APP_COMPARATOR);
+
+ if (outputJson()) {
+ print("%s", json(service, apps));
+ } else {
+ for (Application app : apps) {
+ boolean isActive = service.getState(app.id()) == ACTIVE;
+ if (activeOnly && isActive || !activeOnly) {
+ if (shortOnly) {
+ print(SHORT_FMT, isActive ? "*" : " ",
+ app.id().id(), app.id().name(), app.version(),
+ app.description());
+ } else {
+ print(FMT, isActive ? "*" : " ",
+ app.id().id(), app.id().name(), app.version(), app.origin(),
+ app.description(), app.features(),
+ app.featuresRepo().isPresent() ? app.featuresRepo().get().toString() : "",
+ app.permissions());
+ }
+ }
+ }
+ }
+ }
+
+ private JsonNode json(ApplicationService service, List<Application> apps) {
+ ObjectMapper mapper = new ObjectMapper();
+ ArrayNode result = mapper.createArrayNode();
+ for (Application app : apps) {
+ boolean isActive = service.getState(app.id()) == ACTIVE;
+ if (activeOnly && isActive || !activeOnly) {
+ result.add(jsonForEntity(app, Application.class));
+ }
+ }
+ return result;
+ }
+
+
+
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/app/package-info.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/app/package-info.java
new file mode 100644
index 00000000..37b67fa9
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/app/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2015 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 commands for managing distributed inventory of applications.
+ */
+package org.onosproject.cli.app; \ No newline at end of file
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/cfg/ComponentConfigCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/cfg/ComponentConfigCommand.java
new file mode 100644
index 00000000..5b9a7283
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/cfg/ComponentConfigCommand.java
@@ -0,0 +1,182 @@
+/*
+ * Copyright 2015 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.cli.cfg;
+
+import java.util.Optional;
+import java.util.Set;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.commands.Option;
+import org.onosproject.cfg.ComponentConfigService;
+import org.onosproject.cfg.ConfigProperty;
+import org.onosproject.cli.AbstractShellCommand;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+import static com.google.common.base.Strings.isNullOrEmpty;
+
+/**
+ * Manages component configuration.
+ */
+@Command(scope = "onos", name = "cfg",
+ description = "Manages component configuration")
+public class ComponentConfigCommand extends AbstractShellCommand {
+
+ static final String GET = "get";
+ static final String SET = "set";
+
+ private static final String FMT = " name=%s, type=%s, value=%s, defaultValue=%s, description=%s";
+ private static final String SHORT_FMT = " %s=%s";
+
+ @Option(name = "-s", aliases = "--short", description = "Show short output only",
+ required = false, multiValued = false)
+ private boolean shortOnly = false;
+
+
+ @Argument(index = 0, name = "command",
+ description = "Command name (get|set)",
+ required = false, multiValued = false)
+ String command = null;
+
+ @Argument(index = 1, name = "component", description = "Component name",
+ required = false, multiValued = false)
+ String component = null;
+
+ @Argument(index = 2, name = "name", description = "Property name",
+ required = false, multiValued = false)
+ String name = null;
+
+ @Argument(index = 3, name = "value", description = "Property value",
+ required = false, multiValued = false)
+ String value = null;
+
+ ComponentConfigService service;
+
+ @Override
+ protected void execute() {
+ service = get(ComponentConfigService.class);
+ if (isNullOrEmpty(command)) {
+ listComponents();
+ } else if (command.equals(GET) && isNullOrEmpty(component)) {
+ listAllComponentsProperties();
+ } else if (command.equals(GET) && isNullOrEmpty(name)) {
+ listComponentProperties(component);
+ } else if (command.equals(GET)) {
+ listComponentProperty(component, name);
+ } else if (command.equals(SET) && isNullOrEmpty(value)) {
+ service.unsetProperty(component, name);
+ } else if (command.equals(SET)) {
+ service.setProperty(component, name, value);
+ } else {
+ error("Illegal usage");
+ }
+ }
+
+ private void listAllComponentsProperties() {
+ if (outputJson()) {
+ print("%s", jsonComponentProperties());
+ } else {
+ service.getComponentNames().forEach(this::listComponentProperties);
+ }
+ }
+
+ private JsonNode jsonProperty(ConfigProperty configProperty, ObjectMapper mapper) {
+ return mapper.createObjectNode()
+ .put("name", configProperty.name())
+ .put("type", configProperty.type().toString().toLowerCase())
+ .put("value", configProperty.value())
+ .put("defaultValue", configProperty.defaultValue())
+ .put("description", configProperty.description());
+ }
+
+ private JsonNode jsonComponent(String component, ObjectMapper mapper) {
+ ObjectNode node = mapper.createObjectNode()
+ .put("componentName", component);
+ final ArrayNode propertiesJson = node.putArray("properties");
+ Set<ConfigProperty> properties = service.getProperties(component);
+ if (properties != null) {
+ properties.forEach(configProperty -> propertiesJson.add(
+ jsonProperty(configProperty, mapper)));
+ }
+ return node;
+ }
+
+ private JsonNode jsonComponentProperties() {
+ ObjectMapper mapper = new ObjectMapper();
+ ArrayNode result = mapper.createArrayNode();
+ service.getComponentNames()
+ .forEach(component -> result.add(jsonComponent(component, mapper)));
+
+ return result;
+ }
+
+ private void listComponents() {
+ if (outputJson()) {
+ ArrayNode node = new ObjectMapper().createArrayNode();
+ service.getComponentNames().forEach(node::add);
+ print("%s", node);
+ } else {
+ service.getComponentNames().forEach(n -> print("%s", n));
+ }
+ }
+
+ private void listComponentProperties(String component) {
+ if (outputJson()) {
+ print("%s", jsonComponent(component, new ObjectMapper()));
+ } else {
+ Set<ConfigProperty> props = service.getProperties(component);
+ print("%s", component);
+ if (props == null) {
+ print("No properties for component " + component + " found");
+ } else if (shortOnly) {
+ props.forEach(p -> print(SHORT_FMT, p.name(), p.value()));
+ } else {
+ props.forEach(p -> print(FMT, p.name(), p.type().toString().toLowerCase(),
+ p.value(), p.defaultValue(), p.description()));
+ }
+ }
+ }
+
+ private void listComponentProperty(String component, String name) {
+ Set<ConfigProperty> props = service.getProperties(component);
+
+ if (props == null) {
+ return;
+ }
+ Optional<ConfigProperty> property = props.stream()
+ .filter(p -> p.name().equals(name)).findFirst();
+ if (outputJson()) {
+ print("%s", jsonProperty(property.get(), new ObjectMapper()));
+ } else {
+ if (!property.isPresent()) {
+ print("Property " + name + " for component " + component + " not found");
+ return;
+ }
+ ConfigProperty p = property.get();
+ if (shortOnly) {
+ print(SHORT_FMT, p.name(), p.value());
+ } else {
+ print(FMT, p.name(), p.type().toString().toLowerCase(), p.value(),
+ p.defaultValue(), p.description());
+ }
+ }
+ }
+
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/cfg/ComponentConfigCommandCompleter.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/cfg/ComponentConfigCommandCompleter.java
new file mode 100644
index 00000000..5506d816
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/cfg/ComponentConfigCommandCompleter.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2015 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.cli.cfg;
+
+import org.apache.karaf.shell.console.Completer;
+import org.apache.karaf.shell.console.completer.StringsCompleter;
+
+import java.util.List;
+import java.util.SortedSet;
+
+import static org.onosproject.cli.cfg.ComponentConfigCommand.GET;
+import static org.onosproject.cli.cfg.ComponentConfigCommand.SET;
+
+/**
+ * Component configuration command completer.
+ */
+public class ComponentConfigCommandCompleter implements Completer {
+ @Override
+ public int complete(String buffer, int cursor, List<String> candidates) {
+ // Delegate string completer
+ StringsCompleter delegate = new StringsCompleter();
+ SortedSet<String> strings = delegate.getStrings();
+ strings.add(GET);
+ strings.add(SET);
+
+ // Now let the completer do the work for figuring out what to offer.
+ return delegate.complete(buffer, cursor, candidates);
+ }
+
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/cfg/ComponentNameCompleter.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/cfg/ComponentNameCompleter.java
new file mode 100644
index 00000000..4883b991
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/cfg/ComponentNameCompleter.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2015 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.cli.cfg;
+
+import org.apache.karaf.shell.console.Completer;
+import org.apache.karaf.shell.console.completer.StringsCompleter;
+import org.onosproject.cfg.ComponentConfigService;
+import org.onosproject.cli.AbstractShellCommand;
+
+import java.util.List;
+import java.util.SortedSet;
+
+/**
+ * Component name completer.
+ */
+public class ComponentNameCompleter implements Completer {
+ @Override
+ public int complete(String buffer, int cursor, List<String> candidates) {
+ // Delegate string completer
+ StringsCompleter delegate = new StringsCompleter();
+
+ // Fetch our service and feed it's offerings to the string completer
+ ComponentConfigService service = AbstractShellCommand.get(ComponentConfigService.class);
+ SortedSet<String> strings = delegate.getStrings();
+ service.getComponentNames().forEach(strings::add);
+
+ // Now let the completer do the work for figuring out what to offer.
+ return delegate.complete(buffer, cursor, candidates);
+ }
+
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/cfg/ComponentPropertyNameCompleter.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/cfg/ComponentPropertyNameCompleter.java
new file mode 100644
index 00000000..98e19690
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/cfg/ComponentPropertyNameCompleter.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2015 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.cli.cfg;
+
+import org.apache.karaf.shell.console.completer.ArgumentCompleter;
+import org.apache.karaf.shell.console.completer.StringsCompleter;
+import org.onosproject.cfg.ComponentConfigService;
+import org.onosproject.cfg.ConfigProperty;
+import org.onosproject.cli.AbstractCompleter;
+
+import java.util.List;
+import java.util.Set;
+import java.util.SortedSet;
+
+import static org.onosproject.cli.AbstractShellCommand.get;
+
+/**
+ * Component property name completer.
+ */
+public class ComponentPropertyNameCompleter extends AbstractCompleter {
+ @Override
+ public int complete(String buffer, int cursor, List<String> candidates) {
+ // Delegate string completer
+ StringsCompleter delegate = new StringsCompleter();
+
+ // Component name is the previous argument.
+ ArgumentCompleter.ArgumentList list = getArgumentList();
+ String componentName = list.getArguments()[list.getCursorArgumentIndex() - 1];
+ ComponentConfigService service = get(ComponentConfigService.class);
+
+ SortedSet<String> strings = delegate.getStrings();
+ Set<ConfigProperty> properties =
+ service.getProperties(componentName);
+ if (properties != null) {
+ properties.forEach(property -> strings.add(property.name()));
+ }
+
+ // Now let the completer do the work for figuring out what to offer.
+ return delegate.complete(buffer, cursor, candidates);
+ }
+
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/cfg/NetworkConfigCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/cfg/NetworkConfigCommand.java
new file mode 100644
index 00000000..5f2f86ee
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/cfg/NetworkConfigCommand.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2015 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.cli.cfg;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.net.config.Config;
+import org.onosproject.net.config.NetworkConfigService;
+import org.onosproject.net.config.SubjectFactory;
+
+import static com.google.common.base.Strings.isNullOrEmpty;
+
+/**
+ * Manages network configuration.
+ */
+@Command(scope = "onos", name = "netcfg",
+ description = "Manages network configuration")
+public class NetworkConfigCommand extends AbstractShellCommand {
+
+ @Argument(index = 0, name = "subjectKey", description = "Subject key",
+ required = false, multiValued = false)
+ String subjectKey = null;
+
+ @Argument(index = 1, name = "subject", description = "Subject",
+ required = false, multiValued = false)
+ String subject = null;
+
+ @Argument(index = 2, name = "configKey", description = "Config key",
+ required = false, multiValued = false)
+ String configKey = null;
+
+ private final ObjectMapper mapper = new ObjectMapper();
+ private NetworkConfigService service;
+
+ @Override
+ protected void execute() {
+ service = get(NetworkConfigService.class);
+ JsonNode root = new ObjectMapper().createObjectNode();
+ if (isNullOrEmpty(subjectKey)) {
+ addAll((ObjectNode) root);
+ } else {
+ SubjectFactory subjectFactory = service.getSubjectFactory(subjectKey);
+ if (isNullOrEmpty(subject)) {
+ addSubjectClass((ObjectNode) root, subjectFactory);
+ } else {
+ Object s = subjectFactory.createSubject(subject);
+ if (isNullOrEmpty(configKey)) {
+ addSubject((ObjectNode) root, s);
+ } else {
+ root = getSubjectConfig(getConfig(s, subjectKey, configKey));
+ }
+ }
+ }
+ print("%s", root.toString());
+ }
+
+ @SuppressWarnings("unchecked")
+ private void addAll(ObjectNode root) {
+ service.getSubjectClasses()
+ .forEach(sc -> {
+ SubjectFactory sf = service.getSubjectFactory((Class) sc);
+ addSubjectClass(newObject(root, sf.subjectKey()), sf);
+ });
+ }
+
+ @SuppressWarnings("unchecked")
+ private void addSubjectClass(ObjectNode root, SubjectFactory sf) {
+ service.getSubjects(sf.subjectClass())
+ .forEach(s -> addSubject(newObject(root, s.toString()), s));
+ }
+
+ private void addSubject(ObjectNode root, Object s) {
+ service.getConfigs(s).forEach(c -> root.set(c.key(), c.node()));
+ }
+
+ private JsonNode getSubjectConfig(Config config) {
+ return config != null ? config.node() : null;
+ }
+
+ private Config getConfig(Object s, String subjectKey, String ck) {
+ Class<? extends Config> configClass = service.getConfigClass(subjectKey, ck);
+ return configClass != null ? service.getConfig(s, configClass) : null;
+ }
+
+ private ObjectNode newObject(ObjectNode parent, String key) {
+ ObjectNode node = mapper.createObjectNode();
+ parent.set(key, node);
+ return node;
+ }
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/cfg/NetworkConfigRegistryCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/cfg/NetworkConfigRegistryCommand.java
new file mode 100644
index 00000000..f94967e1
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/cfg/NetworkConfigRegistryCommand.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2015 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.cli.cfg;
+
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.commands.Option;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.net.config.ConfigFactory;
+import org.onosproject.net.config.NetworkConfigRegistry;
+
+/**
+ * Displays network configuration registry contents.
+ */
+@Command(scope = "onos", name = "netcfg-registry",
+ description = "Displays network configuration registry contents")
+public class NetworkConfigRegistryCommand extends AbstractShellCommand {
+
+ private static final String FMT = "subjectKey=%s, configKey=%s, subjectClass=%s, configClass=%s";
+ private static final String SHORT_FMT = "%-12s %-12s %-40s %s";
+
+ @Option(name = "-s", aliases = "--short", description = "Show short output only",
+ required = false, multiValued = false)
+ private boolean shortOnly = false;
+
+ @Override
+ protected void execute() {
+ get(NetworkConfigRegistry.class).getConfigFactories().forEach(this::print);
+ }
+
+ private void print(ConfigFactory configFactory) {
+ print(shortOnly ? SHORT_FMT : FMT,
+ configFactory.subjectFactory().subjectKey(),
+ configFactory.configKey(),
+ configFactory.subjectFactory().subjectClass().getName(),
+ configFactory.configClass().getName());
+ }
+
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/cfg/package-info.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/cfg/package-info.java
new file mode 100644
index 00000000..0891ddb5
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/cfg/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2015 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 commands for managing centralized component and network configurations.
+ */
+package org.onosproject.cli.cfg; \ No newline at end of file
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/AddHostToHostIntentCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/AddHostToHostIntentCommand.java
new file mode 100644
index 00000000..cabf0b3a
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/AddHostToHostIntentCommand.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2014-2015 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.cli.net;
+
+import java.util.List;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.net.HostId;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.intent.Constraint;
+import org.onosproject.net.intent.HostToHostIntent;
+import org.onosproject.net.intent.IntentService;
+
+/**
+ * Installs host-to-host connectivity intent.
+ */
+@Command(scope = "onos", name = "add-host-intent",
+ description = "Installs host-to-host connectivity intent")
+public class AddHostToHostIntentCommand extends ConnectivityIntentCommand {
+
+ @Argument(index = 0, name = "one", description = "One host ID",
+ required = true, multiValued = false)
+ String one = null;
+
+ @Argument(index = 1, name = "two", description = "Another host ID",
+ required = true, multiValued = false)
+ String two = null;
+
+ @Override
+ protected void execute() {
+ IntentService service = get(IntentService.class);
+
+ HostId oneId = HostId.hostId(one);
+ HostId twoId = HostId.hostId(two);
+
+ TrafficSelector selector = buildTrafficSelector();
+ TrafficTreatment treatment = buildTrafficTreatment();
+ List<Constraint> constraints = buildConstraints();
+
+ HostToHostIntent intent = HostToHostIntent.builder()
+ .appId(appId())
+ .key(key())
+ .one(oneId)
+ .two(twoId)
+ .selector(selector)
+ .treatment(treatment)
+ .constraints(constraints)
+ .priority(priority())
+ .build();
+ service.submit(intent);
+ print("Host to Host intent submitted:\n%s", intent.toString());
+ }
+
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/AddMeter.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/AddMeter.java
new file mode 100644
index 00000000..5a431cd4
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/AddMeter.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2015 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.cli.net;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.core.CoreService;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.meter.Band;
+import org.onosproject.net.meter.DefaultBand;
+import org.onosproject.net.meter.DefaultMeterRequest;
+import org.onosproject.net.meter.Meter;
+import org.onosproject.net.meter.MeterRequest;
+import org.onosproject.net.meter.MeterService;
+
+import java.util.Collections;
+
+/**
+ * Add a meter.
+ */
+@Command(scope = "onos", name = "add-meter",
+ description = "Adds a meter to a device (currently for testing)")
+public class AddMeter extends AbstractShellCommand {
+
+ @Argument(index = 0, name = "uri", description = "Device ID",
+ required = true, multiValued = false)
+ String uri = null;
+
+ private final String appId = "org.onosproject.cli.meterCmd";
+
+ @Override
+ protected void execute() {
+ MeterService service = get(MeterService.class);
+ CoreService coreService = get(CoreService.class);
+
+ DeviceId deviceId = DeviceId.deviceId(uri);
+
+ Band band = DefaultBand.builder()
+ .ofType(Band.Type.DROP)
+ .withRate(500)
+ .build();
+
+
+ MeterRequest request = DefaultMeterRequest.builder()
+ .forDevice(deviceId)
+ .fromApp(coreService.registerApplication(appId))
+ .withUnit(Meter.Unit.KB_PER_SEC)
+ .withBands(Collections.singleton(band))
+ .add();
+
+ service.submit(request);
+
+ }
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/AddMplsIntent.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/AddMplsIntent.java
new file mode 100644
index 00000000..1929b726
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/AddMplsIntent.java
@@ -0,0 +1,91 @@
+package org.onosproject.cli.net;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.commands.Option;
+import org.onlab.packet.MplsLabel;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.intent.Constraint;
+import org.onosproject.net.intent.IntentService;
+import org.onosproject.net.intent.MplsIntent;
+
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * Installs MPLS intents.
+ */
+@Command(scope = "onos", name = "add-mpls-intent", description = "Installs mpls connectivity intent")
+public class AddMplsIntent extends ConnectivityIntentCommand {
+
+ @Argument(index = 0, name = "ingressDevice",
+ description = "Ingress Device/Port Description",
+ required = true,
+ multiValued = false)
+ private String ingressDeviceString = null;
+
+ @Option(name = "--ingressLabel",
+ description = "Ingress Mpls label",
+ required = false,
+ multiValued = false)
+ private String ingressLabelString = "";
+
+ @Argument(index = 1, name = "egressDevice",
+ description = "Egress Device/Port Description",
+ required = true,
+ multiValued = false)
+ private String egressDeviceString = null;
+
+ @Option(name = "--egressLabel",
+ description = "Egress Mpls label",
+ required = false,
+ multiValued = false)
+ private String egressLabelString = "";
+
+ @Override
+ protected void execute() {
+ IntentService service = get(IntentService.class);
+
+ ConnectPoint ingress = ConnectPoint.deviceConnectPoint(ingressDeviceString);
+ Optional<MplsLabel> ingressLabel = Optional.empty();
+ if (!ingressLabelString.isEmpty()) {
+ ingressLabel = Optional
+ .ofNullable(MplsLabel.mplsLabel(parseInt(ingressLabelString)));
+ }
+
+ ConnectPoint egress = ConnectPoint.deviceConnectPoint(egressDeviceString);
+ Optional<MplsLabel> egressLabel = Optional.empty();
+ if (!egressLabelString.isEmpty()) {
+ egressLabel = Optional
+ .ofNullable(MplsLabel.mplsLabel(parseInt(egressLabelString)));
+ }
+
+ TrafficSelector selector = buildTrafficSelector();
+ TrafficTreatment treatment = buildTrafficTreatment();
+
+ List<Constraint> constraints = buildConstraints();
+
+ MplsIntent intent = MplsIntent.builder()
+ .appId(appId())
+ .selector(selector)
+ .treatment(treatment)
+ .ingressPoint(ingress)
+ .ingressLabel(ingressLabel)
+ .egressPoint(egress)
+ .egressLabel(egressLabel)
+ .constraints(constraints)
+ .priority(priority())
+ .build();
+ service.submit(intent);
+ }
+
+ protected Integer parseInt(String value) {
+ try {
+ return Integer.parseInt(value);
+ } catch (NumberFormatException nfe) {
+ return null;
+ }
+ }
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/AddMultiPointToSinglePointIntentCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/AddMultiPointToSinglePointIntentCommand.java
new file mode 100644
index 00000000..dc792f49
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/AddMultiPointToSinglePointIntentCommand.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2014-2015 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.cli.net;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.intent.Constraint;
+import org.onosproject.net.intent.Intent;
+import org.onosproject.net.intent.IntentService;
+import org.onosproject.net.intent.MultiPointToSinglePointIntent;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Installs connectivity intent between multiple ingress devices and a single egress device.
+ */
+@Command(scope = "onos", name = "add-multi-to-single-intent",
+ description = "Installs connectivity intent between multiple ingress devices and a single egress device")
+public class AddMultiPointToSinglePointIntentCommand extends ConnectivityIntentCommand {
+
+ @Argument(index = 0, name = "ingressDevices egressDevice",
+ description = "ingressDevice/Port..ingressDevice/Port egressDevice/Port",
+ required = true, multiValued = true)
+ String[] deviceStrings = null;
+
+ @Override
+ protected void execute() {
+ IntentService service = get(IntentService.class);
+
+ if (deviceStrings.length < 2) {
+ return;
+ }
+
+ String egressDeviceString = deviceStrings[deviceStrings.length - 1];
+ ConnectPoint egress = ConnectPoint.deviceConnectPoint(egressDeviceString);
+
+ Set<ConnectPoint> ingressPoints = new HashSet<>();
+ for (int index = 0; index < deviceStrings.length - 1; index++) {
+ String ingressDeviceString = deviceStrings[index];
+ ConnectPoint ingress = ConnectPoint.deviceConnectPoint(ingressDeviceString);
+ ingressPoints.add(ingress);
+ }
+
+ TrafficSelector selector = buildTrafficSelector();
+ TrafficTreatment treatment = buildTrafficTreatment();
+ List<Constraint> constraints = buildConstraints();
+
+ Intent intent = MultiPointToSinglePointIntent.builder()
+ .appId(appId())
+ .key(key())
+ .selector(selector)
+ .treatment(treatment)
+ .ingressPoints(ingressPoints)
+ .egressPoint(egress)
+ .constraints(constraints)
+ .priority(priority())
+ .build();
+ service.submit(intent);
+ print("Multipoint to single point intent submitted:\n%s", intent.toString());
+ }
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/AddOpticalIntentCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/AddOpticalIntentCommand.java
new file mode 100644
index 00000000..57c41009
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/AddOpticalIntentCommand.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2014-2015 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.cli.net;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.commands.Option;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.OchPort;
+import org.onosproject.net.OduCltPort;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.OduSignalType;
+import org.onosproject.net.Port;
+import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.intent.Intent;
+import org.onosproject.net.intent.IntentService;
+import org.onosproject.net.intent.OpticalCircuitIntent;
+import org.onosproject.net.intent.OpticalConnectivityIntent;
+
+import java.util.List;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+/**
+ * Installs optical connectivity or circuit intents, depending on given port types.
+ */
+@Command(scope = "onos", name = "add-optical-intent",
+ description = "Installs optical connectivity intent")
+public class AddOpticalIntentCommand extends ConnectivityIntentCommand {
+
+ @Argument(index = 0, name = "ingressDevice",
+ description = "Ingress Device/Port Description",
+ required = true, multiValued = false)
+ String ingressDeviceString = null;
+
+ @Argument(index = 1, name = "egressDevice",
+ description = "Egress Device/Port Description",
+ required = true, multiValued = false)
+ String egressDeviceString = null;
+
+ @Option(name = "-b", aliases = "--bidirectional",
+ description = "If this argument is passed the optical link created will be bidirectional, " +
+ "else the link will be unidirectional.",
+ required = false, multiValued = false)
+ private boolean bidirectional = false;
+
+
+ private ConnectPoint createConnectPoint(String devicePortString) {
+ String[] splitted = devicePortString.split("/");
+
+ checkArgument(splitted.length == 2,
+ "Connect point must be in \"deviceUri/portNumber\" format");
+
+ DeviceId deviceId = DeviceId.deviceId(splitted[0]);
+
+ DeviceService deviceService = get(DeviceService.class);
+
+ List<Port> ports = deviceService.getPorts(deviceId);
+
+ for (Port port : ports) {
+ if (splitted[1].equals(port.number().name())) {
+ return new ConnectPoint(deviceId, port.number());
+ }
+ }
+
+ return null;
+ }
+
+ @Override
+ protected void execute() {
+ IntentService service = get(IntentService.class);
+
+ ConnectPoint ingress = createConnectPoint(ingressDeviceString);
+ ConnectPoint egress = createConnectPoint(egressDeviceString);
+
+ if (ingress == null || egress == null) {
+ print("Could not create optical intent");
+ }
+
+ DeviceService deviceService = get(DeviceService.class);
+ Port srcPort = deviceService.getPort(ingress.deviceId(), ingress.port());
+ Port dstPort = deviceService.getPort(egress.deviceId(), egress.port());
+
+ Intent intent;
+ // FIXME: Hardcoded signal types
+ if (srcPort instanceof OduCltPort && dstPort instanceof OduCltPort) {
+ intent = OpticalCircuitIntent.builder()
+ .appId(appId())
+ .key(key())
+ .src(ingress)
+ .dst(egress)
+ .signalType(OduCltPort.SignalType.CLT_10GBE)
+ .bidirectional(bidirectional)
+ .build();
+ } else if (srcPort instanceof OchPort && dstPort instanceof OchPort) {
+ intent = OpticalConnectivityIntent.builder()
+ .appId(appId())
+ .key(key())
+ .src(ingress)
+ .dst(egress)
+ .signalType(OduSignalType.ODU4)
+ .bidirectional(bidirectional)
+ .build();
+ } else {
+ print("Unable to create optical intent between connect points {} and {}", ingress, egress);
+ return;
+ }
+
+ service.submit(intent);
+ print("Optical intent submitted:\n%s", intent.toString());
+ }
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/AddPointToPointIntentCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/AddPointToPointIntentCommand.java
new file mode 100644
index 00000000..7c27dd3d
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/AddPointToPointIntentCommand.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2014-2015 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.cli.net;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.intent.Constraint;
+import org.onosproject.net.intent.Intent;
+import org.onosproject.net.intent.IntentService;
+import org.onosproject.net.intent.PointToPointIntent;
+
+import java.util.List;
+
+/**
+ * Installs point-to-point connectivity intents.
+ */
+@Command(scope = "onos", name = "add-point-intent",
+ description = "Installs point-to-point connectivity intent")
+public class AddPointToPointIntentCommand extends ConnectivityIntentCommand {
+
+ @Argument(index = 0, name = "ingressDevice",
+ description = "Ingress Device/Port Description",
+ required = true, multiValued = false)
+ String ingressDeviceString = null;
+
+ @Argument(index = 1, name = "egressDevice",
+ description = "Egress Device/Port Description",
+ required = true, multiValued = false)
+ String egressDeviceString = null;
+
+ @Override
+ protected void execute() {
+ IntentService service = get(IntentService.class);
+
+ ConnectPoint ingress = ConnectPoint.deviceConnectPoint(ingressDeviceString);
+
+ ConnectPoint egress = ConnectPoint.deviceConnectPoint(egressDeviceString);
+
+ TrafficSelector selector = buildTrafficSelector();
+ TrafficTreatment treatment = buildTrafficTreatment();
+
+ List<Constraint> constraints = buildConstraints();
+
+ Intent intent = PointToPointIntent.builder()
+ .appId(appId())
+ .key(key())
+ .selector(selector)
+ .treatment(treatment)
+ .ingressPoint(ingress)
+ .egressPoint(egress)
+ .constraints(constraints)
+ .priority(priority())
+ .build();
+ service.submit(intent);
+ print("Point to point intent submitted:\n%s", intent.toString());
+ }
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/AddSinglePointToMultiPointIntentCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/AddSinglePointToMultiPointIntentCommand.java
new file mode 100644
index 00000000..2939afae
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/AddSinglePointToMultiPointIntentCommand.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2014-2015 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.cli.net;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.flow.DefaultTrafficTreatment;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.intent.Constraint;
+import org.onosproject.net.intent.IntentService;
+import org.onosproject.net.intent.SinglePointToMultiPointIntent;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Installs connectivity intent between a single ingress device and multiple egress devices.
+ */
+@Command(scope = "onos", name = "add-single-to-multi-intent",
+ description = "Installs connectivity intent between a single ingress device and multiple egress devices")
+public class AddSinglePointToMultiPointIntentCommand extends ConnectivityIntentCommand {
+ @Argument(index = 0, name = "ingressDevice egressDevices",
+ description = "ingressDevice/Port egressDevice/Port...egressDevice/Port",
+ required = true, multiValued = true)
+ String[] deviceStrings = null;
+
+ @Override
+ protected void execute() {
+ IntentService service = get(IntentService.class);
+
+ if (deviceStrings.length < 2) {
+ return;
+ }
+
+ String ingressDeviceString = deviceStrings[0];
+ ConnectPoint ingressPoint = ConnectPoint.deviceConnectPoint(ingressDeviceString);
+
+ Set<ConnectPoint> egressPoints = new HashSet<>();
+ for (int index = 1; index < deviceStrings.length; index++) {
+ String egressDeviceString = deviceStrings[index];
+ ConnectPoint egress = ConnectPoint.deviceConnectPoint(egressDeviceString);
+ egressPoints.add(egress);
+ }
+
+ TrafficSelector selector = buildTrafficSelector();
+ TrafficTreatment treatment = DefaultTrafficTreatment.emptyTreatment();
+ List<Constraint> constraints = buildConstraints();
+
+ SinglePointToMultiPointIntent intent =
+ SinglePointToMultiPointIntent.builder()
+ .appId(appId())
+ .key(key())
+ .selector(selector)
+ .treatment(treatment)
+ .ingressPoint(ingressPoint)
+ .egressPoints(egressPoints)
+ .constraints(constraints)
+ .priority(priority())
+ .build();
+ service.submit(intent);
+ print("Single point to multipoint intent submitted:\n%s", intent.toString());
+ }
+
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/AddTestFlowsCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/AddTestFlowsCommand.java
new file mode 100644
index 00000000..e1e158ab
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/AddTestFlowsCommand.java
@@ -0,0 +1,170 @@
+
+/*
+ * Copyright 2014-2015 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.cli.net;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.google.common.base.Stopwatch;
+import com.google.common.collect.Lists;
+import org.apache.commons.lang.math.RandomUtils;
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.onlab.packet.MacAddress;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.CoreService;
+import org.onosproject.net.Device;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.flow.DefaultFlowRule;
+import org.onosproject.net.flow.DefaultTrafficSelector;
+import org.onosproject.net.flow.DefaultTrafficTreatment;
+import org.onosproject.net.flow.FlowRule;
+import org.onosproject.net.flow.FlowRuleOperations;
+import org.onosproject.net.flow.FlowRuleOperationsContext;
+import org.onosproject.net.flow.FlowRuleService;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+
+import java.util.ArrayList;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Installs bulk flows.
+ */
+@Command(scope = "onos", name = "add-test-flows",
+ description = "Installs a number of test flow rules - for testing only")
+public class AddTestFlowsCommand extends AbstractShellCommand {
+
+ private CountDownLatch latch;
+
+ @Argument(index = 0, name = "flowPerDevice", description = "Number of flows to add per device",
+ required = true, multiValued = false)
+ String flows = null;
+
+ @Argument(index = 1, name = "numOfRuns", description = "Number of iterations",
+ required = true, multiValued = false)
+ String numOfRuns = null;
+
+ @Override
+ protected void execute() {
+ FlowRuleService flowService = get(FlowRuleService.class);
+ DeviceService deviceService = get(DeviceService.class);
+ CoreService coreService = get(CoreService.class);
+
+ ApplicationId appId = coreService.registerApplication("onos.test.flow.installer");
+
+ int flowsPerDevice = Integer.parseInt(flows);
+ int num = Integer.parseInt(numOfRuns);
+
+ ArrayList<Long> results = Lists.newArrayList();
+ Iterable<Device> devices = deviceService.getDevices();
+ TrafficTreatment treatment = DefaultTrafficTreatment.builder()
+ .setOutput(PortNumber.portNumber(RandomUtils.nextInt())).build();
+ TrafficSelector.Builder sbuilder;
+ FlowRuleOperations.Builder rules = FlowRuleOperations.builder();
+ FlowRuleOperations.Builder remove = FlowRuleOperations.builder();
+
+ for (Device d : devices) {
+ for (int i = 0; i < flowsPerDevice; i++) {
+ sbuilder = DefaultTrafficSelector.builder();
+
+ sbuilder.matchEthSrc(MacAddress.valueOf(RandomUtils.nextInt() * i))
+ .matchEthDst(MacAddress.valueOf((Integer.MAX_VALUE - i) * RandomUtils.nextInt()));
+
+
+ int randomPriority = RandomUtils.nextInt();
+
+ FlowRule addRule = DefaultFlowRule.builder()
+ .forDevice(d.id())
+ .withSelector(sbuilder.build())
+ .withTreatment(treatment)
+ .withPriority(randomPriority)
+ .fromApp(appId)
+ .makeTemporary(10)
+ .build();
+ FlowRule removeRule = DefaultFlowRule.builder()
+ .forDevice(d.id())
+ .withSelector(sbuilder.build())
+ .withTreatment(treatment)
+ .withPriority(randomPriority)
+ .fromApp(appId)
+ .makeTemporary(10)
+ .build();
+
+ rules.add(addRule);
+ remove.remove(removeRule);
+
+ }
+ }
+
+ for (int i = 0; i < num; i++) {
+ latch = new CountDownLatch(2);
+ flowService.apply(rules.build(new FlowRuleOperationsContext() {
+
+ private final Stopwatch timer = Stopwatch.createStarted();
+
+ @Override
+ public void onSuccess(FlowRuleOperations ops) {
+
+ timer.stop();
+ results.add(timer.elapsed(TimeUnit.MILLISECONDS));
+ if (results.size() == num) {
+ if (outputJson()) {
+ print("%s", json(new ObjectMapper(), true, results));
+ } else {
+ printTime(true, results);
+ }
+ }
+ latch.countDown();
+ }
+ }));
+
+ flowService.apply(remove.build(new FlowRuleOperationsContext() {
+ @Override
+ public void onSuccess(FlowRuleOperations ops) {
+ latch.countDown();
+ }
+ }));
+ try {
+ latch.await();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+
+ }
+ }
+
+ private Object json(ObjectMapper mapper, boolean isSuccess, ArrayList<Long> elapsed) {
+ ObjectNode result = mapper.createObjectNode();
+ result.put("Success", isSuccess);
+ ArrayNode node = result.putArray("elapsed-time");
+ for (Long v : elapsed) {
+ node.add(v);
+ }
+ return result;
+ }
+
+ private void printTime(boolean isSuccess, ArrayList<Long> elapsed) {
+ print("Run is %s.", isSuccess ? "success" : "failure");
+ for (int i = 0; i < elapsed.size(); i++) {
+ print(" Run %s : %s", i, elapsed.get(i));
+ }
+ }
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/AddressBindingsListCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/AddressBindingsListCommand.java
new file mode 100644
index 00000000..3ce45b90
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/AddressBindingsListCommand.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2014-2015 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.cli.net;
+
+import com.google.common.collect.Lists;
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.cli.Comparators;
+import org.onosproject.net.host.HostService;
+import org.onosproject.net.host.InterfaceIpAddress;
+import org.onosproject.net.host.PortAddresses;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Lists all configured address port bindings.
+ */
+@Command(scope = "onos", name = "address-bindings",
+ description = "Lists all configured address port bindings.")
+public class AddressBindingsListCommand extends AbstractShellCommand {
+
+ private static final String FORMAT =
+ "port=%s/%s, ip(s)=%s, mac=%s, vlan=%s";
+
+ @Override
+ protected void execute() {
+ HostService hostService = get(HostService.class);
+
+ List<PortAddresses> addresses =
+ Lists.newArrayList(hostService.getAddressBindings());
+
+ Collections.sort(addresses, Comparators.ADDRESSES_COMPARATOR);
+
+ for (PortAddresses pa : addresses) {
+ print(FORMAT, pa.connectPoint().deviceId(), pa.connectPoint().port(),
+ printIpAddresses(pa.ipAddresses()), pa.mac(), pa.vlan());
+ }
+ }
+
+ private String printIpAddresses(Set<InterfaceIpAddress> addresses) {
+ StringBuilder output = new StringBuilder("[");
+ for (InterfaceIpAddress address : addresses) {
+ output.append(address.ipAddress().toString());
+ output.append("/");
+ output.append(address.subnetAddress().prefixLength());
+ output.append(", ");
+ }
+ // Remove the last comma
+ output.delete(output.length() - 2 , output.length());
+ output.append("]");
+ return output.toString();
+ }
+
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/AnnotateDeviceCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/AnnotateDeviceCommand.java
new file mode 100644
index 00000000..113fe316
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/AnnotateDeviceCommand.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2015 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.cli.net;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.net.DefaultAnnotations;
+import org.onosproject.net.Device;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.MastershipRole;
+import org.onosproject.net.device.DefaultDeviceDescription;
+import org.onosproject.net.device.DeviceDescription;
+import org.onosproject.net.device.DeviceProvider;
+import org.onosproject.net.device.DeviceProviderRegistry;
+import org.onosproject.net.device.DeviceProviderService;
+import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.provider.AbstractProvider;
+import org.onosproject.net.provider.ProviderId;
+
+/**
+ * Annotates network device model.
+ */
+@Command(scope = "onos", name = "annotate-device",
+ description = "Annotates network model entities")
+public class AnnotateDeviceCommand extends AbstractShellCommand {
+
+ static final ProviderId PID = new ProviderId("cli", "org.onosproject.cli", true);
+
+ @Argument(index = 0, name = "uri", description = "Device ID",
+ required = true, multiValued = false)
+ String uri = null;
+
+ @Argument(index = 1, name = "key", description = "Annotation key",
+ required = true, multiValued = false)
+ String key = null;
+
+ @Argument(index = 2, name = "value",
+ description = "Annotation value (null to remove)",
+ required = false, multiValued = false)
+ String value = null;
+
+ @Override
+ protected void execute() {
+ DeviceService service = get(DeviceService.class);
+ Device device = service.getDevice(DeviceId.deviceId(uri));
+
+ DeviceProviderRegistry registry = get(DeviceProviderRegistry.class);
+ DeviceProvider provider = new AnnotationProvider();
+ try {
+ DeviceProviderService providerService = registry.register(provider);
+ providerService.deviceConnected(device.id(), description(device, key, value));
+ } finally {
+ registry.unregister(provider);
+ }
+ }
+
+ private DeviceDescription description(Device device, String key, String value) {
+ DefaultAnnotations.Builder builder = DefaultAnnotations.builder();
+ if (value != null) {
+ builder.set(key, value);
+ } else {
+ builder.remove(key);
+ }
+ return new DefaultDeviceDescription(device.id().uri(), device.type(),
+ device.manufacturer(), device.hwVersion(),
+ device.swVersion(), device.serialNumber(),
+ device.chassisId(), builder.build());
+ }
+
+ // Token provider entity
+ private static final class AnnotationProvider
+ extends AbstractProvider implements DeviceProvider {
+ private AnnotationProvider() {
+ super(PID);
+ }
+
+ @Override
+ public void triggerProbe(DeviceId deviceId) {
+ }
+
+ @Override
+ public void roleChanged(DeviceId deviceId, MastershipRole newRole) {
+ }
+
+ @Override
+ public boolean isReachable(DeviceId deviceId) {
+ return false;
+ }
+ }
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/ClusterDevicesCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/ClusterDevicesCommand.java
new file mode 100644
index 00000000..88c8a8bd
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/ClusterDevicesCommand.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2014-2015 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.cli.net;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.common.collect.Lists;
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cli.Comparators;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.topology.TopologyCluster;
+
+import java.util.Collections;
+import java.util.List;
+
+import static org.onosproject.cli.MastersListCommand.json;
+import static org.onosproject.net.topology.ClusterId.clusterId;
+
+/**
+ * Lists devices of the specified topology cluster in the current topology.
+ */
+@Command(scope = "onos", name = "cluster-devices",
+ description = "Lists devices of the specified topology cluster in the current topology")
+public class ClusterDevicesCommand extends ClustersListCommand {
+
+ @Argument(index = 0, name = "id", description = "Cluster ID",
+ required = true, multiValued = false)
+ String id = null;
+
+ @Override
+ protected void execute() {
+ int cid = Integer.parseInt(id);
+ init();
+ TopologyCluster cluster = service.getCluster(topology, clusterId(cid));
+ if (cluster == null) {
+ error("No such cluster %s", cid);
+ } else {
+ List<DeviceId> ids = Lists.newArrayList(service.getClusterDevices(topology, cluster));
+ Collections.sort(ids, Comparators.ELEMENT_ID_COMPARATOR);
+ if (outputJson()) {
+ print("%s", json(new ObjectMapper(), ids));
+ } else {
+ for (DeviceId deviceId : ids) {
+ print("%s", deviceId);
+ }
+ }
+ }
+ }
+
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/ClusterIdCompleter.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/ClusterIdCompleter.java
new file mode 100644
index 00000000..73e8acba
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/ClusterIdCompleter.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2014 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.cli.net;
+
+import org.apache.karaf.shell.console.Completer;
+import org.apache.karaf.shell.console.completer.StringsCompleter;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.net.topology.Topology;
+import org.onosproject.net.topology.TopologyCluster;
+import org.onosproject.net.topology.TopologyService;
+
+import java.util.List;
+import java.util.SortedSet;
+
+/**
+ * Cluster ID completer.
+ */
+public class ClusterIdCompleter implements Completer {
+ @Override
+ public int complete(String buffer, int cursor, List<String> candidates) {
+ // Delegate string completer
+ StringsCompleter delegate = new StringsCompleter();
+
+ // Fetch our service and feed it's offerings to the string completer
+ TopologyService service = AbstractShellCommand.get(TopologyService.class);
+ Topology topology = service.currentTopology();
+
+ SortedSet<String> strings = delegate.getStrings();
+ for (TopologyCluster cluster : service.getClusters(topology)) {
+ strings.add(Integer.toString(cluster.id().index()));
+ }
+
+ // Now let the completer do the work for figuring out what to offer.
+ return delegate.complete(buffer, cursor, candidates);
+ }
+
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/ClusterLinksCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/ClusterLinksCommand.java
new file mode 100644
index 00000000..dc63bff9
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/ClusterLinksCommand.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2014 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.cli.net;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.net.Link;
+import org.onosproject.net.topology.TopologyCluster;
+
+import static org.onosproject.cli.net.LinksListCommand.json;
+import static org.onosproject.cli.net.LinksListCommand.linkString;
+import static org.onosproject.net.topology.ClusterId.clusterId;
+
+/**
+ * Lists links of the specified topology cluster in the current topology.
+ */
+@Command(scope = "onos", name = "cluster-links",
+ description = "Lists links of the specified topology cluster in the current topology")
+public class ClusterLinksCommand extends ClustersListCommand {
+
+ @Argument(index = 0, name = "id", description = "Cluster ID",
+ required = true, multiValued = false)
+ String id = null;
+
+ @Override
+ protected void execute() {
+ int cid = Integer.parseInt(id);
+ init();
+ TopologyCluster cluster = service.getCluster(topology, clusterId(cid));
+ if (cluster == null) {
+ error("No such cluster %s", cid);
+ } else if (outputJson()) {
+ print("%s", json(this, service.getClusterLinks(topology, cluster)));
+ } else {
+ for (Link link : service.getClusterLinks(topology, cluster)) {
+ print(linkString(link));
+ }
+ }
+ }
+
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/ClustersListCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/ClustersListCommand.java
new file mode 100644
index 00000000..21c27324
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/ClustersListCommand.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2014 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.cli.net;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.google.common.collect.Lists;
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cli.Comparators;
+import org.onosproject.net.topology.TopologyCluster;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Lists all clusters in the current topology.
+ */
+@Command(scope = "onos", name = "clusters",
+ description = "Lists all clusters in the current topology")
+public class ClustersListCommand extends TopologyCommand {
+
+ private static final String FMT =
+ "id=%d, devices=%d, links=%d";
+
+ @Override
+ protected void execute() {
+ init();
+ List<TopologyCluster> clusters = Lists.newArrayList(service.getClusters(topology));
+ Collections.sort(clusters, Comparators.CLUSTER_COMPARATOR);
+
+ if (outputJson()) {
+ print("%s", json(clusters));
+ } else {
+ for (TopologyCluster cluster : clusters) {
+ print(FMT, cluster.id().index(), cluster.deviceCount(), cluster.linkCount());
+ }
+ }
+ }
+
+ // Produces a JSON result.
+ private JsonNode json(Iterable<TopologyCluster> clusters) {
+ ObjectMapper mapper = new ObjectMapper();
+ ArrayNode result = mapper.createArrayNode();
+
+ clusters.spliterator()
+ .forEachRemaining(cluster ->
+ result.add(jsonForEntity(cluster, TopologyCluster.class)));
+
+ return result;
+ }
+
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/ConnectPointCompleter.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/ConnectPointCompleter.java
new file mode 100644
index 00000000..5e2727cf
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/ConnectPointCompleter.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2014 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.cli.net;
+
+import org.apache.karaf.shell.console.Completer;
+import org.apache.karaf.shell.console.completer.StringsCompleter;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.net.Device;
+import org.onosproject.net.Port;
+import org.onosproject.net.device.DeviceService;
+
+import java.util.List;
+import java.util.SortedSet;
+
+/**
+ * ConnectPoint completer.
+ */
+public class ConnectPointCompleter implements Completer {
+ @Override
+ public int complete(String buffer, int cursor, List<String> candidates) {
+ // Delegate string completer
+ StringsCompleter delegate = new StringsCompleter();
+
+ // Fetch our service and feed it's offerings to the string completer
+ DeviceService service = AbstractShellCommand.get(DeviceService.class);
+
+ // Generate the device ID/port number identifiers
+ for (Device device : service.getDevices()) {
+ SortedSet<String> strings = delegate.getStrings();
+ for (Port port : service.getPorts(device.id())) {
+ if (!port.number().isLogical()) {
+ strings.add(device.id().toString() + "/" + port.number());
+ }
+ }
+ }
+
+ // Now let the completer do the work for figuring out what to offer.
+ return delegate.complete(buffer, cursor, candidates);
+ }
+
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/ConnectivityIntentCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/ConnectivityIntentCommand.java
new file mode 100644
index 00000000..6c33f45c
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/ConnectivityIntentCommand.java
@@ -0,0 +1,403 @@
+/*
+ * Copyright 2014-2015 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.cli.net;
+
+import static com.google.common.base.Strings.isNullOrEmpty;
+import static org.onosproject.net.flow.DefaultTrafficTreatment.builder;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import org.apache.karaf.shell.commands.Option;
+import org.onlab.packet.Ip6Address;
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.IpPrefix;
+import org.onlab.packet.MacAddress;
+import org.onlab.packet.TpPort;
+import org.onlab.packet.VlanId;
+import org.onlab.util.Bandwidth;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.CoreService;
+import org.onosproject.net.Link;
+import org.onosproject.net.flow.DefaultTrafficSelector;
+import org.onosproject.net.flow.DefaultTrafficTreatment;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.intent.Constraint;
+import org.onosproject.net.intent.Intent;
+import org.onosproject.net.intent.Key;
+import org.onosproject.net.intent.constraint.BandwidthConstraint;
+import org.onosproject.net.intent.constraint.LambdaConstraint;
+import org.onosproject.net.intent.constraint.LinkTypeConstraint;
+import org.onosproject.net.intent.constraint.PartialFailureConstraint;
+import org.onosproject.net.resource.link.BandwidthResource;
+
+/**
+ * Base class for command line operations for connectivity based intents.
+ */
+public abstract class ConnectivityIntentCommand extends AbstractShellCommand {
+
+ // Selectors
+ @Option(name = "-s", aliases = "--ethSrc", description = "Source MAC Address",
+ required = false, multiValued = false)
+ private String srcMacString = null;
+
+ @Option(name = "-d", aliases = "--ethDst", description = "Destination MAC Address",
+ required = false, multiValued = false)
+ private String dstMacString = null;
+
+ @Option(name = "-t", aliases = "--ethType", description = "Ethernet Type",
+ required = false, multiValued = false)
+ private String ethTypeString = null;
+
+ @Option(name = "-v", aliases = "--vlan", description = "VLAN ID",
+ required = false, multiValued = false)
+ private String vlanString = null;
+
+ @Option(name = "--ipProto", description = "IP Protocol",
+ required = false, multiValued = false)
+ private String ipProtoString = null;
+
+ @Option(name = "--ipSrc", description = "Source IP Prefix",
+ required = false, multiValued = false)
+ private String srcIpString = null;
+
+ @Option(name = "--ipDst", description = "Destination IP Prefix",
+ required = false, multiValued = false)
+ private String dstIpString = null;
+
+ @Option(name = "--fLabel", description = "IPv6 Flow Label",
+ required = false, multiValued = false)
+ private String fLabelString = null;
+
+ @Option(name = "--icmp6Type", description = "ICMPv6 Type",
+ required = false, multiValued = false)
+ private String icmp6TypeString = null;
+
+ @Option(name = "--icmp6Code", description = "ICMPv6 Code",
+ required = false, multiValued = false)
+ private String icmp6CodeString = null;
+
+ @Option(name = "--ndTarget", description = "IPv6 Neighbor Discovery Target Address",
+ required = false, multiValued = false)
+ private String ndTargetString = null;
+
+ @Option(name = "--ndSLL", description = "IPv6 Neighbor Discovery Source Link-Layer",
+ required = false, multiValued = false)
+ private String ndSLLString = null;
+
+ @Option(name = "--ndTLL", description = "IPv6 Neighbor Discovery Target Link-Layer",
+ required = false, multiValued = false)
+ private String ndTLLString = null;
+
+ @Option(name = "--tcpSrc", description = "Source TCP Port",
+ required = false, multiValued = false)
+ private String srcTcpString = null;
+
+ @Option(name = "--tcpDst", description = "Destination TCP Port",
+ required = false, multiValued = false)
+ private String dstTcpString = null;
+
+ @Option(name = "--extHdr", description = "IPv6 Extension Header Pseudo-field",
+ required = false, multiValued = true)
+ private List<String> extHdrStringList = null;
+
+ @Option(name = "-b", aliases = "--bandwidth", description = "Bandwidth",
+ required = false, multiValued = false)
+ private String bandwidthString = null;
+
+ @Option(name = "-l", aliases = "--lambda", description = "Lambda",
+ required = false, multiValued = false)
+ private boolean lambda = false;
+
+ @Option(name = "-a", aliases = "--appId", description = "Application Id",
+ required = false, multiValued = false)
+ private String appId = null;
+
+ @Option(name = "-k", aliases = "--key", description = "Intent Key",
+ required = false, multiValued = false)
+ private String intentKey = null;
+
+ @Option(name = "--partial", description = "Allow partial installation",
+ required = false, multiValued = false)
+ private boolean partial = false;
+
+
+ // Treatments
+ @Option(name = "--setEthSrc", description = "Rewrite Source MAC Address",
+ required = false, multiValued = false)
+ private String setEthSrcString = null;
+
+ @Option(name = "--setEthDst", description = "Rewrite Destination MAC Address",
+ required = false, multiValued = false)
+ private String setEthDstString = null;
+
+ @Option(name = "--setIpSrc", description = "Rewrite Source IP Address",
+ required = false, multiValued = false)
+ private String setIpSrcString = null;
+
+ @Option(name = "--setIpDst", description = "Rewrite Destination IP Address",
+ required = false, multiValued = false)
+ private String setIpDstString = null;
+
+ @Option(name = "--setVlan", description = "Rewrite VLAN ID",
+ required = false, multiValued = false)
+ private String setVlan = null;
+
+ @Option(name = "--popVlan", description = "Pop VLAN Tag",
+ required = false, multiValued = false)
+ private boolean popVlan = false;
+
+ @Option(name = "--pushVlan", description = "Push VLAN ID",
+ required = false, multiValued = false)
+ private String pushVlan = null;
+
+ // Priorities
+ @Option(name = "-p", aliases = "--priority", description = "Priority",
+ required = false, multiValued = false)
+ private int priority = Intent.DEFAULT_INTENT_PRIORITY;
+
+ /**
+ * Constructs a traffic selector based on the command line arguments
+ * presented to the command.
+ * @return traffic selector
+ */
+ protected TrafficSelector buildTrafficSelector() {
+ IpPrefix srcIpPrefix = null;
+ IpPrefix dstIpPrefix = null;
+
+ TrafficSelector.Builder selectorBuilder = DefaultTrafficSelector.builder();
+
+ if (!isNullOrEmpty(srcIpString)) {
+ srcIpPrefix = IpPrefix.valueOf(srcIpString);
+ if (srcIpPrefix.isIp4()) {
+ selectorBuilder.matchIPSrc(srcIpPrefix);
+ } else {
+ selectorBuilder.matchIPv6Src(srcIpPrefix);
+ }
+ }
+
+ if (!isNullOrEmpty(dstIpString)) {
+ dstIpPrefix = IpPrefix.valueOf(dstIpString);
+ if (dstIpPrefix.isIp4()) {
+ selectorBuilder.matchIPDst(dstIpPrefix);
+ } else {
+ selectorBuilder.matchIPv6Dst(dstIpPrefix);
+ }
+ }
+
+ if ((srcIpPrefix != null) && (dstIpPrefix != null) &&
+ (srcIpPrefix.version() != dstIpPrefix.version())) {
+ // ERROR: IP src/dst version mismatch
+ throw new IllegalArgumentException(
+ "IP source and destination version mismatch");
+ }
+
+ //
+ // Set the default EthType based on the IP version if the matching
+ // source or destination IP prefixes.
+ //
+ Short ethType = null;
+ if ((srcIpPrefix != null) && srcIpPrefix.isIp6()) {
+ ethType = EthType.IPV6.value();
+ }
+ if ((dstIpPrefix != null) && dstIpPrefix.isIp6()) {
+ ethType = EthType.IPV6.value();
+ }
+ if (!isNullOrEmpty(ethTypeString)) {
+ ethType = EthType.parseFromString(ethTypeString);
+ }
+ if (ethType != null) {
+ selectorBuilder.matchEthType(ethType);
+ }
+ if (!isNullOrEmpty(vlanString)) {
+ selectorBuilder.matchVlanId(VlanId.vlanId(Short.parseShort(vlanString)));
+ }
+ if (!isNullOrEmpty(srcMacString)) {
+ selectorBuilder.matchEthSrc(MacAddress.valueOf(srcMacString));
+ }
+
+ if (!isNullOrEmpty(dstMacString)) {
+ selectorBuilder.matchEthDst(MacAddress.valueOf(dstMacString));
+ }
+
+ if (!isNullOrEmpty(ipProtoString)) {
+ short ipProtoShort = IpProtocol.parseFromString(ipProtoString);
+ selectorBuilder.matchIPProtocol((byte) ipProtoShort);
+ }
+
+ if (!isNullOrEmpty(fLabelString)) {
+ selectorBuilder.matchIPv6FlowLabel(Integer.parseInt(fLabelString));
+ }
+
+ if (!isNullOrEmpty(icmp6TypeString)) {
+ byte icmp6Type = Icmp6Type.parseFromString(icmp6TypeString);
+ selectorBuilder.matchIcmpv6Type(icmp6Type);
+ }
+
+ if (!isNullOrEmpty(icmp6CodeString)) {
+ byte icmp6Code = Icmp6Code.parseFromString(icmp6CodeString);
+ selectorBuilder.matchIcmpv6Code(icmp6Code);
+ }
+
+ if (!isNullOrEmpty(ndTargetString)) {
+ selectorBuilder.matchIPv6NDTargetAddress(Ip6Address.valueOf(ndTargetString));
+ }
+
+ if (!isNullOrEmpty(ndSLLString)) {
+ selectorBuilder.matchIPv6NDSourceLinkLayerAddress(MacAddress.valueOf(ndSLLString));
+ }
+
+ if (!isNullOrEmpty(ndTLLString)) {
+ selectorBuilder.matchIPv6NDTargetLinkLayerAddress(MacAddress.valueOf(ndTLLString));
+ }
+
+ if (!isNullOrEmpty(srcTcpString)) {
+ selectorBuilder.matchTcpSrc(TpPort.tpPort(Integer.parseInt(srcTcpString)));
+ }
+
+ if (!isNullOrEmpty(dstTcpString)) {
+ selectorBuilder.matchTcpDst(TpPort.tpPort(Integer.parseInt(dstTcpString)));
+ }
+
+ if (extHdrStringList != null) {
+ short extHdr = 0;
+ for (String extHdrString : extHdrStringList) {
+ extHdr = (short) (extHdr | ExtHeader.parseFromString(extHdrString));
+ }
+ selectorBuilder.matchIPv6ExthdrFlags(extHdr);
+ }
+
+ return selectorBuilder.build();
+ }
+
+ /**
+ * Generates a traffic treatment for this intent based on command line
+ * arguments presented to the command.
+ *
+ * @return traffic treatment
+ */
+ protected TrafficTreatment buildTrafficTreatment() {
+ final TrafficTreatment.Builder treatmentBuilder = builder();
+ boolean emptyTreatment = true;
+
+ if (!isNullOrEmpty(setEthSrcString)) {
+ treatmentBuilder.setEthSrc(MacAddress.valueOf(setEthSrcString));
+ emptyTreatment = false;
+ }
+
+ if (!isNullOrEmpty(setEthDstString)) {
+ treatmentBuilder.setEthDst(MacAddress.valueOf(setEthDstString));
+ emptyTreatment = false;
+ }
+
+ if (!isNullOrEmpty(setIpSrcString)) {
+ treatmentBuilder.setIpSrc(IpAddress.valueOf(setIpSrcString));
+ emptyTreatment = false;
+ }
+
+ if (!isNullOrEmpty(setIpDstString)) {
+ treatmentBuilder.setIpSrc(IpAddress.valueOf(setIpDstString));
+ emptyTreatment = false;
+ }
+ if (!isNullOrEmpty(setVlan)) {
+ treatmentBuilder.setVlanId(VlanId.vlanId(Short.parseShort(setVlan)));
+ emptyTreatment = false;
+ }
+ if (popVlan) {
+ treatmentBuilder.popVlan();
+ emptyTreatment = false;
+ }
+ if (!isNullOrEmpty(pushVlan)) {
+ treatmentBuilder.pushVlan();
+ treatmentBuilder.setVlanId(VlanId.vlanId(Short.parseShort(pushVlan)));
+ emptyTreatment = false;
+ }
+
+ if (emptyTreatment) {
+ return DefaultTrafficTreatment.emptyTreatment();
+ } else {
+ return treatmentBuilder.build();
+ }
+ }
+
+ /**
+ * Builds the constraint list for this command based on the command line
+ * parameters.
+ *
+ * @return List of constraint objects describing the constraints requested
+ */
+ protected List<Constraint> buildConstraints() {
+ final List<Constraint> constraints = new LinkedList<>();
+
+ // Check for a bandwidth specification
+ if (!isNullOrEmpty(bandwidthString)) {
+ final Bandwidth bandwidth = Bandwidth.bps(Double.parseDouble(bandwidthString));
+ constraints.add(new BandwidthConstraint(new BandwidthResource(bandwidth)));
+ }
+
+ // Check for a lambda specification
+ if (lambda) {
+ constraints.add(new LambdaConstraint(null));
+ }
+ constraints.add(new LinkTypeConstraint(lambda, Link.Type.OPTICAL));
+
+ if (partial) {
+ constraints.add(new PartialFailureConstraint());
+ }
+
+ return constraints;
+ }
+
+ @Override
+ protected ApplicationId appId() {
+ ApplicationId appIdForIntent;
+ if (appId == null) {
+ appIdForIntent = super.appId();
+ } else {
+ CoreService service = get(CoreService.class);
+ appIdForIntent = service.getAppId(appId);
+ }
+ return appIdForIntent;
+ }
+
+ /**
+ * Creates a key for an intent based on command line arguments. If a key
+ * has been specified, it is returned. If no key is specified, null
+ * is returned.
+ *
+ * @return intent key if specified, null otherwise
+ */
+ protected Key key() {
+ Key key = null;
+ ApplicationId appIdForIntent;
+
+ if (intentKey != null) {
+ key = Key.of(intentKey, appId());
+ }
+ return key;
+ }
+
+ /**
+ * Gets the priority to use for the intent.
+ *
+ * @return priority
+ */
+ protected int priority() {
+ return priority;
+ }
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/CountersListCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/CountersListCommand.java
new file mode 100644
index 00000000..a44fdc9f
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/CountersListCommand.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2015 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.cli.net;
+
+import java.util.Map;
+
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.store.service.StorageAdminService;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+/**
+ * Command to list the various counters in the system.
+ */
+@Command(scope = "onos", name = "counters",
+ description = "Lists information about atomic counters in the system")
+public class CountersListCommand extends AbstractShellCommand {
+
+ private static final String FMT = "name=%s value=%d";
+
+ /**
+ * Displays counters as text.
+ *
+ * @param counters counter info
+ */
+ private void displayCounters(Map<String, Long> counters) {
+ counters.forEach((name, value) -> print(FMT, name, value));
+ }
+
+ /**
+ * Converts info for counters into a JSON object.
+ *
+ * @param counters counter info
+ */
+ private JsonNode json(Map<String, Long> counters) {
+ ObjectMapper mapper = new ObjectMapper();
+ ArrayNode jsonCounters = mapper.createArrayNode();
+
+ // Create a JSON node for each counter
+ counters.forEach((name, value) -> {
+ ObjectNode jsonCounter = mapper.createObjectNode();
+ jsonCounter.put("name", name)
+ .put("value", value);
+ jsonCounters.add(jsonCounter);
+ });
+
+ return jsonCounters;
+ }
+
+ /**
+ * Converts info for counters from different databases into a JSON object.
+ *
+ * @param partitionedDbCounters counters info
+ * @param inMemoryDbCounters counters info
+ */
+ private JsonNode jsonAllCounters(Map<String, Long> partitionedDbCounters,
+ Map<String, Long> inMemoryDbCounters) {
+ ObjectMapper mapper = new ObjectMapper();
+ ArrayNode jsonCounters = mapper.createArrayNode();
+
+ // Create a JSON node for partitioned database counter
+ ObjectNode jsonPartitionedDatabaseCounters = mapper.createObjectNode();
+ jsonPartitionedDatabaseCounters.set("partitionedDatabaseCounters",
+ json(partitionedDbCounters));
+ jsonCounters.add(jsonPartitionedDatabaseCounters);
+ // Create a JSON node for in-memory database counter
+ ObjectNode jsonInMemoryDatabseCounters = mapper.createObjectNode();
+ jsonInMemoryDatabseCounters.set("inMemoryDatabaseCounters",
+ json(inMemoryDbCounters));
+ jsonCounters.add(jsonInMemoryDatabseCounters);
+
+ return jsonCounters;
+ }
+
+
+ @Override
+ protected void execute() {
+ StorageAdminService storageAdminService = get(StorageAdminService.class);
+ Map<String, Long> partitionedDatabaseCounters = storageAdminService.getPartitionedDatabaseCounters();
+ Map<String, Long> inMemoryDatabaseCounters = storageAdminService.getInMemoryDatabaseCounters();
+ if (outputJson()) {
+ print("%s", jsonAllCounters(partitionedDatabaseCounters, inMemoryDatabaseCounters));
+ } else {
+ print("Partitioned database counters:");
+ displayCounters(partitionedDatabaseCounters);
+ print("In-memory database counters:");
+ displayCounters(inMemoryDatabaseCounters);
+ }
+ }
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/DeviceIdCompleter.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/DeviceIdCompleter.java
new file mode 100644
index 00000000..82ef5edf
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/DeviceIdCompleter.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2014 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.cli.net;
+
+import org.apache.karaf.shell.console.Completer;
+import org.apache.karaf.shell.console.completer.StringsCompleter;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.net.Device;
+import org.onosproject.net.device.DeviceService;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.SortedSet;
+
+/**
+ * Device ID completer.
+ */
+public class DeviceIdCompleter implements Completer {
+ @Override
+ public int complete(String buffer, int cursor, List<String> candidates) {
+ // Delegate string completer
+ StringsCompleter delegate = new StringsCompleter();
+
+ // Fetch our service and feed it's offerings to the string completer
+ DeviceService service = AbstractShellCommand.get(DeviceService.class);
+ Iterator<Device> it = service.getDevices().iterator();
+ SortedSet<String> strings = delegate.getStrings();
+ while (it.hasNext()) {
+ strings.add(it.next().id().toString());
+ }
+
+ // Now let the completer do the work for figuring out what to offer.
+ return delegate.complete(buffer, cursor, candidates);
+ }
+
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/DevicePortStatsCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/DevicePortStatsCommand.java
new file mode 100644
index 00000000..2e804545
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/DevicePortStatsCommand.java
@@ -0,0 +1,192 @@
+package org.onosproject.cli.net;
+
+/*
+ * Copyright 2015 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.
+ */
+
+import static org.onosproject.net.DeviceId.deviceId;
+
+import java.util.concurrent.TimeUnit;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.commands.Option;
+import org.onosproject.net.Device;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.device.PortStatistics;
+
+/**
+ * Lists port statistic of all ports in the system.
+ */
+@Command(scope = "onos", name = "portstats",
+ description = "Lists statistics of all ports in the system")
+public class DevicePortStatsCommand extends DevicesListCommand {
+
+ @Option(name = "-d", aliases = "--delta", description = "Show Delta Port Statistics,"
+ + "only for the last polling interval",
+ required = false, multiValued = false)
+ private boolean delta = false;
+
+ @Option(name = "-t", aliases = "--table", description = "Show human readable table format for statistics",
+ required = false, multiValued = false)
+ private boolean table = false;
+
+ @Argument(index = 0, name = "uri", description = "Device ID",
+ required = false, multiValued = false)
+ String uri = null;
+
+ private static final String FORMAT =
+ " port=%s, pktRx=%s, pktTx=%s, bytesRx=%s, bytesTx=%s, pktRxDrp=%s, pktTxDrp=%s, Dur=%s";
+
+ @Override
+ protected void execute() {
+ DeviceService deviceService = get(DeviceService.class);
+
+ if (uri == null) {
+ for (Device d : getSortedDevices(deviceService)) {
+ if (delta) {
+ if (table) {
+ printPortStatsDeltaTable(d.id(), deviceService.getPortDeltaStatistics(d.id()));
+ } else {
+ printPortStatsDelta(d.id(), deviceService.getPortDeltaStatistics(d.id()));
+ }
+ } else {
+ printPortStats(d.id(), deviceService.getPortStatistics(d.id()));
+ }
+ }
+ } else {
+ Device d = deviceService.getDevice(deviceId(uri));
+ if (d == null) {
+ error("No such device %s", uri);
+ } else if (delta) {
+ if (table) {
+ printPortStatsDeltaTable(d.id(), deviceService.getPortDeltaStatistics(d.id()));
+ } else {
+ printPortStatsDelta(d.id(), deviceService.getPortDeltaStatistics(d.id()));
+ }
+ } else {
+ printPortStats(d.id(), deviceService.getPortStatistics(d.id()));
+ }
+ }
+ }
+
+ /**
+ * Prints Port Statistics.
+ *
+ * @param deviceId
+ * @param portStats
+ */
+ private void printPortStats(DeviceId deviceId, Iterable<PortStatistics> portStats) {
+
+ print("deviceId=%s", deviceId);
+ for (PortStatistics stat : portStats) {
+ print(FORMAT, stat.port(), stat.packetsReceived(), stat.packetsSent(), stat.bytesReceived(),
+ stat.bytesSent(), stat.packetsRxDropped(), stat.packetsTxDropped(), stat.durationSec());
+ }
+ }
+ /**
+ * Prints Port delta statistics.
+ *
+ * @param deviceId
+ * @param portStats
+ */
+ private void printPortStatsDelta(DeviceId deviceId, Iterable<PortStatistics> portStats) {
+ final String formatDelta = " port=%s, pktRx=%s, pktTx=%s, bytesRx=%s, bytesTx=%s,"
+ + " rateRx=%s, rateTx=%s, pktRxDrp=%s, pktTxDrp=%s, interval=%s";
+ print("deviceId=%s", deviceId);
+ for (PortStatistics stat : portStats) {
+ float duration = ((float) stat.durationSec()) +
+ (((float) stat.durationNano()) / TimeUnit.SECONDS.toNanos(1));
+ float rateRx = stat.bytesReceived() * 8 / duration;
+ float rateTx = stat.bytesSent() * 8 / duration;
+ print(formatDelta, stat.port(),
+ stat.packetsReceived(),
+ stat.packetsSent(),
+ stat.bytesReceived(),
+ stat.bytesSent(),
+ String.format("%.1f", rateRx),
+ String.format("%.1f", rateTx),
+ stat.packetsRxDropped(),
+ stat.packetsTxDropped(),
+ String.format("%.3f", duration));
+ }
+ }
+
+ /**
+ * Prints human readable table with delta Port Statistics for specific device.
+ *
+ * @param deviceId
+ * @param portStats
+ */
+ private void printPortStatsDeltaTable(DeviceId deviceId, Iterable<PortStatistics> portStats) {
+ final String formatDeltaTable = "|%5s | %7s | %7s | %7s | %7s | %7s | %7s | %7s | %7s |%9s |";
+ print("+---------------------------------------------------------------------------------------------------+");
+ print("| DeviceId = %s |", deviceId);
+ print("|---------------------------------------------------------------------------------------------------|");
+ print("| | Receive | Transmit | Time [s] |");
+ print("| Port | Packets | Bytes | Rate bps | Drop | Packets | Bytes | Rate bps | Drop | Interval |");
+ print("|---------------------------------------------------------------------------------------------------|");
+
+ for (PortStatistics stat : portStats) {
+ float duration = ((float) stat.durationSec()) +
+ (((float) stat.durationNano()) / TimeUnit.SECONDS.toNanos(1));
+ float rateRx = stat.bytesReceived() * 8 / duration;
+ float rateTx = stat.bytesSent() * 8 / duration;
+ print(formatDeltaTable, stat.port(),
+ humanReadable(stat.packetsReceived()),
+ humanReadable(stat.bytesReceived()),
+ humanReadableBps(rateRx),
+ humanReadable(stat.packetsRxDropped()),
+ humanReadable(stat.packetsSent()),
+ humanReadable(stat.bytesSent()),
+ humanReadableBps(rateTx),
+ humanReadable(stat.packetsTxDropped()),
+ String.format("%.3f", duration));
+ }
+ print("+---------------------------------------------------------------------------------------------------+");
+ }
+
+ /**
+ * Converts bytes to human readable string with Kilo, Mega, Giga, etc.
+ *
+ * @param bytes input byte array
+ * @return human readble string
+ */
+ public static String humanReadable(long bytes) {
+ int unit = 1000;
+ if (bytes < unit) {
+ return String.format("%s ", bytes);
+ }
+ int exp = (int) (Math.log(bytes) / Math.log(unit));
+ Character pre = ("KMGTPE").charAt(exp - 1);
+ return String.format("%.2f%s", bytes / Math.pow(unit, exp), pre);
+ }
+ /**
+ * Converts bps to human readable format.
+ *
+ * @param bps input rate
+ * @return human readble string
+ */
+ public static String humanReadableBps(float bps) {
+ int unit = 1000;
+ if (bps < unit) {
+ return String.format("%.0f ", (float) bps);
+ }
+ int exp = (int) (Math.log(bps) / Math.log(unit));
+ Character pre = ("KMGTPE").charAt(exp - 1);
+ return String.format("%.2f%s", bps / Math.pow(unit, exp), pre);
+ }
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/DevicePortsListCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/DevicePortsListCommand.java
new file mode 100644
index 00000000..494273cc
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/DevicePortsListCommand.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright 2014 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.cli.net;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.commands.Option;
+import org.onosproject.cli.Comparators;
+import org.onosproject.net.Device;
+import org.onosproject.net.Port;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.device.DeviceService;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import static org.onosproject.net.DeviceId.deviceId;
+
+/**
+ * Lists all ports or all ports of a device.
+ */
+@Command(scope = "onos", name = "ports",
+ description = "Lists all ports or all ports of a device")
+public class DevicePortsListCommand extends DevicesListCommand {
+
+ private static final String FMT = " port=%s, state=%s, type=%s, speed=%s%s";
+
+ @Option(name = "-e", aliases = "--enabled", description = "Show only enabled ports",
+ required = false, multiValued = false)
+ private boolean enabled = false;
+
+ @Option(name = "-d", aliases = "--disabled", description = "Show only disabled ports",
+ required = false, multiValued = false)
+ private boolean disabled = false;
+
+ @Argument(index = 0, name = "uri", description = "Device ID",
+ required = false, multiValued = false)
+ String uri = null;
+
+ @Override
+ protected void execute() {
+ DeviceService service = get(DeviceService.class);
+ if (uri == null) {
+ if (outputJson()) {
+ print("%s", jsonPorts(service, getSortedDevices(service)));
+ } else {
+ for (Device device : getSortedDevices(service)) {
+ printDevice(service, device);
+ }
+ }
+
+ } else {
+ Device device = service.getDevice(deviceId(uri));
+ if (device == null) {
+ error("No such device %s", uri);
+ } else if (outputJson()) {
+ print("%s", jsonPorts(service, new ObjectMapper(), device));
+ } else {
+ printDevice(service, device);
+ }
+ }
+ }
+
+ /**
+ * Produces JSON array containing ports of the specified devices.
+ *
+ * @param service device service
+ * @param devices collection of devices
+ * @return JSON array
+ */
+ public JsonNode jsonPorts(DeviceService service, Iterable<Device> devices) {
+ ObjectMapper mapper = new ObjectMapper();
+ ArrayNode result = mapper.createArrayNode();
+ for (Device device : devices) {
+ result.add(jsonPorts(service, mapper, device));
+ }
+ return result;
+ }
+
+ /**
+ * Produces JSON array containing ports of the specified device.
+ *
+ * @param service device service
+ * @param mapper object mapper
+ * @param device infrastructure devices
+ * @return JSON array
+ */
+ public JsonNode jsonPorts(DeviceService service, ObjectMapper mapper, Device device) {
+ ObjectNode result = mapper.createObjectNode();
+ ArrayNode ports = mapper.createArrayNode();
+ for (Port port : service.getPorts(device.id())) {
+ if (isIncluded(port)) {
+ ports.add(mapper.createObjectNode()
+ .put("port", portName(port.number()))
+ .put("isEnabled", port.isEnabled())
+ .put("type", port.type().toString().toLowerCase())
+ .put("portSpeed", port.portSpeed())
+ .set("annotations", annotations(mapper, port.annotations())));
+ }
+ }
+ result.set("device", jsonForEntity(device, Device.class));
+ result.set("ports", ports);
+ return result;
+ }
+
+ private String portName(PortNumber port) {
+ return port.equals(PortNumber.LOCAL) ? "local" : port.toString();
+ }
+
+ // Determines if a port should be included in output.
+ private boolean isIncluded(Port port) {
+ return enabled && port.isEnabled() || disabled && !port.isEnabled() ||
+ !enabled && !disabled;
+ }
+
+ @Override
+ protected void printDevice(DeviceService service, Device device) {
+ super.printDevice(service, device);
+ List<Port> ports = new ArrayList<>(service.getPorts(device.id()));
+ Collections.sort(ports, Comparators.PORT_COMPARATOR);
+ for (Port port : ports) {
+ if (isIncluded(port)) {
+ print(FMT, portName(port.number()),
+ port.isEnabled() ? "enabled" : "disabled",
+ port.type().toString().toLowerCase(), port.portSpeed(),
+ annotations(port.annotations()));
+ }
+ }
+ }
+
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/DeviceRemoveCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/DeviceRemoveCommand.java
new file mode 100644
index 00000000..1226e436
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/DeviceRemoveCommand.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2014 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.cli.net;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.device.DeviceAdminService;
+
+/**
+ * Removes an infrastructure device.
+ */
+@Command(scope = "onos", name = "device-remove",
+ description = "Removes an infrastructure device")
+public class DeviceRemoveCommand extends AbstractShellCommand {
+
+ @Argument(index = 0, name = "uri", description = "Device ID",
+ required = true, multiValued = false)
+ String uri = null;
+
+ @Override
+ protected void execute() {
+ get(DeviceAdminService.class).removeDevice(DeviceId.deviceId(uri));
+ }
+
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/DeviceRoleCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/DeviceRoleCommand.java
new file mode 100644
index 00000000..17fc87a3
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/DeviceRoleCommand.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2014 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.cli.net;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.cluster.NodeId;
+import org.onosproject.mastership.MastershipAdminService;
+import org.onosproject.net.MastershipRole;
+
+import com.google.common.util.concurrent.Futures;
+
+import static org.onosproject.net.DeviceId.deviceId;
+
+/**
+ * Sets role of the controller node for the given infrastructure device.
+ */
+@Command(scope = "onos", name = "device-role",
+ description = "Sets role of the controller node for the given infrastructure device")
+public class DeviceRoleCommand extends AbstractShellCommand {
+
+ @Argument(index = 0, name = "uri", description = "Device ID",
+ required = true, multiValued = false)
+ String uri = null;
+
+ @Argument(index = 1, name = "node", description = "Node ID",
+ required = true, multiValued = false)
+ String node = null;
+
+ @Argument(index = 2, name = "role", description = "Mastership role",
+ required = true, multiValued = false)
+ String role = null;
+
+ @Override
+ protected void execute() {
+ MastershipAdminService service = get(MastershipAdminService.class);
+ MastershipRole mastershipRole = MastershipRole.valueOf(role.toUpperCase());
+ Futures.getUnchecked(service.setRole(new NodeId(node), deviceId(uri), mastershipRole));
+ }
+
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/DevicesListCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/DevicesListCommand.java
new file mode 100644
index 00000000..e40bcad6
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/DevicesListCommand.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2014 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.cli.net;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.cli.Comparators;
+import org.onosproject.net.Device;
+import org.onosproject.net.device.DeviceService;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+
+import static com.google.common.collect.Lists.newArrayList;
+
+/**
+ * Lists all infrastructure devices.
+ */
+@Command(scope = "onos", name = "devices",
+ description = "Lists all infrastructure devices")
+public class DevicesListCommand extends AbstractShellCommand {
+
+ private static final String FMT =
+ "id=%s, available=%s, role=%s, type=%s, mfr=%s, hw=%s, sw=%s, serial=%s%s";
+
+ @Override
+ protected void execute() {
+ DeviceService service = get(DeviceService.class);
+ if (outputJson()) {
+ print("%s", json(getSortedDevices(service)));
+ } else {
+ for (Device device : getSortedDevices(service)) {
+ printDevice(service, device);
+ }
+ }
+ }
+
+ /**
+ * Returns JSON node representing the specified devices.
+ *
+ * @param devices collection of devices
+ * @return JSON node
+ */
+ private JsonNode json(Iterable<Device> devices) {
+ ObjectMapper mapper = new ObjectMapper();
+ ArrayNode result = mapper.createArrayNode();
+ for (Device device : devices) {
+ result.add(jsonForEntity(device, Device.class));
+ }
+ return result;
+ }
+
+ /**
+ * Returns the list of devices sorted using the device ID URIs.
+ *
+ * @param service device service
+ * @return sorted device list
+ */
+ public static List<Device> getSortedDevices(DeviceService service) {
+ List<Device> devices = newArrayList(service.getDevices());
+ Collections.sort(devices, Comparators.ELEMENT_COMPARATOR);
+ return devices;
+ }
+
+ /**
+ * Prints information about the specified device.
+ *
+ * @param service device service
+ * @param device infrastructure device
+ */
+ protected void printDevice(DeviceService service, Device device) {
+ if (device != null) {
+ print(FMT, device.id(), service.isAvailable(device.id()),
+ service.getRole(device.id()), device.type(),
+ device.manufacturer(), device.hwVersion(), device.swVersion(),
+ device.serialNumber(), annotations(device.annotations()));
+ }
+ }
+
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/DriverNameCompleter.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/DriverNameCompleter.java
new file mode 100644
index 00000000..2ba8a20a
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/DriverNameCompleter.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2015 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.cli.net;
+
+import org.apache.karaf.shell.console.Completer;
+import org.apache.karaf.shell.console.completer.StringsCompleter;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.net.driver.DriverAdminService;
+
+import java.util.List;
+import java.util.SortedSet;
+
+/**
+ * Device driver name completer.
+ */
+public class DriverNameCompleter implements Completer {
+ @Override
+ public int complete(String buffer, int cursor, List<String> candidates) {
+ // Delegate string completer
+ StringsCompleter delegate = new StringsCompleter();
+ SortedSet<String> strings = delegate.getStrings();
+
+ // Fetch our service and feed it's offerings to the string completer
+ DriverAdminService service = AbstractShellCommand.get(DriverAdminService.class);
+ service.getDrivers().forEach(d -> strings.add(d.name()));
+
+ // Now let the completer do the work for figuring out what to offer.
+ return delegate.complete(buffer, cursor, candidates);
+ }
+
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/DriversListCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/DriversListCommand.java
new file mode 100644
index 00000000..05d9e957
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/DriversListCommand.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2015 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.cli.net;
+
+import java.util.Set;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.net.driver.Driver;
+import org.onosproject.net.driver.DriverAdminService;
+
+import com.fasterxml.jackson.databind.node.ArrayNode;
+
+/**
+ * Lists device drivers.
+ */
+@Command(scope = "onos", name = "drivers",
+ description = "Lists device drivers")
+public class DriversListCommand extends AbstractShellCommand {
+
+ private static final String FMT = "driver=%s, extends=%s, mfr=%s, hw=%s, sw=%s";
+ private static final String FMT_B = " %s via %s";
+ private static final String FMT_P = " %s=%s";
+
+ @Argument(index = 0, name = "driverName", description = "Driver name",
+ required = false, multiValued = false)
+ String driverName = null;
+
+ @Override
+ protected void execute() {
+ DriverAdminService service = get(DriverAdminService.class);
+
+ if (driverName != null) {
+ printDriver(service.getDriver(driverName));
+ } else {
+ if (outputJson()) {
+ json(service.getDrivers());
+ } else {
+ service.getDrivers().forEach(this::printDriver);
+ }
+ }
+ }
+
+ private void json(Driver driver) {
+ print("%s", jsonForEntity(driver, Driver.class));
+ }
+
+ private void json(Set<Driver> drivers) {
+ ArrayNode result = mapper().createArrayNode();
+ drivers.forEach(driver -> result.add(jsonForEntity(driver, Driver.class)));
+ print("%s", result.toString());
+ }
+
+ private void printDriver(Driver driver) {
+ if (outputJson()) {
+ json(driver);
+ } else {
+ Driver parent = driver.parent();
+ print(FMT, driver.name(), parent != null ? parent.name() : "none",
+ driver.manufacturer(), driver.hwVersion(), driver.swVersion());
+ driver.behaviours().forEach(b -> print(FMT_B, b.getCanonicalName(),
+ driver.implementation(b).getCanonicalName()));
+ driver.properties().forEach((k, v) -> print(FMT_P, k, v));
+ }
+ }
+
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/EdgePortsListCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/EdgePortsListCommand.java
new file mode 100644
index 00000000..1a9235e6
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/EdgePortsListCommand.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2014 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.cli.net;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.net.edge.EdgePortService;
+
+import static org.onosproject.net.DeviceId.deviceId;
+
+/**
+ * Lists all edge ports.
+ */
+@Command(scope = "onos", name = "edge-ports",
+ description = "Lists all edge ports.")
+public class EdgePortsListCommand extends AbstractShellCommand {
+
+ private static final String FMT = "%s/%s";
+
+ @Argument(index = 0, name = "uri", description = "Device ID",
+ required = false, multiValued = false)
+ String uri = null;
+
+
+
+ @Override
+ protected void execute() {
+ EdgePortService service = get(EdgePortService.class);
+ if (uri == null) {
+ service.getEdgePoints().forEach(e -> print(FMT, e.deviceId(), e.port()));
+ } else {
+ service.getEdgePoints(deviceId(uri)).forEach(e -> print(FMT, e.deviceId(), e.port()));
+ }
+ }
+
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/EthType.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/EthType.java
new file mode 100644
index 00000000..02c97b8f
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/EthType.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2014-2015 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.cli.net;
+
+import org.onlab.packet.Ethernet;
+
+/**
+ * Allowed values for Ethernet types. Used by the CLI completer for
+ * connectivity based intent L2 parameters.
+ */
+public enum EthType {
+ /** ARP. */
+ ARP(Ethernet.TYPE_ARP),
+ /** RARP. */
+ RARP(Ethernet.TYPE_RARP),
+ /** IPV4. */
+ IPV4(Ethernet.TYPE_IPV4),
+ /** IPV6. */
+ IPV6(Ethernet.TYPE_IPV6),
+ /** LLDP. */
+ LLDP(Ethernet.TYPE_LLDP),
+ /** BSN. */
+ BSN(Ethernet.TYPE_BSN);
+
+ private short value;
+
+ /**
+ * Constructs an EthType with the given value.
+ *
+ * @param value value to use when this EthType is seen
+ */
+ private EthType(short value) {
+ this.value = value;
+ }
+
+ /**
+ * Gets the value to use for this EthType.
+ *
+ * @return short value to use for this EthType
+ */
+ public short value() {
+ return this.value;
+ }
+
+ /**
+ * Parse a string input that could contain an EthType value. The value
+ * may appear in the string either as a known protocol name (one of the
+ * values of this enum), or a numeric protocol value.
+ *
+ * @param input the input string to parse
+ * @return the numeric value of the parsed Ethernet type
+ * @throws IllegalArgumentException if the input string does not contain a
+ * value that can be parsed into an Ethernet type
+ */
+ public static short parseFromString(String input) {
+ try {
+ return valueOf(input).value();
+ } catch (IllegalArgumentException e) {
+ // The input is not a known Ethernet type name, let's see if it's an
+ // Ethernet type value (short). We parse with Integer to handle
+ // unsigned values correctly.
+ try {
+ return (short) Integer.parseInt(input);
+ } catch (NumberFormatException e1) {
+ throw new IllegalArgumentException(
+ "EthType value must be either a string protocol name"
+ + " or a 16-bit protocol value");
+ }
+ }
+ }
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/EthTypeCompleter.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/EthTypeCompleter.java
new file mode 100644
index 00000000..b6a2285c
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/EthTypeCompleter.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2014 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.cli.net;
+
+import java.util.List;
+import java.util.SortedSet;
+
+import org.apache.karaf.shell.console.Completer;
+import org.apache.karaf.shell.console.completer.StringsCompleter;
+
+/**
+ * Ethernet type completer.
+ */
+public class EthTypeCompleter implements Completer {
+ @Override
+ public int complete(String buffer, int cursor, List<String> candidates) {
+ // Delegate string completer
+ StringsCompleter delegate = new StringsCompleter();
+ SortedSet<String> strings = delegate.getStrings();
+
+ for (EthType eth : EthType.values()) {
+ strings.add(eth.toString());
+ }
+
+ // Now let the completer do the work for figuring out what to offer.
+ return delegate.complete(buffer, cursor, candidates);
+ }
+
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/ExtHeader.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/ExtHeader.java
new file mode 100644
index 00000000..e27332e1
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/ExtHeader.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2014 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.cli.net;
+
+/**
+ * Known values for IPv6 extension header field that can be supplied to the CLI.
+ */
+public enum ExtHeader {
+ /** No next header. */
+ NOEXT((short) (1 << 0)),
+ /** Encapsulated Security Payload. */
+ ESP((short) (1 << 1)),
+ /** Authentication header. */
+ AUTH((short) (1 << 2)),
+ /** Destination header. */
+ DEST((short) (1 << 3)),
+ /** Fragment header. */
+ FRAG((short) (1 << 4)),
+ /** Router header. */
+ ROUTE((short) (1 << 5)),
+ /** Hop-by-hop header. */
+ HOP((short) (1 << 6)),
+ /** Unexpected repeats encountered. */
+ UNREP((short) (1 << 7)),
+ /** Unexpected sequencing encountered. */
+ UNSEQ((short) (1 << 8));
+
+ private short value;
+
+ /**
+ * Constructs an ExtHeader with the given value.
+ *
+ * @param value value to use when this ExtHeader is seen
+ */
+ private ExtHeader(short value) {
+ this.value = value;
+ }
+
+ /**
+ * Gets the value to use for this ExtHeader.
+ *
+ * @return short value to use for this ExtHeader
+ */
+ public short value() {
+ return this.value;
+ }
+
+ /**
+ * Parse a string input that could contain an ExtHeader value. The value
+ * may appear in the string either as a known exntension header name (one of the
+ * values of this enum), or a numeric extension header value.
+ *
+ * @param input the input string to parse
+ * @return the numeric value of the parsed IPv6 extension header
+ * @throws IllegalArgumentException if the input string does not contain a
+ * value that can be parsed into an IPv6 extension header
+ */
+ public static short parseFromString(String input) {
+ try {
+ return valueOf(input).value();
+ } catch (IllegalArgumentException e) {
+ // The input is not a known IPv6 extension header name, let's see if
+ // it's an IPv6 extension header value (short).
+ // We parse with Short to handle unsigned values correctly.
+ try {
+ return Short.parseShort(input);
+ } catch (NumberFormatException e1) {
+ throw new IllegalArgumentException(
+ "ExtHeader value must be either a string extension header name"
+ + " or an 8-bit extension header value");
+ }
+ }
+ }
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/ExtHeaderCompleter.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/ExtHeaderCompleter.java
new file mode 100644
index 00000000..1242e119
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/ExtHeaderCompleter.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2014 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.cli.net;
+
+import org.apache.karaf.shell.console.Completer;
+import org.apache.karaf.shell.console.completer.StringsCompleter;
+
+import java.util.List;
+import java.util.SortedSet;
+
+/**
+ * IPv6 extension header completer.
+ */
+public class ExtHeaderCompleter implements Completer {
+ @Override
+ public int complete(String buffer, int cursor, List<String> candidates) {
+ // Delegate string completer
+ StringsCompleter delegate = new StringsCompleter();
+ SortedSet<String> strings = delegate.getStrings();
+
+ for (ExtHeader extHeader : ExtHeader.values()) {
+ strings.add(extHeader.toString());
+ }
+
+ // Now let the completer do the work for figuring out what to offer.
+ return delegate.complete(buffer, cursor, candidates);
+ }
+
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/FlowObjectiveCompositionCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/FlowObjectiveCompositionCommand.java
new file mode 100644
index 00000000..9bacc7ae
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/FlowObjectiveCompositionCommand.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2015 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.cli.net;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.net.flowobjective.FlowObjectiveService;
+
+/**
+ * Manages FlowObjectiveComposition policy.
+ */
+@Command(scope = "onos", name = "policy",
+ description = "Manages FlowObjectiveComposition policy")
+public class FlowObjectiveCompositionCommand extends AbstractShellCommand {
+
+ @Argument(index = 0, name = "command",
+ description = "Command name (install)",
+ required = true, multiValued = false)
+ String command = null;
+
+ @Argument(index = 1, name = "names", description = "policy string",
+ required = true, multiValued = true)
+ String[] policies = null;
+
+ @Override
+ protected void execute() {
+ FlowObjectiveService service = get(FlowObjectiveService.class);
+ service.initPolicy(policies[0]);
+ print("Policy %s installed", policies[0]);
+ }
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/FlowRuleStatusCompleter.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/FlowRuleStatusCompleter.java
new file mode 100644
index 00000000..ce910c95
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/FlowRuleStatusCompleter.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2014 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.cli.net;
+
+import java.util.List;
+import java.util.SortedSet;
+
+import org.apache.karaf.shell.console.Completer;
+import org.apache.karaf.shell.console.completer.StringsCompleter;
+import org.onosproject.net.flow.FlowEntry.FlowEntryState;
+
+/**
+ * Flow rule status completer.
+ */
+public class FlowRuleStatusCompleter implements Completer {
+ @Override
+ public int complete(String buffer, int cursor, List<String> candidates) {
+ // Delegate string completer
+ StringsCompleter delegate = new StringsCompleter();
+
+ FlowEntryState[] states = FlowEntryState.values();
+ SortedSet<String> strings = delegate.getStrings();
+ for (int i = 0; i < states.length; i++) {
+ strings.add(states[i].toString().toLowerCase());
+ }
+ strings.add(FlowsListCommand.ANY);
+
+ // Now let the completer do the work for figuring out what to offer.
+ return delegate.complete(buffer, cursor, candidates);
+ }
+
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/FlowsListCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/FlowsListCommand.java
new file mode 100644
index 00000000..de84f519
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/FlowsListCommand.java
@@ -0,0 +1,169 @@
+/*
+ * Copyright 2014-2015 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.cli.net;
+
+import static com.google.common.collect.Lists.newArrayList;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.SortedMap;
+import java.util.TreeMap;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.cli.Comparators;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.CoreService;
+import org.onosproject.net.Device;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.flow.FlowEntry;
+import org.onosproject.net.flow.FlowEntry.FlowEntryState;
+import org.onosproject.net.flow.FlowRuleService;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+/**
+ * Lists all currently-known flows.
+ */
+@Command(scope = "onos", name = "flows",
+ description = "Lists all currently-known flows.")
+public class FlowsListCommand extends AbstractShellCommand {
+
+ public static final String ANY = "any";
+
+ private static final String FMT =
+ " id=%s, state=%s, bytes=%s, packets=%s, duration=%s, priority=%s, tableId=%s appId=%s, payLoad=%s";
+ private static final String TFMT = " treatment=%s";
+ private static final String SFMT = " selector=%s";
+
+ @Argument(index = 1, name = "uri", description = "Device ID",
+ required = false, multiValued = false)
+ String uri = null;
+
+ @Argument(index = 0, name = "state", description = "Flow Rule state",
+ required = false, multiValued = false)
+ String state = null;
+
+ @Override
+ protected void execute() {
+ CoreService coreService = get(CoreService.class);
+ DeviceService deviceService = get(DeviceService.class);
+ FlowRuleService service = get(FlowRuleService.class);
+ SortedMap<Device, List<FlowEntry>> flows = getSortedFlows(deviceService, service);
+
+ if (outputJson()) {
+ print("%s", json(flows.keySet(), flows));
+ } else {
+ flows.forEach((device, flow) -> printFlows(device, flow, coreService));
+ }
+ }
+
+ /**
+ * Produces a JSON array of flows grouped by the each device.
+ *
+ * @param devices collection of devices to group flow by
+ * @param flows collection of flows per each device
+ * @return JSON array
+ */
+ private JsonNode json(Iterable<Device> devices,
+ Map<Device, List<FlowEntry>> flows) {
+ ObjectMapper mapper = new ObjectMapper();
+ ArrayNode result = mapper.createArrayNode();
+ for (Device device : devices) {
+ result.add(json(mapper, device, flows.get(device)));
+ }
+ return result;
+ }
+
+ // Produces JSON object with the flows of the given device.
+ private ObjectNode json(ObjectMapper mapper,
+ Device device, List<FlowEntry> flows) {
+ ObjectNode result = mapper.createObjectNode();
+ ArrayNode array = mapper.createArrayNode();
+
+ flows.forEach(flow -> array.add(jsonForEntity(flow, FlowEntry.class)));
+
+ result.put("device", device.id().toString())
+ .put("flowCount", flows.size())
+ .set("flows", array);
+ return result;
+ }
+
+ /**
+ * Returns the list of devices sorted using the device ID URIs.
+ *
+ * @param deviceService device service
+ * @param service flow rule service
+ * @return sorted device list
+ */
+ protected SortedMap<Device, List<FlowEntry>> getSortedFlows(DeviceService deviceService,
+ FlowRuleService service) {
+ SortedMap<Device, List<FlowEntry>> flows = new TreeMap<>(Comparators.ELEMENT_COMPARATOR);
+ List<FlowEntry> rules;
+ FlowEntryState s = null;
+ if (state != null && !state.equals("any")) {
+ s = FlowEntryState.valueOf(state.toUpperCase());
+ }
+ Iterable<Device> devices = uri == null ? deviceService.getDevices() :
+ Collections.singletonList(deviceService.getDevice(DeviceId.deviceId(uri)));
+ for (Device d : devices) {
+ if (s == null) {
+ rules = newArrayList(service.getFlowEntries(d.id()));
+ } else {
+ rules = newArrayList();
+ for (FlowEntry f : service.getFlowEntries(d.id())) {
+ if (f.state().equals(s)) {
+ rules.add(f);
+ }
+ }
+ }
+ rules.sort(Comparators.FLOW_RULE_COMPARATOR);
+ flows.put(d, rules);
+ }
+ return flows;
+ }
+
+ /**
+ * Prints flows.
+ *
+ * @param d the device
+ * @param flows the set of flows for that device
+ * @param coreService core system service
+ */
+ protected void printFlows(Device d, List<FlowEntry> flows,
+ CoreService coreService) {
+ boolean empty = flows == null || flows.isEmpty();
+ print("deviceId=%s, flowRuleCount=%d", d.id(), empty ? 0 : flows.size());
+ if (!empty) {
+ for (FlowEntry f : flows) {
+ ApplicationId appId = coreService.getAppId(f.appId());
+ print(FMT, Long.toHexString(f.id().value()), f.state(),
+ f.bytes(), f.packets(), f.life(), f.priority(), f.tableId(),
+ appId != null ? appId.name() : "<none>",
+ f.payLoad() == null ? null : f.payLoad().payLoad().toString());
+ print(SFMT, f.selector().criteria());
+ print(TFMT, f.treatment());
+ }
+ }
+ }
+
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/GetStatistics.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/GetStatistics.java
new file mode 100644
index 00000000..911e03c2
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/GetStatistics.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2014 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.cli.net;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.PortNumber;
+
+import org.onosproject.net.statistic.Load;
+import org.onosproject.net.statistic.StatisticService;
+
+
+import static org.onosproject.net.DeviceId.deviceId;
+import static org.onosproject.net.PortNumber.portNumber;
+
+/**
+ * Fetches statistics.
+ */
+@Command(scope = "onos", name = "get-stats",
+ description = "Fetches stats for a connection point")
+public class GetStatistics extends AbstractShellCommand {
+
+ @Argument(index = 0, name = "connectPoint",
+ description = "Device/Port Description",
+ required = true, multiValued = false)
+ String connectPoint = null;
+
+
+ @Override
+ protected void execute() {
+ StatisticService service = get(StatisticService.class);
+
+ DeviceId ingressDeviceId = deviceId(getDeviceId(connectPoint));
+ PortNumber ingressPortNumber = portNumber(getPortNumber(connectPoint));
+ ConnectPoint cp = new ConnectPoint(ingressDeviceId, ingressPortNumber);
+
+ Load load = service.load(cp);
+
+ print("Load on %s -> %s", cp, load);
+ }
+
+ /**
+ * Extracts the port number portion of the ConnectPoint.
+ *
+ * @param deviceString string representing the device/port
+ * @return port number as a string, empty string if the port is not found
+ */
+ private String getPortNumber(String deviceString) {
+ int slash = deviceString.indexOf('/');
+ if (slash <= 0) {
+ return "";
+ }
+ return deviceString.substring(slash + 1, deviceString.length());
+ }
+
+ /**
+ * Extracts the device ID portion of the ConnectPoint.
+ *
+ * @param deviceString string representing the device/port
+ * @return device ID string
+ */
+ private String getDeviceId(String deviceString) {
+ int slash = deviceString.indexOf('/');
+ if (slash <= 0) {
+ return "";
+ }
+ return deviceString.substring(0, slash);
+ }
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/GlobalLabelApplyCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/GlobalLabelApplyCommand.java
new file mode 100644
index 00000000..a8e8f2e0
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/GlobalLabelApplyCommand.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2014-2015 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.cli.net;
+
+import java.util.Collection;
+import java.util.Iterator;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.incubator.net.resource.label.DefaultLabelResource;
+import org.onosproject.incubator.net.resource.label.LabelResource;
+import org.onosproject.incubator.net.resource.label.LabelResourceService;
+
+@Command(scope = "onos", name = "global-label-apply",
+ description = "Apply global labels from global resource pool")
+public class GlobalLabelApplyCommand extends AbstractShellCommand {
+ @Argument(index = 0, name = "applyNum",
+ description = "Applying number means how many labels applications want to use.",
+ required = true, multiValued = false)
+ String applyNum = null;
+
+ private static final String FMT = "deviceid=%s, labelresourceid=%s";
+
+ @Override
+ protected void execute() {
+ LabelResourceService lrs = get(LabelResourceService.class);
+ Collection<LabelResource> result =
+ lrs.applyFromGlobalPool(Long.parseLong(applyNum));
+ if (result.size() > 0) {
+ for (Iterator<LabelResource> iterator = result.iterator(); iterator
+ .hasNext();) {
+ DefaultLabelResource defaultLabelResource = (DefaultLabelResource) iterator
+ .next();
+ print(FMT, defaultLabelResource.deviceId().toString(),
+ defaultLabelResource.labelResourceId().toString());
+ }
+ }
+ }
+
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/GlobalLabelCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/GlobalLabelCommand.java
new file mode 100644
index 00000000..92f39ccd
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/GlobalLabelCommand.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2014-2015 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.cli.net;
+
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.incubator.net.resource.label.LabelResourcePool;
+import org.onosproject.incubator.net.resource.label.LabelResourceService;
+
+@Command(scope = "onos", name = "global-label-pool",
+ description = "Gets global label resource pool information.")
+public class GlobalLabelCommand extends AbstractShellCommand {
+ private static final String FMT = "deviceid=%s, beginLabel=%s,"
+ + "endLabel=%s, totalNum=%s, usedNum=%s, currentUsedMaxLabelId=%s,"
+ + "releaseLabelIds=%s";
+
+ @Override
+ protected void execute() {
+ LabelResourceService lrs = get(LabelResourceService.class);
+ LabelResourcePool pool = lrs.getGlobalLabelResourcePool();
+ if (pool != null) {
+ print(FMT, pool.deviceId().toString(), pool.beginLabel(),
+ pool.endLabel(), pool.totalNum(), pool.usedNum(),
+ pool.currentUsedMaxLabelId(), pool.releaseLabelId()
+ .toString());
+ }
+ }
+
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/GlobalLabelPoolCreateCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/GlobalLabelPoolCreateCommand.java
new file mode 100644
index 00000000..3e226678
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/GlobalLabelPoolCreateCommand.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2014-2015 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.cli.net;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.incubator.net.resource.label.LabelResourceAdminService;
+import org.onosproject.incubator.net.resource.label.LabelResourceId;
+
+/**
+ * create label resource pool by specific device id.
+ */
+@Command(scope = "onos", name = "global-label-pool-create",
+description = "Creates global label resource pool.")
+public class GlobalLabelPoolCreateCommand extends AbstractShellCommand {
+ @Argument(index = 0, name = "beginLabel",
+ description = "The first label of global label resource pool.",
+ required = true, multiValued = false)
+ String beginLabel = null;
+ @Argument(index = 1, name = "endLabel",
+ description = "The last label of global label resource pool.",
+ required = true, multiValued = false)
+ String endLabel = null;
+
+ @Override
+ protected void execute() {
+ LabelResourceAdminService lrs = get(LabelResourceAdminService.class);
+ lrs.createGlobalPool(LabelResourceId.labelResourceId(Long
+ .parseLong(beginLabel)), LabelResourceId.labelResourceId(Long
+ .parseLong(endLabel)));
+ }
+
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/GlobalLabelPoolDestoryCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/GlobalLabelPoolDestoryCommand.java
new file mode 100644
index 00000000..ae1bee64
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/GlobalLabelPoolDestoryCommand.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2014-2015 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.cli.net;
+
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.incubator.net.resource.label.LabelResourceAdminService;
+
+@Command(scope = "onos", name = "global-label-pool-destroy",
+description = "Destroys global label resource pool")
+public class GlobalLabelPoolDestoryCommand extends AbstractShellCommand {
+ @Override
+ protected void execute() {
+ LabelResourceAdminService lrs = get(LabelResourceAdminService.class);
+ lrs.destroyGlobalPool();
+ }
+
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/GlobalLabelReleaseCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/GlobalLabelReleaseCommand.java
new file mode 100644
index 00000000..737f7961
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/GlobalLabelReleaseCommand.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2014-2015 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.cli.net;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.incubator.net.resource.label.LabelResourceId;
+import org.onosproject.incubator.net.resource.label.LabelResourceService;
+
+@Command(scope = "onos", name = "global-label-release",
+description = "Releases labels to global label resource pool.")
+public class GlobalLabelReleaseCommand extends AbstractShellCommand {
+ @Argument(index = 0, name = "releaseLabelIds",
+ description = "Represents for the label ids that are released. They are splited by dot symbol",
+ required = true, multiValued = false)
+ String releaseLabelIds = null;
+
+ @Override
+ protected void execute() {
+ LabelResourceService lrs = get(LabelResourceService.class);
+ Set<LabelResourceId> release = new HashSet<LabelResourceId>();
+ String[] labelIds = releaseLabelIds.split(",");
+ LabelResourceId resource = null;
+ for (int i = 0; i < labelIds.length; i++) {
+ resource = LabelResourceId.labelResourceId(Long.parseLong(labelIds[i]));
+ release.add(resource);
+ }
+ lrs.releaseToGlobalPool(release);
+ }
+
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/GroupsListCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/GroupsListCommand.java
new file mode 100644
index 00000000..afbcab80
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/GroupsListCommand.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright 2015 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.cli.net;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.SortedMap;
+import java.util.TreeMap;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.cli.Comparators;
+import org.onosproject.net.Device;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.group.Group;
+import org.onosproject.net.group.Group.GroupState;
+import org.onosproject.net.group.GroupBucket;
+import org.onosproject.net.group.GroupService;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+
+import static com.google.common.collect.Lists.newArrayList;
+
+/**
+ * Lists all groups in the system.
+ */
+@Command(scope = "onos", name = "groups",
+ description = "Lists all groups in the system")
+public class GroupsListCommand extends AbstractShellCommand {
+
+ private static final String FORMAT =
+ " id=%s, state=%s, bytes=%s, packets=%s, appId=%s";
+ private static final String BUCKET_FORMAT =
+ " id=%s, bucket=%s, bytes=%s, packets=%s, actions=%s";
+
+ @Argument(index = 1, name = "uri", description = "Device ID",
+ required = false, multiValued = false)
+ String uri = null;
+
+ @Argument(index = 0, name = "state", description = "Group state",
+ required = false, multiValued = false)
+ String state;
+
+ private JsonNode json(Map<Device, List<Group>> sortedGroups) {
+ ArrayNode result = mapper().createArrayNode();
+
+ sortedGroups.forEach((device, groups) ->
+ groups.forEach(group ->
+ result.add(jsonForEntity(group, Group.class))));
+
+ return result;
+ }
+
+ @Override
+ protected void execute() {
+ DeviceService deviceService = get(DeviceService.class);
+ GroupService groupService = get(GroupService.class);
+ SortedMap<Device, List<Group>> sortedGroups =
+ getSortedGroups(deviceService, groupService);
+
+ if (outputJson()) {
+ print("%s", json(sortedGroups));
+ } else {
+ sortedGroups.forEach((device, groups) -> printGroups(device.id(), groups));
+ }
+ }
+
+ /**
+ * Returns the list of devices sorted using the device ID URIs.
+ *
+ * @param deviceService device service
+ * @param groupService group service
+ * @return sorted device list
+ */
+ protected SortedMap<Device, List<Group>>
+ getSortedGroups(DeviceService deviceService,
+ GroupService groupService) {
+ SortedMap<Device, List<Group>> sortedGroups =
+ new TreeMap<>(Comparators.ELEMENT_COMPARATOR);
+ List<Group> groups;
+ GroupState s = null;
+ if (state != null && !state.equals("any")) {
+ s = GroupState.valueOf(state.toUpperCase());
+ }
+ Iterable<Device> devices = (uri == null) ? deviceService.getDevices() :
+ Collections.singletonList(deviceService.getDevice(DeviceId.deviceId(uri)));
+ for (Device d : devices) {
+ if (s == null) {
+ groups = newArrayList(groupService.getGroups(d.id()));
+ } else {
+ groups = newArrayList();
+ for (Group g : groupService.getGroups(d.id())) {
+ if (g.state().equals(s)) {
+ groups.add(g);
+ }
+ }
+ }
+ groups.sort(Comparators.GROUP_COMPARATOR);
+ sortedGroups.put(d, groups);
+ }
+ return sortedGroups;
+ }
+
+ private void printGroups(DeviceId deviceId, List<Group> groups) {
+ print("deviceId=%s", deviceId);
+ for (Group group : groups) {
+ print(FORMAT, group.id().id(), group.state(),
+ group.bytes(), group.packets(), group.appId().name());
+ int i = 0;
+ for (GroupBucket bucket:group.buckets().buckets()) {
+ print(BUCKET_FORMAT, group.id().id(), ++i,
+ bucket.bytes(), bucket.packets(),
+ bucket.treatment().allInstructions());
+ }
+ }
+ }
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/HostIdCompleter.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/HostIdCompleter.java
new file mode 100644
index 00000000..4694425f
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/HostIdCompleter.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2014 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.cli.net;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.SortedSet;
+
+import org.apache.karaf.shell.console.Completer;
+import org.apache.karaf.shell.console.completer.StringsCompleter;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.net.Host;
+import org.onosproject.net.host.HostService;
+
+/**
+ * Host ID completer.
+ */
+public class HostIdCompleter implements Completer {
+
+ @Override
+ public int complete(String buffer, int cursor, List<String> candidates) {
+ // Delegate string completer
+ StringsCompleter delegate = new StringsCompleter();
+
+ HostService service = AbstractShellCommand.get(HostService.class);
+ Iterator<Host> it = service.getHosts().iterator();
+ SortedSet<String> strings = delegate.getStrings();
+ while (it.hasNext()) {
+ strings.add(it.next().id().toString());
+ }
+
+ // Now let the completer do the work for figuring out what to offer.
+ return delegate.complete(buffer, cursor, candidates);
+
+ }
+
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/HostRemoveCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/HostRemoveCommand.java
new file mode 100644
index 00000000..c0db07db
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/HostRemoveCommand.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2014 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.cli.net;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.net.HostId;
+import org.onosproject.net.host.HostAdminService;
+
+/**
+ * Removes an end-station host.
+ */
+@Command(scope = "onos", name = "host-remove",
+ description = "Removes an end-station host")
+public class HostRemoveCommand extends AbstractShellCommand {
+
+ @Argument(index = 0, name = "id", description = "Host ID",
+ required = true, multiValued = false)
+ String id = null;
+
+ @Override
+ protected void execute() {
+ get(HostAdminService.class).removeHost(HostId.hostId(id));
+ }
+
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/HostsListCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/HostsListCommand.java
new file mode 100644
index 00000000..a90627e4
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/HostsListCommand.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2014 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.cli.net;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.cli.Comparators;
+import org.onosproject.net.Host;
+import org.onosproject.net.host.HostService;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+
+import static com.google.common.collect.Lists.newArrayList;
+
+/**
+ * Lists all currently-known hosts.
+ */
+@Command(scope = "onos", name = "hosts",
+ description = "Lists all currently-known hosts.")
+public class HostsListCommand extends AbstractShellCommand {
+
+ private static final String FMT =
+ "id=%s, mac=%s, location=%s/%s, vlan=%s, ip(s)=%s%s";
+
+ @Override
+ protected void execute() {
+ HostService service = get(HostService.class);
+ if (outputJson()) {
+ print("%s", json(getSortedHosts(service)));
+ } else {
+ for (Host host : getSortedHosts(service)) {
+ printHost(host);
+ }
+ }
+ }
+
+ // Produces JSON structure.
+ private JsonNode json(Iterable<Host> hosts) {
+ ObjectMapper mapper = new ObjectMapper();
+ ArrayNode result = mapper.createArrayNode();
+
+ hosts.forEach(host -> result.add(jsonForEntity(host, Host.class)));
+ return result;
+ }
+
+ /**
+ * Returns the list of devices sorted using the device ID URIs.
+ *
+ * @param service device service
+ * @return sorted device list
+ */
+ protected List<Host> getSortedHosts(HostService service) {
+ List<Host> hosts = newArrayList(service.getHosts());
+ Collections.sort(hosts, Comparators.ELEMENT_COMPARATOR);
+ return hosts;
+ }
+
+ /**
+ * Prints information about a host.
+ *
+ * @param host end-station host
+ */
+ protected void printHost(Host host) {
+ if (host != null) {
+ print(FMT, host.id(), host.mac(),
+ host.location().deviceId(),
+ host.location().port(),
+ host.vlan(), host.ipAddresses(),
+ annotations(host.annotations()));
+ }
+ }
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/Icmp6Code.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/Icmp6Code.java
new file mode 100644
index 00000000..8568ec62
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/Icmp6Code.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2014 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.cli.net;
+
+import org.onlab.packet.ICMP6;
+
+/**
+ * Known values for ICMPv6 code field that can be supplied to the CLI.
+ */
+public enum Icmp6Code {
+ // Code for DEST_UNREACH
+ /** No route to destination. */
+ NO_ROUTE(ICMP6.NO_ROUTE),
+ /** Communication with destination administratively prohibited. */
+ COMM_PROHIBIT(ICMP6.COMM_PROHIBIT),
+ /** Beyond scope of source address. */
+ BEYOND_SCOPE(ICMP6.BEYOND_SCOPE),
+ /** Address unreachable. */
+ ADDR_UNREACH(ICMP6.ADDR_UNREACH),
+ /** Port unreachable. */
+ PORT_UNREACH(ICMP6.PORT_UNREACH),
+ /** Source address failed ingress/egress policy. */
+ FAIL_POLICY(ICMP6.FAIL_POLICY),
+ /** Reject route to destination. */
+ REJECT_ROUTE(ICMP6.REJECT_ROUTE),
+ /** Error in Source Routing Header. */
+ SRC_ROUTING_HEADER_ERR(ICMP6.SRC_ROUTING_HEADER_ERR),
+
+ // Code for TIME_EXCEED
+ /** Hop limit exceeded in transit. */
+ HOP_LIMIT_EXCEED(ICMP6.HOP_LIMIT_EXCEED),
+ /** Fragment reassembly time exceeded. */
+ DEFRAG_TIME_EXCEED(ICMP6.DEFRAG_TIME_EXCEED),
+
+ // Code for PARAM_ERR
+ /** Erroneous header field encountered. */
+ HDR_FIELD_ERR(ICMP6.HDR_FIELD_ERR),
+ /** Unrecognized Next Header type encountered. */
+ NEXT_HEADER_ERR(ICMP6.NEXT_HEADER_ERR),
+ /** Unrecognized IPv6 option encountered. */
+ IPV6_OPT_ERR(ICMP6.IPV6_OPT_ERR);
+
+ private byte value;
+
+ /**
+ * Constructs an Icmp6Code with the given value.
+ *
+ * @param value value to use when this Icmp6Code is seen
+ */
+ private Icmp6Code(byte value) {
+ this.value = value;
+ }
+
+ /**
+ * Gets the value to use for this Icmp6Code.
+ *
+ * @return short value to use for this Icmp6Code
+ */
+ public byte value() {
+ return this.value;
+ }
+
+ /**
+ * Parse a string input that could contain an Icmp6Code value. The value
+ * may appear in the string either as a known code name (one of the
+ * values of this enum), or a numeric code value.
+ *
+ * @param input the input string to parse
+ * @return the numeric value of the parsed ICMPv6 code
+ * @throws IllegalArgumentException if the input string does not contain a
+ * value that can be parsed into an ICMPv6 code
+ */
+ public static byte parseFromString(String input) {
+ try {
+ return valueOf(input).value();
+ } catch (IllegalArgumentException e) {
+ // The input is not a known ICMPv6 code name, let's see if it's an ICMP6
+ // code value (byte). We parse with Byte to handle unsigned values
+ // correctly.
+ try {
+ return Byte.parseByte(input);
+ } catch (NumberFormatException e1) {
+ throw new IllegalArgumentException(
+ "Icmp6Code value must be either a string code name"
+ + " or an 8-bit code value");
+ }
+ }
+ }
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/Icmp6CodeCompleter.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/Icmp6CodeCompleter.java
new file mode 100644
index 00000000..bf32d4f8
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/Icmp6CodeCompleter.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2014 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.cli.net;
+
+import org.apache.karaf.shell.console.Completer;
+import org.apache.karaf.shell.console.completer.StringsCompleter;
+
+import java.util.List;
+import java.util.SortedSet;
+
+/**
+ * ICMPv6 type completer.
+ */
+public class Icmp6CodeCompleter implements Completer {
+ @Override
+ public int complete(String buffer, int cursor, List<String> candidates) {
+ // Delegate string completer
+ StringsCompleter delegate = new StringsCompleter();
+ SortedSet<String> strings = delegate.getStrings();
+
+ for (Icmp6Code code : Icmp6Code.values()) {
+ strings.add(code.toString());
+ }
+
+ // Now let the completer do the work for figuring out what to offer.
+ return delegate.complete(buffer, cursor, candidates);
+ }
+
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/Icmp6Type.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/Icmp6Type.java
new file mode 100644
index 00000000..a9bffd0a
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/Icmp6Type.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2014 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.cli.net;
+
+import org.onlab.packet.ICMP6;
+
+/**
+ * Known values for ICMPv6 type field that can be supplied to the CLI.
+ */
+public enum Icmp6Type {
+ /** Destination Unreachable. */
+ DEST_UNREACH(ICMP6.DEST_UNREACH),
+ /** Packet Too Big. */
+ PKT_TOO_BIG(ICMP6.PKT_TOO_BIG),
+ /** Time Exceeded. */
+ TIME_EXCEED(ICMP6.TIME_EXCEED),
+ /** Parameter Problem. */
+ PARAM_ERR(ICMP6.PARAM_ERR),
+ /** Echo Request. */
+ ECHO_REQUEST(ICMP6.ECHO_REQUEST),
+ /** Echo Reply. */
+ ECHO_REPLY(ICMP6.ECHO_REPLY),
+ /** Multicast Listener Query. */
+ MCAST_QUERY(ICMP6.MCAST_QUERY),
+ /** Multicast Listener Report. */
+ MCAST_REPORT(ICMP6.MCAST_REPORT),
+ /** Multicast Listener Done. */
+ MCAST_DONE(ICMP6.MCAST_DONE),
+ /** Router Solicitation. */
+ ROUTER_SOLICITATION(ICMP6.ROUTER_SOLICITATION),
+ /** Router Advertisement. */
+ ROUTER_ADVERTISEMENT(ICMP6.ROUTER_ADVERTISEMENT),
+ /** Neighbor Solicitation. */
+ NEIGHBOR_SOLICITATION(ICMP6.NEIGHBOR_SOLICITATION),
+ /** Neighbor Advertisement. */
+ NEIGHBOR_ADVERTISEMENT(ICMP6.NEIGHBOR_ADVERTISEMENT),
+ /** Redirect Message. */
+ REDIRECT(ICMP6.REDIRECT);
+
+
+ private byte value;
+
+ /**
+ * Constructs an Icmp6Type with the given value.
+ *
+ * @param value value to use when this Icmp6Type is seen
+ */
+ private Icmp6Type(byte value) {
+ this.value = value;
+ }
+
+ /**
+ * Gets the value to use for this Icmp6Type.
+ *
+ * @return short value to use for this Icmp6Type
+ */
+ public byte value() {
+ return this.value;
+ }
+
+ /**
+ * Parse a string input that could contain an Icmp6Type value. The value
+ * may appear in the string either as a known type name (one of the
+ * values of this enum), or a numeric type value.
+ *
+ * @param input the input string to parse
+ * @return the numeric value of the parsed ICMPv6 type
+ * @throws IllegalArgumentException if the input string does not contain a
+ * value that can be parsed into an ICMPv6 type
+ */
+ public static byte parseFromString(String input) {
+ try {
+ return valueOf(input).value();
+ } catch (IllegalArgumentException e) {
+ // The input is not a known ICMPv6 type name, let's see if it's an ICMP6
+ // type value (byte). We parse with Byte to handle unsigned values
+ // correctly.
+ try {
+ return Byte.parseByte(input);
+ } catch (NumberFormatException e1) {
+ throw new IllegalArgumentException(
+ "Icmp6Type value must be either a string type name"
+ + " or an 8-bit type value");
+ }
+ }
+ }
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/Icmp6TypeCompleter.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/Icmp6TypeCompleter.java
new file mode 100644
index 00000000..8871388e
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/Icmp6TypeCompleter.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2014 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.cli.net;
+
+import org.apache.karaf.shell.console.Completer;
+import org.apache.karaf.shell.console.completer.StringsCompleter;
+
+import java.util.List;
+import java.util.SortedSet;
+
+/**
+ * ICMPv6 type completer.
+ */
+public class Icmp6TypeCompleter implements Completer {
+ @Override
+ public int complete(String buffer, int cursor, List<String> candidates) {
+ // Delegate string completer
+ StringsCompleter delegate = new StringsCompleter();
+ SortedSet<String> strings = delegate.getStrings();
+
+ for (Icmp6Type type : Icmp6Type.values()) {
+ strings.add(type.toString());
+ }
+
+ // Now let the completer do the work for figuring out what to offer.
+ return delegate.complete(buffer, cursor, candidates);
+ }
+
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/IntentCycleCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/IntentCycleCommand.java
new file mode 100644
index 00000000..1c01c5ba
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/IntentCycleCommand.java
@@ -0,0 +1,206 @@
+/*
+ * Copyright 2015 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.cli.net;
+
+import java.util.EnumSet;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.atomic.AtomicLong;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.onlab.packet.Ethernet;
+import org.onlab.packet.MacAddress;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.flow.DefaultTrafficSelector;
+import org.onosproject.net.flow.DefaultTrafficTreatment;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.intent.Intent;
+import org.onosproject.net.intent.IntentEvent;
+import org.onosproject.net.intent.IntentEvent.Type;
+import org.onosproject.net.intent.IntentListener;
+import org.onosproject.net.intent.IntentService;
+import org.onosproject.net.intent.Key;
+import org.onosproject.net.intent.PointToPointIntent;
+
+import com.google.common.collect.Lists;
+
+import static org.onlab.util.Tools.delay;
+import static org.onosproject.net.DeviceId.deviceId;
+import static org.onosproject.net.PortNumber.portNumber;
+
+/**
+ * Installs point-to-point connectivity intents.
+ */
+@Command(scope = "onos", name = "cycle-intents",
+ description = "Installs random intents to test throughput")
+public class IntentCycleCommand extends AbstractShellCommand
+ implements IntentListener {
+
+ @Argument(index = 0, name = "ingressDevice",
+ description = "Ingress Device/Port Description",
+ required = true, multiValued = false)
+ String ingressDeviceString = null;
+
+ @Argument(index = 1, name = "egressDevice",
+ description = "Egress Device/Port Description",
+ required = true, multiValued = false)
+ String egressDeviceString = null;
+
+ @Argument(index = 2, name = "numberOfIntents",
+ description = "Number of intents to install/withdraw",
+ required = true, multiValued = false)
+ String numberOfIntents = null;
+
+ @Argument(index = 3, name = "keyOffset",
+ description = "Starting point for first key (default: 1)",
+ required = false, multiValued = false)
+ String keyOffsetStr = null;
+
+ private IntentService service;
+ private CountDownLatch latch;
+ private volatile long start, end;
+ private int count;
+ private int keyOffset;
+ private long submitCounter = 0;
+ private AtomicLong eventCounter = new AtomicLong(0);
+ private boolean add;
+
+ @Override
+ protected void execute() {
+ service = get(IntentService.class);
+
+
+ DeviceId ingressDeviceId = deviceId(getDeviceId(ingressDeviceString));
+ PortNumber ingressPortNumber = portNumber(getPortNumber(ingressDeviceString));
+ ConnectPoint ingress = new ConnectPoint(ingressDeviceId, ingressPortNumber);
+
+ DeviceId egressDeviceId = deviceId(getDeviceId(egressDeviceString));
+ PortNumber egressPortNumber = portNumber(getPortNumber(egressDeviceString));
+ ConnectPoint egress = new ConnectPoint(egressDeviceId, egressPortNumber);
+
+ count = Integer.parseInt(numberOfIntents);
+ keyOffset = (keyOffsetStr != null) ? Integer.parseInt(keyOffsetStr) : 1;
+
+ service.addListener(this);
+
+ List<Intent> operations = generateIntents(ingress, egress);
+
+ add = true;
+ start = System.currentTimeMillis();
+ while (start + 10000 > System.currentTimeMillis()) {
+ submitIntents(operations);
+ }
+ delay(5000);
+ printResults();
+
+ add = false;
+ submitIntents(operations);
+
+ service.removeListener(this);
+ }
+
+ private List<Intent> generateIntents(ConnectPoint ingress, ConnectPoint egress) {
+ TrafficSelector.Builder selectorBldr = DefaultTrafficSelector.builder()
+ .matchEthType(Ethernet.TYPE_IPV4);
+ TrafficTreatment treatment = DefaultTrafficTreatment.emptyTreatment();
+
+ List<Intent> intents = Lists.newArrayList();
+ for (int i = 0; i < count; i++) {
+ TrafficSelector selector = selectorBldr
+ .matchEthSrc(MacAddress.valueOf(i + keyOffset))
+ .build();
+ intents.add(
+ PointToPointIntent.builder()
+ .appId(appId())
+ .key(Key.of(i + keyOffset, appId()))
+ .selector(selector)
+ .treatment(treatment)
+ .ingressPoint(ingress)
+ .egressPoint(egress)
+ .build());
+
+
+ }
+ return intents;
+ }
+
+ private void submitIntents(List<Intent> intents) {
+ for (Intent intent : intents) {
+ if (add) {
+ submitCounter++;
+ service.submit(intent);
+ } else {
+ service.withdraw(intent);
+ }
+ }
+ }
+
+ private void printResults() {
+ //long delta = end - start;
+ //String text = add ? "install" : "withdraw";
+ print("count: %s / %s", eventCounter, Long.valueOf(submitCounter));
+ //print("Time to %s %d intents: %d ms", text, count, delta);
+ }
+
+ /**
+ * Extracts the port number portion of the ConnectPoint.
+ *
+ * @param deviceString string representing the device/port
+ * @return port number as a string, empty string if the port is not found
+ */
+ private String getPortNumber(String deviceString) {
+ int slash = deviceString.indexOf('/');
+ if (slash <= 0) {
+ return "";
+ }
+ return deviceString.substring(slash + 1, deviceString.length());
+ }
+
+ /**
+ * Extracts the device ID portion of the ConnectPoint.
+ *
+ * @param deviceString string representing the device/port
+ * @return device ID string
+ */
+ private String getDeviceId(String deviceString) {
+ int slash = deviceString.indexOf('/');
+ if (slash <= 0) {
+ return "";
+ }
+ return deviceString.substring(0, slash);
+ }
+
+ private static final EnumSet<Type> IGNORE_EVENT
+ = EnumSet.of(Type.INSTALL_REQ, Type.WITHDRAW_REQ);
+ @Override
+ public synchronized void event(IntentEvent event) {
+ if (!appId().equals(event.subject().appId())) {
+ // not my event, ignore
+ return;
+ }
+ Type expected = add ? Type.INSTALLED : Type.WITHDRAWN;
+ if (event.type() == expected) {
+ eventCounter.getAndIncrement();
+ } else if (IGNORE_EVENT.contains(event.type())) {
+ log.info("Unexpected intent event: {}", event);
+ }
+ }
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/IntentKeyCompleter.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/IntentKeyCompleter.java
new file mode 100644
index 00000000..e3f647b4
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/IntentKeyCompleter.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2014-2015 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.cli.net;
+
+import org.apache.karaf.shell.console.Completer;
+import org.apache.karaf.shell.console.completer.StringsCompleter;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.net.intent.Intent;
+import org.onosproject.net.intent.IntentService;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.SortedSet;
+
+/**
+ * Intent Key completer.
+ */
+public class IntentKeyCompleter implements Completer {
+ @Override
+ public int complete(String buffer, int cursor, List<String> candidates) {
+ // Delegate string completer
+ StringsCompleter delegate = new StringsCompleter();
+
+ // Fetch our service and feed it's offerings to the string completer
+ IntentService service = AbstractShellCommand.get(IntentService.class);
+ Iterator<Intent> it = service.getIntents().iterator();
+ SortedSet<String> strings = delegate.getStrings();
+ while (it.hasNext()) {
+ strings.add(it.next().key().toString());
+ }
+
+ // Now let the completer do the work for figuring out what to offer.
+ return delegate.complete(buffer, cursor, candidates);
+ }
+
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/IntentPurgeCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/IntentPurgeCommand.java
new file mode 100644
index 00000000..61174e70
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/IntentPurgeCommand.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2015 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.cli.net;
+
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.net.intent.Intent;
+import org.onosproject.net.intent.IntentService;
+
+import static org.onosproject.net.intent.IntentState.WITHDRAWN;
+
+/**
+ * Purges all WITHDRAWN intents.
+ */
+@Command(scope = "onos", name = "purge-intents",
+ description = "Purges all WITHDRAWN intents")
+public class IntentPurgeCommand extends AbstractShellCommand {
+ @Override
+ protected void execute() {
+ IntentService intentService = get(IntentService.class);
+ for (Intent intent: intentService.getIntents()) {
+ if (intentService.getIntentState(intent.key()) == WITHDRAWN) {
+ intentService.purge(intent);
+ }
+ }
+ }
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/IntentPushTestCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/IntentPushTestCommand.java
new file mode 100644
index 00000000..15921fed
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/IntentPushTestCommand.java
@@ -0,0 +1,232 @@
+/*
+ * Copyright 2014-2015 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.cli.net;
+
+import java.util.EnumSet;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.commands.Option;
+import org.onlab.packet.Ethernet;
+import org.onlab.packet.MacAddress;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.flow.DefaultTrafficSelector;
+import org.onosproject.net.flow.DefaultTrafficTreatment;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.intent.Intent;
+import org.onosproject.net.intent.IntentEvent;
+import org.onosproject.net.intent.IntentEvent.Type;
+import org.onosproject.net.intent.IntentListener;
+import org.onosproject.net.intent.IntentService;
+import org.onosproject.net.intent.Key;
+import org.onosproject.net.intent.PointToPointIntent;
+
+import com.google.common.collect.Lists;
+
+import static org.onosproject.net.DeviceId.deviceId;
+import static org.onosproject.net.PortNumber.portNumber;
+
+/**
+ * Installs bulk point-to-point connectivity intents between given ingress/egress devices.
+ */
+@Command(scope = "onos", name = "push-test-intents",
+ description = "Installs random intents to test throughput")
+public class IntentPushTestCommand extends AbstractShellCommand
+ implements IntentListener {
+
+ @Argument(index = 0, name = "ingressDevice",
+ description = "Ingress Device/Port Description",
+ required = true, multiValued = false)
+ String ingressDeviceString = null;
+
+ @Argument(index = 1, name = "egressDevice",
+ description = "Egress Device/Port Description",
+ required = true, multiValued = false)
+ String egressDeviceString = null;
+
+ @Argument(index = 2, name = "numberOfIntents",
+ description = "Number of intents to install/withdraw",
+ required = true, multiValued = false)
+ String numberOfIntents = null;
+
+ @Argument(index = 3, name = "keyOffset",
+ description = "Starting point for first key (default: 1)",
+ required = false, multiValued = false)
+ String keyOffsetStr = null;
+
+ @Option(name = "-i", aliases = "--install",
+ description = "Install intents",
+ required = false, multiValued = false)
+ private boolean installOnly = false;
+
+ @Option(name = "-w", aliases = "--withdraw",
+ description = "Withdraw intents",
+ required = false, multiValued = false)
+ private boolean withdrawOnly = false;
+
+ private IntentService service;
+ private CountDownLatch latch;
+ private volatile long start, end;
+ private int count;
+ private int keyOffset;
+ private boolean add;
+
+ @Override
+ protected void execute() {
+ service = get(IntentService.class);
+
+
+ DeviceId ingressDeviceId = deviceId(getDeviceId(ingressDeviceString));
+ PortNumber ingressPortNumber = portNumber(getPortNumber(ingressDeviceString));
+ ConnectPoint ingress = new ConnectPoint(ingressDeviceId, ingressPortNumber);
+
+ DeviceId egressDeviceId = deviceId(getDeviceId(egressDeviceString));
+ PortNumber egressPortNumber = portNumber(getPortNumber(egressDeviceString));
+ ConnectPoint egress = new ConnectPoint(egressDeviceId, egressPortNumber);
+
+ count = Integer.parseInt(numberOfIntents);
+ keyOffset = (keyOffsetStr != null) ? Integer.parseInt(keyOffsetStr) : 1;
+
+ service.addListener(this);
+
+ List<Intent> operations = generateIntents(ingress, egress);
+
+ boolean both = !(installOnly ^ withdrawOnly);
+
+ if (installOnly || both) {
+ add = true;
+ submitIntents(operations);
+ }
+
+ if (withdrawOnly || both) {
+ add = false;
+ submitIntents(operations);
+ }
+
+ service.removeListener(this);
+ }
+
+ private List<Intent> generateIntents(ConnectPoint ingress, ConnectPoint egress) {
+ TrafficSelector.Builder selectorBldr = DefaultTrafficSelector.builder()
+ .matchEthType(Ethernet.TYPE_IPV4);
+ TrafficTreatment treatment = DefaultTrafficTreatment.emptyTreatment();
+
+ List<Intent> intents = Lists.newArrayList();
+ for (int i = 0; i < count; i++) {
+ TrafficSelector selector = selectorBldr
+ .matchEthSrc(MacAddress.valueOf(i + keyOffset))
+ .build();
+ intents.add(PointToPointIntent.builder()
+ .appId(appId())
+ .key(Key.of(i + keyOffset, appId()))
+ .selector(selector)
+ .treatment(treatment)
+ .ingressPoint(ingress)
+ .egressPoint(egress)
+ .build());
+
+
+ }
+ return intents;
+ }
+
+ private void submitIntents(List<Intent> intents) {
+ latch = new CountDownLatch(count);
+ start = System.currentTimeMillis();
+ for (Intent intent : intents) {
+ if (add) {
+ service.submit(intent);
+ } else {
+ service.withdraw(intent);
+ }
+ }
+
+ try {
+ if (latch.await(500 + count * 30, TimeUnit.MILLISECONDS)) {
+ printResults(count);
+ } else {
+ print("Failure: %d intents not installed", latch.getCount());
+ }
+ } catch (InterruptedException e) {
+ print(e.toString());
+ }
+ }
+
+ private void printResults(int count) {
+ long delta = end - start;
+ String text = add ? "install" : "withdraw";
+ print("Time to %s %d intents: %d ms", text, count, delta);
+ }
+
+ /**
+ * Extracts the port number portion of the ConnectPoint.
+ *
+ * @param deviceString string representing the device/port
+ * @return port number as a string, empty string if the port is not found
+ */
+ private String getPortNumber(String deviceString) {
+ int slash = deviceString.indexOf('/');
+ if (slash <= 0) {
+ return "";
+ }
+ return deviceString.substring(slash + 1, deviceString.length());
+ }
+
+ /**
+ * Extracts the device ID portion of the ConnectPoint.
+ *
+ * @param deviceString string representing the device/port
+ * @return device ID string
+ */
+ private String getDeviceId(String deviceString) {
+ int slash = deviceString.indexOf('/');
+ if (slash <= 0) {
+ return "";
+ }
+ return deviceString.substring(0, slash);
+ }
+
+ private static final EnumSet<IntentEvent.Type> IGNORE_EVENT
+ = EnumSet.of(Type.INSTALL_REQ, Type.WITHDRAW_REQ);
+ @Override
+ public synchronized void event(IntentEvent event) {
+ if (!appId().equals(event.subject().appId())) {
+ // not my event, ignore
+ return;
+ }
+ Type expected = add ? Type.INSTALLED : Type.WITHDRAWN;
+ if (event.type() == expected) {
+ end = Math.max(end, event.time());
+ if (latch != null) {
+ if (latch.getCount() == 0) {
+ log.warn("Latch was already 0 before counting down?");
+ }
+ latch.countDown();
+ } else {
+ log.warn("install event latch is null");
+ }
+ } else if (IGNORE_EVENT.contains(event.type())) {
+ log.debug("Unexpected intent event: {}", event);
+ }
+ }
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/IntentRemoveCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/IntentRemoveCommand.java
new file mode 100644
index 00000000..492b3a27
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/IntentRemoveCommand.java
@@ -0,0 +1,170 @@
+/*
+ * Copyright 2014-2015 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.cli.net;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.commands.Option;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.CoreService;
+import org.onosproject.net.intent.Intent;
+import org.onosproject.net.intent.IntentState;
+import org.onosproject.net.intent.IntentService;
+import org.onosproject.net.intent.IntentListener;
+import org.onosproject.net.intent.IntentEvent;
+import org.onosproject.net.intent.Key;
+
+import java.math.BigInteger;
+import java.util.EnumSet;
+import java.util.Objects;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import static com.google.common.base.Strings.isNullOrEmpty;
+import static org.onosproject.net.intent.IntentState.FAILED;
+import static org.onosproject.net.intent.IntentState.WITHDRAWN;
+
+/**
+ * Removes an intent.
+ */
+@Command(scope = "onos", name = "remove-intent",
+ description = "Removes the specified intent")
+public class IntentRemoveCommand extends AbstractShellCommand {
+
+ @Argument(index = 0, name = "app",
+ description = "Application ID",
+ required = false, multiValued = false)
+ String applicationIdString = null;
+
+ @Argument(index = 1, name = "key",
+ description = "Intent Key",
+ required = false, multiValued = false)
+ String keyString = null;
+
+ @Option(name = "-p", aliases = "--purge",
+ description = "Purge the intent from the store after removal",
+ required = false, multiValued = false)
+ private boolean purgeAfterRemove = false;
+
+ @Option(name = "-s", aliases = "--sync",
+ description = "Waits for the removal before returning",
+ required = false, multiValued = false)
+ private boolean sync = false;
+
+ private static final EnumSet<IntentState> CAN_PURGE = EnumSet.of(WITHDRAWN, FAILED);
+
+ @Override
+ protected void execute() {
+ IntentService intentService = get(IntentService.class);
+ CoreService coreService = get(CoreService.class);
+
+ if (purgeAfterRemove || sync) {
+ print("Using \"sync\" to remove/purge intents - this may take a while...");
+ print("Check \"summary\" to see remove/purge progress.");
+ }
+
+ ApplicationId appId = appId();
+ if (!isNullOrEmpty(applicationIdString)) {
+ appId = coreService.getAppId(applicationIdString);
+ if (appId == null) {
+ print("Cannot find application Id %s", applicationIdString);
+ return;
+ }
+ }
+
+ if (isNullOrEmpty(keyString)) {
+ for (Intent intent : intentService.getIntents()) {
+ if (intent.appId().equals(appId)) {
+ removeIntent(intentService, intent);
+ }
+ }
+
+ } else {
+ final Key key;
+ if (keyString.startsWith("0x")) {
+ // The intent uses a LongKey
+ keyString = keyString.replaceFirst("0x", "");
+ key = Key.of(new BigInteger(keyString, 16).longValue(), appId);
+ } else {
+ // The intent uses a StringKey
+ key = Key.of(keyString, appId);
+ }
+
+ Intent intent = intentService.getIntent(key);
+ if (intent != null) {
+ removeIntent(intentService, intent);
+ }
+ }
+ }
+
+ private void removeIntent(IntentService intentService, Intent intent) {
+ IntentListener listener = null;
+ Key key = intent.key();
+ final CountDownLatch withdrawLatch, purgeLatch;
+ if (purgeAfterRemove || sync) {
+ // set up latch and listener to track uninstall progress
+ withdrawLatch = new CountDownLatch(1);
+ purgeLatch = purgeAfterRemove ? new CountDownLatch(1) : null;
+ listener = (IntentEvent event) -> {
+ if (Objects.equals(event.subject().key(), key)) {
+ if (event.type() == IntentEvent.Type.WITHDRAWN ||
+ event.type() == IntentEvent.Type.FAILED) {
+ withdrawLatch.countDown();
+ } else if (purgeAfterRemove &&
+ event.type() == IntentEvent.Type.PURGED) {
+ purgeLatch.countDown();
+ }
+ }
+ };
+ intentService.addListener(listener);
+ } else {
+ purgeLatch = null;
+ withdrawLatch = null;
+ }
+
+ // request the withdraw
+ intentService.withdraw(intent);
+
+ if (purgeAfterRemove || sync) {
+ try { // wait for withdraw event
+ withdrawLatch.await(5, TimeUnit.SECONDS);
+ } catch (InterruptedException e) {
+ print("Timed out waiting for intent {} withdraw", key);
+ }
+ if (purgeAfterRemove && CAN_PURGE.contains(intentService.getIntentState(key))) {
+ intentService.purge(intent);
+ if (sync) { // wait for purge event
+ /* TODO
+ Technically, the event comes before map.remove() is called.
+ If we depend on sync and purge working together, we will
+ need to address this.
+ */
+ try {
+ purgeLatch.await(5, TimeUnit.SECONDS);
+ } catch (InterruptedException e) {
+ print("Timed out waiting for intent {} purge", key);
+ }
+ }
+ }
+ }
+
+ if (listener != null) {
+ // clean up the listener
+ intentService.removeListener(listener);
+ }
+ }
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/IntentsListCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/IntentsListCommand.java
new file mode 100644
index 00000000..55b9ec9c
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/IntentsListCommand.java
@@ -0,0 +1,398 @@
+/*
+ * Copyright 2014-2015 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.cli.net;
+
+import java.util.List;
+
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.commands.Option;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.net.intent.ConnectivityIntent;
+import org.onosproject.net.intent.HostToHostIntent;
+import org.onosproject.net.intent.Intent;
+import org.onosproject.net.intent.IntentService;
+import org.onosproject.net.intent.IntentState;
+import org.onosproject.net.intent.LinkCollectionIntent;
+import org.onosproject.net.intent.MultiPointToSinglePointIntent;
+import org.onosproject.net.intent.PathIntent;
+import org.onosproject.net.intent.PointToPointIntent;
+import org.onosproject.net.intent.SinglePointToMultiPointIntent;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+/**
+ * Lists the inventory of intents and their states.
+ */
+@Command(scope = "onos", name = "intents",
+ description = "Lists the inventory of intents and their states")
+public class IntentsListCommand extends AbstractShellCommand {
+
+ @Option(name = "-i", aliases = "--installable",
+ description = "Output Installable Intents",
+ required = false, multiValued = false)
+ private boolean showInstallable = false;
+
+ @Option(name = "-s", aliases = "--summary",
+ description = "Intents summary",
+ required = false, multiValued = false)
+ private boolean intentsSummary = false;
+
+ @Option(name = "-p", aliases = "--pending",
+ description = "Show inforamtion about pending intents",
+ required = false, multiValued = false)
+ private boolean pending = false;
+
+ @Override
+ protected void execute() {
+ IntentService service = get(IntentService.class);
+
+ if (intentsSummary) {
+ IntentSummaries intentSummaries = new IntentSummaries();
+ intentSummaries.collectIntentSummary(service,
+ service.getIntents());
+ if (outputJson()) {
+ print("%s", intentSummaries.json());
+ } else {
+ intentSummaries.printSummary();
+ }
+ return;
+ } else if (pending) {
+ if (outputJson()) {
+ print("%s", json(service, service.getPending()));
+ } else {
+ service.getPending().forEach(intent ->
+ print("id=%s, key=%s, type=%s, appId=%s",
+ intent.id(), intent.key(),
+ intent.getClass().getSimpleName(),
+ intent.appId().name())
+ );
+ }
+ return;
+ }
+
+ if (outputJson()) {
+ print("%s", json(service, service.getIntents()));
+ } else {
+ for (Intent intent : service.getIntents()) {
+ IntentState state = service.getIntentState(intent.key());
+ if (state != null) {
+ print("id=%s, state=%s, key=%s, type=%s, appId=%s",
+ intent.id(), state, intent.key(),
+ intent.getClass().getSimpleName(),
+ intent.appId().name());
+ printDetails(service, intent);
+ }
+ }
+ }
+ }
+
+ /**
+ * Internal local class to keep track of all intent summaries.
+ */
+ private class IntentSummaries {
+ private IntentSummary summaryAll;
+ private IntentSummary summaryConnectivity;
+ private IntentSummary summaryHostToHost;
+ private IntentSummary summaryPointToPoint;
+ private IntentSummary summaryMultiPointToSinglePoint;
+ private IntentSummary summarySinglePointToMultiPoint;
+ private IntentSummary summaryPath;
+ private IntentSummary summaryLinkCollection;
+ private IntentSummary summaryUnknownType;
+
+ /**
+ * Initializes the internal state.
+ */
+ private void init() {
+ summaryAll = new IntentSummary("All");
+ summaryConnectivity = new IntentSummary("Connectivity");
+ summaryHostToHost = new IntentSummary("HostToHost");
+ summaryPointToPoint = new IntentSummary("PointToPoint");
+ summaryMultiPointToSinglePoint =
+ new IntentSummary("MultiPointToSinglePoint");
+ summarySinglePointToMultiPoint =
+ new IntentSummary("SinglePointToMultiPoint");
+ summaryPath = new IntentSummary("Path");
+ summaryLinkCollection = new IntentSummary("LinkCollection");
+ summaryUnknownType = new IntentSummary("UnknownType");
+ }
+
+ /**
+ * Collects summary of all intents.
+ *
+ * @param service the Intent Service to use
+ * @param intents the intents
+ */
+ private void collectIntentSummary(IntentService service,
+ Iterable<Intent> intents) {
+ init();
+
+ // Collect the summary for each intent type intents
+ for (Intent intent : intents) {
+ IntentState intentState = service.getIntentState(intent.key());
+ if (intentState == null) {
+ continue;
+ }
+
+ // Update the summary for all Intents
+ summaryAll.update(intentState);
+
+ if (intent instanceof ConnectivityIntent) {
+ summaryConnectivity.update(intentState);
+ // NOTE: ConnectivityIntent is a base type Intent
+ // continue;
+ }
+ if (intent instanceof HostToHostIntent) {
+ summaryHostToHost.update(intentState);
+ continue;
+ }
+ if (intent instanceof PointToPointIntent) {
+ summaryPointToPoint.update(intentState);
+ continue;
+ }
+ if (intent instanceof MultiPointToSinglePointIntent) {
+ summaryMultiPointToSinglePoint.update(intentState);
+ continue;
+ }
+ if (intent instanceof SinglePointToMultiPointIntent) {
+ summarySinglePointToMultiPoint.update(intentState);
+ continue;
+ }
+ if (intent instanceof PathIntent) {
+ summaryPath.update(intentState);
+ continue;
+ }
+ if (intent instanceof LinkCollectionIntent) {
+ summaryLinkCollection.update(intentState);
+ continue;
+ }
+
+ summaryUnknownType.update(intentState);
+ }
+ }
+
+ /**
+ * Gets JSON representation of all Intents summary.
+ *
+ * @return JSON representation of all Intents summary
+ */
+ ObjectNode json() {
+ ObjectMapper mapper = new ObjectMapper();
+ ObjectNode result = mapper.createObjectNode();
+ result.set("connectivity", summaryConnectivity.json(mapper));
+ result.set("hostToHost", summaryHostToHost.json(mapper));
+ result.set("pointToPoint", summaryPointToPoint.json(mapper));
+ result.set("multiPointToSinglePoint",
+ summaryMultiPointToSinglePoint.json(mapper));
+ result.set("singlePointToMultiPoint",
+ summarySinglePointToMultiPoint.json(mapper));
+ result.set("path", summaryPath.json(mapper));
+ result.set("linkCollection", summaryLinkCollection.json(mapper));
+ result.set("unknownType", summaryUnknownType.json(mapper));
+ result.set("all", summaryAll.json(mapper));
+ return result;
+ }
+
+ /**
+ * Prints summary of the intents.
+ */
+ private void printSummary() {
+ summaryConnectivity.printState();
+ summaryHostToHost.printState();
+ summaryPointToPoint.printState();
+ summaryMultiPointToSinglePoint.printState();
+ summarySinglePointToMultiPoint.printState();
+ summaryPath.printState();
+ summaryLinkCollection.printState();
+ summaryUnknownType.printState();
+ summaryAll.printState();
+ }
+
+ /**
+ * Internal local class to keep track of a single type Intent summary.
+ */
+ private class IntentSummary {
+ private final String intentType;
+ private int total = 0;
+ private int installReq = 0;
+ private int compiling = 0;
+ private int installing = 0;
+ private int installed = 0;
+ private int recompiling = 0;
+ private int withdrawReq = 0;
+ private int withdrawing = 0;
+ private int withdrawn = 0;
+ private int failed = 0;
+ private int unknownState = 0;
+
+ private static final String FORMAT_SUMMARY_LINE1 =
+ "%-23s total= %7d installed= %7d";
+ private static final String FORMAT_SUMMARY_LINE2 =
+ "%-23s withdrawn= %7d failed= %7d";
+ private static final String FORMAT_SUMMARY_LINE3 =
+ "%-23s installReq= %7d compiling= %7d";
+ private static final String FORMAT_SUMMARY_LINE4 =
+ "%-23s installing= %7d recompiling= %7d";
+ private static final String FORMAT_SUMMARY_LINE5 =
+ "%-23s withdrawReq= %7d withdrawing= %7d";
+ private static final String FORMAT_SUMMARY_LINE6 =
+ "%-23s unknownState= %7d";
+
+ /**
+ * Constructor.
+ *
+ * @param intentType the scring describing the Intent type
+ */
+ IntentSummary(String intentType) {
+ this.intentType = intentType;
+ }
+
+ /**
+ * Updates the Intent Summary.
+ *
+ * @param intentState the state of the Intent
+ */
+ void update(IntentState intentState) {
+ total++;
+ switch (intentState) {
+ case INSTALL_REQ:
+ installReq++;
+ break;
+ case COMPILING:
+ compiling++;
+ break;
+ case INSTALLING:
+ installing++;
+ break;
+ case INSTALLED:
+ installed++;
+ break;
+ case RECOMPILING:
+ recompiling++;
+ break;
+ case WITHDRAW_REQ:
+ withdrawReq++;
+ break;
+ case WITHDRAWING:
+ withdrawing++;
+ break;
+ case WITHDRAWN:
+ withdrawn++;
+ break;
+ case FAILED:
+ failed++;
+ break;
+ default:
+ unknownState++;
+ break;
+ }
+ }
+
+ /**
+ * Prints the Intent Summary.
+ */
+ void printState() {
+ print(FORMAT_SUMMARY_LINE1, intentType, total, installed);
+ print(FORMAT_SUMMARY_LINE2, intentType, withdrawn, failed);
+ print(FORMAT_SUMMARY_LINE3, intentType, installReq, compiling);
+ print(FORMAT_SUMMARY_LINE4, intentType, installing, recompiling);
+ print(FORMAT_SUMMARY_LINE5, intentType, withdrawReq, withdrawing);
+ if (unknownState != 0) {
+ print(FORMAT_SUMMARY_LINE6, intentType, unknownState);
+ }
+ }
+
+ /**
+ * Gets the JSON representation of the Intent Summary.
+ *
+ * @return the JSON representation of the Intent Summary
+ */
+ JsonNode json(ObjectMapper mapper) {
+ ObjectNode result = mapper.createObjectNode()
+ .put("total", total)
+ .put("installed", installed)
+ .put("failed", failed)
+ .put("installReq", installReq)
+ .put("compiling", compiling)
+ .put("installing", installing)
+ .put("recompiling", recompiling)
+ .put("withdrawReq", withdrawReq)
+ .put("withdrawing", withdrawing)
+ .put("withdrawn", withdrawn)
+ .put("unknownState", unknownState);
+
+ return result;
+ }
+ }
+ }
+
+ private void printDetails(IntentService service, Intent intent) {
+ if (!intent.resources().isEmpty()) {
+ print(" resources=%s", intent.resources());
+ }
+ if (intent instanceof ConnectivityIntent) {
+ ConnectivityIntent ci = (ConnectivityIntent) intent;
+ if (!ci.selector().criteria().isEmpty()) {
+ print(" selector=%s", ci.selector().criteria());
+ }
+ if (!ci.treatment().allInstructions().isEmpty()) {
+ print(" treatment=%s", ci.treatment().allInstructions());
+ }
+ if (ci.constraints() != null && !ci.constraints().isEmpty()) {
+ print(" constraints=%s", ci.constraints());
+ }
+ }
+
+ if (intent instanceof HostToHostIntent) {
+ HostToHostIntent pi = (HostToHostIntent) intent;
+ print(" host1=%s, host2=%s", pi.one(), pi.two());
+ } else if (intent instanceof PointToPointIntent) {
+ PointToPointIntent pi = (PointToPointIntent) intent;
+ print(" ingress=%s, egress=%s", pi.ingressPoint(), pi.egressPoint());
+ } else if (intent instanceof MultiPointToSinglePointIntent) {
+ MultiPointToSinglePointIntent pi = (MultiPointToSinglePointIntent) intent;
+ print(" ingress=%s, egress=%s", pi.ingressPoints(), pi.egressPoint());
+ } else if (intent instanceof SinglePointToMultiPointIntent) {
+ SinglePointToMultiPointIntent pi = (SinglePointToMultiPointIntent) intent;
+ print(" ingress=%s, egress=%s", pi.ingressPoint(), pi.egressPoints());
+ } else if (intent instanceof PathIntent) {
+ PathIntent pi = (PathIntent) intent;
+ print(" path=%s, cost=%d", pi.path().links(), pi.path().cost());
+ } else if (intent instanceof LinkCollectionIntent) {
+ LinkCollectionIntent li = (LinkCollectionIntent) intent;
+ print(" links=%s", li.links());
+ print(" egress=%s", li.egressPoints());
+ }
+
+ List<Intent> installable = service.getInstallableIntents(intent.key());
+ if (showInstallable && installable != null && !installable.isEmpty()) {
+ print(" installable=%s", installable);
+ }
+ }
+
+ // Produces JSON array of the specified intents.
+ private JsonNode json(IntentService service, Iterable<Intent> intents) {
+ ObjectMapper mapper = new ObjectMapper();
+ ArrayNode result = mapper.createArrayNode();
+
+ intents.forEach(intent -> result.add(jsonForEntity(intent, Intent.class)));
+ return result;
+ }
+
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/InterfacesListCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/InterfacesListCommand.java
new file mode 100644
index 00000000..aa93eb94
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/InterfacesListCommand.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2015 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.cli.net;
+
+import com.google.common.collect.Lists;
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.cli.Comparators;
+import org.onosproject.incubator.net.intf.Interface;
+import org.onosproject.incubator.net.intf.InterfaceService;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Lists all configured interfaces.
+ */
+@Command(scope = "onos", name = "interfaces",
+ description = "Lists all configured interfaces.")
+public class InterfacesListCommand extends AbstractShellCommand {
+
+ private static final String FORMAT =
+ "port=%s/%s, ips=%s, mac=%s, vlan=%s";
+
+ @Override
+ protected void execute() {
+ InterfaceService interfaceService = get(InterfaceService.class);
+
+ List<Interface> interfaces = Lists.newArrayList(interfaceService.getInterfaces());
+
+ Collections.sort(interfaces, Comparators.INTERFACES_COMPARATOR);
+
+ for (Interface intf : interfaces) {
+ print(FORMAT, intf.connectPoint().deviceId(), intf.connectPoint().port(),
+ intf.ipAddresses(), intf.mac(), intf.vlan());
+ }
+ }
+
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/IpProtocol.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/IpProtocol.java
new file mode 100644
index 00000000..5e0d865e
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/IpProtocol.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2014 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.cli.net;
+
+import org.onlab.packet.IPv4;
+import org.onlab.packet.IPv6;
+
+/**
+ * Known protocol values for IP protocol field that can be supplied to the CLI.
+ */
+public enum IpProtocol {
+ /** ICMP. **/
+ ICMP(IPv4.PROTOCOL_ICMP),
+ /** TCP. **/
+ TCP(IPv4.PROTOCOL_TCP),
+ /** UDP. **/
+ UDP(IPv4.PROTOCOL_UDP),
+ /** ICMP6. **/
+ ICMP6(IPv6.PROTOCOL_ICMP6);
+
+ private short value;
+
+ /**
+ * Constructs an IpProtocol with the given value.
+ *
+ * @param value value to use when this IpProtocol is seen
+ */
+ private IpProtocol(short value) {
+ this.value = value;
+ }
+
+ /**
+ * Gets the value to use for this IpProtocol.
+ *
+ * @return short value to use for this IpProtocol
+ */
+ public short value() {
+ return this.value;
+ }
+
+ /**
+ * Parse a string input that could contain an IpProtocol value. The value
+ * may appear in the string either as a known protocol name (one of the
+ * values of this enum), or a numeric protocol value.
+ *
+ * @param input the input string to parse
+ * @return the numeric value of the parsed IP protocol
+ * @throws IllegalArgumentException if the input string does not contain a
+ * value that can be parsed into an IP protocol
+ */
+ public static short parseFromString(String input) {
+ try {
+ return valueOf(input).value();
+ } catch (IllegalArgumentException e) {
+ // The input is not a known IP protocol name, let's see if it's an IP
+ // protocol value (byte). We parse with Short to handle unsigned values
+ // correctly.
+ try {
+ return Short.parseShort(input);
+ } catch (NumberFormatException e1) {
+ throw new IllegalArgumentException(
+ "IpProtocol value must be either a string protocol name"
+ + " or an 8-bit protocol value");
+ }
+ }
+ }
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/IpProtocolCompleter.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/IpProtocolCompleter.java
new file mode 100644
index 00000000..ec02b1da
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/IpProtocolCompleter.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2014 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.cli.net;
+
+import java.util.List;
+import java.util.SortedSet;
+
+import org.apache.karaf.shell.console.Completer;
+import org.apache.karaf.shell.console.completer.StringsCompleter;
+
+/**
+ * IP protocol completer.
+ */
+public class IpProtocolCompleter implements Completer {
+ @Override
+ public int complete(String buffer, int cursor, List<String> candidates) {
+ // Delegate string completer
+ StringsCompleter delegate = new StringsCompleter();
+ SortedSet<String> strings = delegate.getStrings();
+
+ for (IpProtocol ip : IpProtocol.values()) {
+ strings.add(ip.toString());
+ }
+
+ // Now let the completer do the work for figuring out what to offer.
+ return delegate.complete(buffer, cursor, candidates);
+ }
+
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/LabelApplyCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/LabelApplyCommand.java
new file mode 100644
index 00000000..c88d41c4
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/LabelApplyCommand.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2014-2015 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.cli.net;
+
+import java.util.Collection;
+import java.util.Iterator;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.net.DeviceId;
+import org.onosproject.incubator.net.resource.label.DefaultLabelResource;
+import org.onosproject.incubator.net.resource.label.LabelResource;
+import org.onosproject.incubator.net.resource.label.LabelResourceService;
+
+@Command(scope = "onos", name = "label-apply",
+ description = "Apply label resource from device pool by specific device id")
+public class LabelApplyCommand extends AbstractShellCommand {
+ @Argument(index = 0, name = "deviceId",
+ description = "Device identity",
+ required = true, multiValued = false)
+ String deviceId = null;
+ @Argument(index = 1, name = "applyNum",
+ description = "Applying number means how many labels applications want to use.",
+ required = true, multiValued = false)
+ String applyNum = null;
+
+ private static final String FMT = "deviceid=%s, labelresourceid=%s";
+
+ @Override
+ protected void execute() {
+ LabelResourceService lrs = get(LabelResourceService.class);
+ Collection<LabelResource> result = lrs.applyFromDevicePool(DeviceId
+ .deviceId(deviceId), Long.parseLong(applyNum));
+ if (result.size() > 0) {
+ for (Iterator<LabelResource> iterator = result.iterator(); iterator
+ .hasNext();) {
+ DefaultLabelResource defaultLabelResource = (DefaultLabelResource) iterator
+ .next();
+ print(FMT, defaultLabelResource.deviceId().toString(),
+ defaultLabelResource.labelResourceId().toString());
+ }
+ }
+ }
+
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/LabelPoolCreateCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/LabelPoolCreateCommand.java
new file mode 100644
index 00000000..78a6d196
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/LabelPoolCreateCommand.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2014-2015 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.cli.net;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.net.DeviceId;
+import org.onosproject.incubator.net.resource.label.LabelResourceAdminService;
+import org.onosproject.incubator.net.resource.label.LabelResourceId;
+
+/**
+ * create label resource pool by specific device id.
+ */
+@Command(scope = "onos", name = "label-pool-create",
+ description = "Creates label resource pool by a specific device id")
+public class LabelPoolCreateCommand extends AbstractShellCommand {
+ @Argument(index = 0, name = "deviceId", description = "Device identity", required = true, multiValued = false)
+ String deviceId = null;
+ @Argument(index = 1, name = "beginLabel",
+ description = "The first label of global label resource pool.", required = true, multiValued = false)
+ String beginLabel = null;
+ @Argument(index = 2, name = "endLabel",
+ description = "The last label of global label resource pool.", required = true, multiValued = false)
+ String endLabel = null;
+
+ @Override
+ protected void execute() {
+ LabelResourceAdminService lrs = get(LabelResourceAdminService.class);
+ lrs.createDevicePool(DeviceId.deviceId(deviceId), LabelResourceId
+ .labelResourceId(Long.parseLong(beginLabel)), LabelResourceId
+ .labelResourceId(Long.parseLong(endLabel)));
+ }
+
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/LabelPoolDestroyCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/LabelPoolDestroyCommand.java
new file mode 100644
index 00000000..6445de63
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/LabelPoolDestroyCommand.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2014-2015 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.cli.net;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.net.DeviceId;
+import org.onosproject.incubator.net.resource.label.LabelResourceAdminService;
+
+@Command(scope = "onos", name = "label-pool-destroy",
+ description = "Destroys label resource pool by a specific device id")
+public class LabelPoolDestroyCommand extends AbstractShellCommand {
+ @Argument(index = 0, name = "deviceId", description = "Device identity", required = true, multiValued = false)
+ String deviceId = null;
+
+ @Override
+ protected void execute() {
+ LabelResourceAdminService lrs = get(LabelResourceAdminService.class);
+ lrs.destroyDevicePool(DeviceId.deviceId(deviceId));
+ }
+
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/LabelReleaseCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/LabelReleaseCommand.java
new file mode 100644
index 00000000..cc52204c
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/LabelReleaseCommand.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2014-2015 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.cli.net;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.net.DeviceId;
+import org.onosproject.incubator.net.resource.label.DefaultLabelResource;
+import org.onosproject.incubator.net.resource.label.LabelResource;
+import org.onosproject.incubator.net.resource.label.LabelResourceId;
+import org.onosproject.incubator.net.resource.label.LabelResourceService;
+
+import com.google.common.collect.ArrayListMultimap;
+import com.google.common.collect.Multimap;
+
+@Command(scope = "onos", name = "label-release",
+description = "Releases label ids to label resource pool by a specific device id")
+public class LabelReleaseCommand extends AbstractShellCommand {
+ @Argument(index = 0, name = "deviceId",
+ description = "Device identity",
+ required = true, multiValued = false)
+ String deviceId = null;
+ @Argument(index = 1, name = "releaseLabelIds",
+ description = "Represents for the label ids that are released. They are splited by dot symbol",
+ required = true, multiValued = false)
+ String releaseLabelIds = null;
+
+ @Override
+ protected void execute() {
+ LabelResourceService lrs = get(LabelResourceService.class);
+ Multimap<DeviceId, LabelResource> map = ArrayListMultimap
+ .create();
+ String[] labelIds = releaseLabelIds.split(",");
+ DefaultLabelResource resource = null;
+ for (int i = 0; i < labelIds.length; i++) {
+ resource = new DefaultLabelResource(
+ DeviceId.deviceId(deviceId),
+ LabelResourceId.labelResourceId(Long
+ .parseLong(labelIds[i])));
+ map.put(DeviceId.deviceId(deviceId), resource);
+ }
+ lrs.releaseToDevicePool(map);
+ }
+
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/LabelResourceCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/LabelResourceCommand.java
new file mode 100644
index 00000000..fe263c68
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/LabelResourceCommand.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2014-2015 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.cli.net;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.net.DeviceId;
+import org.onosproject.incubator.net.resource.label.LabelResourcePool;
+import org.onosproject.incubator.net.resource.label.LabelResourceService;
+
+@Command(scope = "onos", name = "label-pool",
+ description = "Gets label resource pool information by a specific device id")
+public class LabelResourceCommand extends AbstractShellCommand {
+ @Argument(index = 0, name = "deviceId",
+ description = "Device identity", required = true, multiValued = false)
+ String deviceId = null;
+ private static final String FMT = "deviceid=%s, beginLabel=%s,"
+ + "endLabel=%s, totalNum=%s, usedNum=%s, currentUsedMaxLabelId=%s,"
+ + "releaseLabelIds=%s";
+
+ @Override
+ protected void execute() {
+ LabelResourceService lrs = get(LabelResourceService.class);
+ LabelResourcePool pool = lrs.getDeviceLabelResourcePool(DeviceId
+ .deviceId(deviceId));
+ if (pool != null) {
+ print(FMT, pool.deviceId().toString(), pool.beginLabel(),
+ pool.endLabel(), pool.totalNum(), pool.usedNum(),
+ pool.currentUsedMaxLabelId(), pool.releaseLabelId()
+ .toString());
+ } else {
+ print(FMT, deviceId, null, null, null, null, null, null);
+ }
+ }
+
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/LeaderCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/LeaderCommand.java
new file mode 100644
index 00000000..da4ab13a
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/LeaderCommand.java
@@ -0,0 +1,194 @@
+/*
+ * Copyright 2014-2015 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.cli.net;
+
+import java.util.Comparator;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Pattern;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.commands.Option;
+import org.onlab.util.Tools;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.cluster.Leadership;
+import org.onosproject.cluster.LeadershipService;
+import org.onosproject.cluster.NodeId;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+
+/**
+ * Prints the leader for every topic.
+ */
+@Command(scope = "onos", name = "leaders",
+ description = "Finds the leader for particular topic.")
+public class LeaderCommand extends AbstractShellCommand {
+
+ private static final String FMT = "%-30s | %-15s | %-6s | %-10s |";
+ private static final String FMT_C = "%-30s | %-15s | %-19s |";
+ private boolean allTopics;
+ private Pattern pattern;
+
+ @Argument(index = 0, name = "topic", description = "A leadership topic. Can be a regex",
+ required = false, multiValued = false)
+ String topicPattern = null;
+
+ @Option(name = "-c", aliases = "--candidates",
+ description = "List candidate Nodes for each topic's leadership race",
+ required = false, multiValued = false)
+ private boolean showCandidates = false;
+
+ /**
+ * Compares leaders, sorting by toString() output.
+ */
+ private Comparator<Leadership> leadershipComparator =
+ (e1, e2) -> {
+ if (e1.leader() == null && e2.leader() == null) {
+ return 0;
+ }
+ if (e1.leader() == null) {
+ return 1;
+ }
+ if (e2.leader() == null) {
+ return -1;
+ }
+ return e1.leader().toString().compareTo(e2.leader().toString());
+ };
+
+ /**
+ * Displays text representing the leaders.
+ *
+ * @param leaderBoard map of leaders
+ */
+ private void displayLeaders(Map<String, Leadership> leaderBoard) {
+ print("------------------------------------------------------------------------");
+ print(FMT, "Topic", "Leader", "Epoch", "Elected");
+ print("------------------------------------------------------------------------");
+
+ leaderBoard.values()
+ .stream()
+ .filter(l -> allTopics || pattern.matcher(l.topic()).matches())
+ .sorted(leadershipComparator)
+ .forEach(l -> print(FMT,
+ l.topic(),
+ l.leader(),
+ l.epoch(),
+ Tools.timeAgo(l.electedTime())));
+ print("------------------------------------------------------------------------");
+ }
+
+ private void displayCandidates(Map<String, Leadership> leaderBoard,
+ Map<String, List<NodeId>> candidates) {
+ print("------------------------------------------------------------------------");
+ print(FMT_C, "Topic", "Leader", "Candidates");
+ print("------------------------------------------------------------------------");
+ candidates
+ .entrySet()
+ .stream()
+ .filter(es -> allTopics || pattern.matcher(es.getKey()).matches())
+ .forEach(es -> {
+ List<NodeId> list = es.getValue();
+ if (list == null || list.isEmpty()) {
+ return;
+ }
+ Leadership l = leaderBoard.get(es.getKey());
+ print(FMT_C,
+ es.getKey(),
+ l == null ? "null" : l.leader(),
+ // formatting hacks to get it into a table
+ list.get(0).toString());
+ list.subList(1, list.size()).forEach(n -> print(FMT_C, " ", " ", n));
+ print(FMT_C, " ", " ", " ");
+ });
+ print("------------------------------------------------------------------------");
+ }
+
+ /**
+ * Returns JSON node representing the leaders.
+ *
+ * @param leaderBoard map of leaders
+ */
+ private JsonNode json(Map<String, Leadership> leaderBoard) {
+ ObjectMapper mapper = new ObjectMapper();
+ ArrayNode result = mapper.createArrayNode();
+ leaderBoard.values()
+ .stream()
+ .sorted(leadershipComparator)
+ .forEach(l ->
+ result.add(
+ mapper.createObjectNode()
+ .put("topic", l.topic())
+ .put("leader", l.leader().toString())
+ .put("candidates", l.candidates().toString())
+ .put("epoch", l.epoch())
+ .put("electedTime", Tools.timeAgo(l.electedTime()))));
+
+ return result;
+ }
+
+ /**
+ * Returns JSON node representing the leaders.
+ *
+ * @param leaderBoard map of leaders
+ */
+ private JsonNode json(Map<String, Leadership> leaderBoard,
+ Map<String, List<NodeId>> candidateBoard) {
+ ObjectMapper mapper = new ObjectMapper();
+ ArrayNode result = mapper.createArrayNode();
+ candidateBoard.entrySet()
+ .stream()
+ .forEach(es -> {
+ Leadership l = leaderBoard.get(es.getKey());
+ result.add(
+ mapper.createObjectNode()
+ .put("topic", es.getKey())
+ .put("leader", l == null ? "none" : l.leader().toString())
+ .put("candidates", es.getValue().toString()));
+ });
+ return result;
+ }
+
+ @Override
+ protected void execute() {
+ LeadershipService leaderService = get(LeadershipService.class);
+ Map<String, Leadership> leaderBoard = leaderService.getLeaderBoard();
+ if (topicPattern == null) {
+ allTopics = true;
+ } else {
+ allTopics = false;
+ pattern = Pattern.compile(topicPattern);
+ }
+
+ if (showCandidates) {
+ Map<String, List<NodeId>> candidates = leaderService
+ .getCandidates();
+ if (outputJson()) {
+ print("%s", json(leaderBoard, candidates));
+ } else {
+ displayCandidates(leaderBoard, candidates);
+ }
+ } else {
+ if (outputJson()) {
+ print("%s", json(leaderBoard));
+ } else {
+ displayLeaders(leaderBoard);
+ }
+ }
+ }
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/LinkDstCompleter.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/LinkDstCompleter.java
new file mode 100644
index 00000000..626777e3
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/LinkDstCompleter.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2015 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.cli.net;
+
+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.net.ConnectPoint;
+import org.onosproject.net.link.LinkService;
+
+import java.util.List;
+import java.util.SortedSet;
+
+/**
+ * Link destination end-point completer.
+ */
+public class LinkDstCompleter extends AbstractCompleter {
+ @Override
+ public int complete(String buffer, int cursor, List<String> candidates) {
+ // Delegate string completer
+ StringsCompleter delegate = new StringsCompleter();
+
+ // Fetch our service and feed it's offerings to the string completer
+ LinkService service = AbstractShellCommand.get(LinkService.class);
+
+ // Link source the previous argument.
+ ArgumentCompleter.ArgumentList list = getArgumentList();
+ String srcArg = list.getArguments()[list.getCursorArgumentIndex() - 1];
+
+ // Generate the device ID/port number identifiers
+ SortedSet<String> strings = delegate.getStrings();
+ try {
+ ConnectPoint src = ConnectPoint.deviceConnectPoint(srcArg);
+ service.getEgressLinks(src)
+ .forEach(link -> strings.add(link.dst().elementId().toString() +
+ "/" + link.dst().port()));
+ } catch (NumberFormatException e) {
+ System.err.println("Invalid connect-point");
+ }
+
+ // Now let the completer do the work for figuring out what to offer.
+ return delegate.complete(buffer, cursor, candidates);
+ }
+
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/LinkResourceTestCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/LinkResourceTestCommand.java
new file mode 100644
index 00000000..d68084c7
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/LinkResourceTestCommand.java
@@ -0,0 +1,123 @@
+package org.onosproject.cli.net;
+
+import java.util.Set;
+import java.util.List;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.commands.Option;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.net.intent.IntentId;
+import org.onosproject.net.resource.link.DefaultLinkResourceRequest;
+import org.onosproject.net.resource.link.LinkResourceAllocations;
+import org.onosproject.net.resource.link.LinkResourceRequest;
+import org.onosproject.net.resource.link.LinkResourceService;
+import org.onosproject.net.topology.PathService;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.Link;
+import org.onosproject.net.Path;
+
+import com.google.common.collect.Lists;
+
+/**
+ * Commands to test out LinkResourceManager directly.
+ */
+@Command(scope = "onos", name = "resource-request",
+ description = "request or remove resources")
+public class LinkResourceTestCommand extends AbstractShellCommand {
+
+ // default is bandwidth.
+ @Option(name = "-m", aliases = "--mpls", description = "MPLS resource",
+ required = false, multiValued = false)
+ private boolean isMPLS = false;
+
+ @Option(name = "-o", aliases = "--optical", description = "Optical resource",
+ required = false, multiValued = false)
+ private boolean isOptical = false;
+
+ @Option(name = "-d", aliases = "--delete", description = "Delete resource by intent ID",
+ required = false, multiValued = false)
+ private boolean remove = false;
+
+ @Argument(index = 0, name = "srcString", description = "Link source",
+ required = true, multiValued = false)
+ String srcString = null;
+
+ @Argument(index = 1, name = "dstString", description = "Link destination",
+ required = true, multiValued = false)
+ String dstString = null;
+
+ @Argument(index = 2, name = "id", description = "Identifier",
+ required = true, multiValued = false)
+ int id;
+
+ private LinkResourceService resService;
+ private PathService pathService;
+
+ private static final int BANDWIDTH = 1_000_000;
+
+ @Override
+ protected void execute() {
+ resService = get(LinkResourceService.class);
+ pathService = get(PathService.class);
+
+ DeviceId src = DeviceId.deviceId(getDeviceId(srcString));
+ DeviceId dst = DeviceId.deviceId(getDeviceId(dstString));
+ IntentId intId = IntentId.valueOf(id);
+
+ Set<Path> paths = pathService.getPaths(src, dst);
+
+ if (paths == null || paths.isEmpty()) {
+ print("No path between %s and %s", srcString, dstString);
+ return;
+ }
+
+ if (remove) {
+ LinkResourceAllocations lra = resService.getAllocations(intId);
+ resService.releaseResources(lra);
+ return;
+ }
+
+ for (Path p : paths) {
+ List<Link> links = p.links();
+ LinkResourceRequest.Builder request = null;
+ if (isMPLS) {
+ List<Link> nlinks = Lists.newArrayList();
+ try {
+ nlinks.addAll(links.subList(1, links.size() - 2));
+ request = DefaultLinkResourceRequest.builder(intId, nlinks)
+ .addMplsRequest();
+ } catch (IndexOutOfBoundsException e) {
+ log.warn("could not allocate MPLS path", e);
+ continue;
+ }
+ } else if (isOptical) {
+ request = DefaultLinkResourceRequest.builder(intId, links)
+ .addLambdaRequest();
+ } else {
+ request = DefaultLinkResourceRequest.builder(intId, links)
+ .addBandwidthRequest(BANDWIDTH);
+ }
+
+ if (request != null) {
+ LinkResourceRequest lrr = request.build();
+ LinkResourceAllocations lra = resService.requestResources(lrr);
+ if (lra != null) {
+ break;
+ }
+ print("Allocated:\n%s", lra);
+ } else {
+ log.info("nothing to request");
+ }
+ }
+ }
+
+ public String getDeviceId(String deviceString) {
+ int slash = deviceString.indexOf('/');
+ if (slash <= 0) {
+ return "";
+ }
+ return deviceString.substring(0, slash);
+ }
+
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/LinkSrcCompleter.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/LinkSrcCompleter.java
new file mode 100644
index 00000000..f957f77f
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/LinkSrcCompleter.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2015 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.cli.net;
+
+import org.apache.karaf.shell.console.completer.StringsCompleter;
+import org.onosproject.cli.AbstractCompleter;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.net.link.LinkService;
+
+import java.util.List;
+import java.util.SortedSet;
+
+/**
+ * Link source end-point completer.
+ */
+public class LinkSrcCompleter extends AbstractCompleter {
+ @Override
+ public int complete(String buffer, int cursor, List<String> candidates) {
+ // Delegate string completer
+ StringsCompleter delegate = new StringsCompleter();
+
+ // Fetch our service and feed it's offerings to the string completer
+ LinkService service = AbstractShellCommand.get(LinkService.class);
+
+ // Generate the device ID/port number identifiers
+ SortedSet<String> strings = delegate.getStrings();
+ service.getLinks()
+ .forEach(link -> strings.add(link.src().elementId().toString() +
+ "/" + link.src().port()));
+
+ // Now let the completer do the work for figuring out what to offer.
+ return delegate.complete(buffer, cursor, candidates);
+ }
+
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/LinksListCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/LinksListCommand.java
new file mode 100644
index 00000000..b9403a39
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/LinksListCommand.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2014 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.cli.net;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.net.Link;
+import org.onosproject.net.link.LinkService;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+import static org.onosproject.net.DeviceId.deviceId;
+
+/**
+ * Lists all infrastructure links.
+ */
+@Command(scope = "onos", name = "links",
+ description = "Lists all infrastructure links")
+public class LinksListCommand extends AbstractShellCommand {
+
+ private static final String FMT = "src=%s/%s, dst=%s/%s, type=%s, state=%s%s";
+ private static final String COMPACT = "%s/%s-%s/%s";
+
+ @Argument(index = 0, name = "uri", description = "Device ID",
+ required = false, multiValued = false)
+ String uri = null;
+
+ @Override
+ protected void execute() {
+ LinkService service = get(LinkService.class);
+ Iterable<Link> links = uri != null ?
+ service.getDeviceLinks(deviceId(uri)) : service.getLinks();
+ if (outputJson()) {
+ print("%s", json(this, links));
+ } else {
+ for (Link link : links) {
+ print(linkString(link));
+ }
+ }
+ }
+
+ /**
+ * Produces a JSON array containing the specified links.
+ *
+ * @param context context to use for looking up codecs
+ * @param links collection of links
+ * @return JSON array
+ */
+ public static JsonNode json(AbstractShellCommand context, Iterable<Link> links) {
+ ObjectMapper mapper = new ObjectMapper();
+ ArrayNode result = mapper.createArrayNode();
+
+ links.forEach(link -> result.add(context.jsonForEntity(link, Link.class)));
+
+ return result;
+ }
+
+ /**
+ * Produces a JSON object for the specified link.
+ *
+ * @param context context to use for looking up codecs
+ * @param link link to encode
+ * @return JSON object
+ */
+ public static ObjectNode json(AbstractShellCommand context, Link link) {
+ return context.jsonForEntity(link, Link.class);
+ }
+
+ /**
+ * Returns a formatted string representing the given link.
+ *
+ * @param link infrastructure link
+ * @return formatted link string
+ */
+ public static String linkString(Link link) {
+ return String.format(FMT, link.src().deviceId(), link.src().port(),
+ link.dst().deviceId(), link.dst().port(),
+ link.type(), link.state(),
+ annotations(link.annotations()));
+ }
+
+ /**
+ * Returns a compact string representing the given link.
+ *
+ * @param link infrastructure link
+ * @return formatted link string
+ */
+ public static String compactLinkString(Link link) {
+ return String.format(COMPACT, link.src().deviceId(), link.src().port(),
+ link.dst().deviceId(), link.dst().port());
+ }
+
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/MapsListCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/MapsListCommand.java
new file mode 100644
index 00000000..27cc5254
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/MapsListCommand.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2015 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.cli.net;
+
+import java.util.List;
+
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.store.service.MapInfo;
+import org.onosproject.store.service.StorageAdminService;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+/**
+ * Command to list the various maps in the system.
+ */
+@Command(scope = "onos", name = "maps",
+ description = "Lists information about consistent maps in the system")
+public class MapsListCommand extends AbstractShellCommand {
+
+ // TODO: Add support to display different eventually
+ // consistent maps as well.
+
+ private static final String FMT = "name=%s size=%d";
+
+ /**
+ * Displays map info as text.
+ *
+ * @param mapInfo map descriptions
+ */
+ private void displayMaps(List<MapInfo> mapInfo) {
+ for (MapInfo info : mapInfo) {
+ print(FMT, info.name(), info.size());
+ }
+ }
+
+ /**
+ * Converts list of map info into a JSON object.
+ *
+ * @param mapInfo map descriptions
+ */
+ private JsonNode json(List<MapInfo> mapInfo) {
+ ObjectMapper mapper = new ObjectMapper();
+ ArrayNode maps = mapper.createArrayNode();
+
+ // Create a JSON node for each map
+ mapInfo.stream()
+ .forEach(info -> {
+ ObjectNode map = mapper.createObjectNode();
+ map.put("name", info.name())
+ .put("size", info.size());
+ maps.add(map);
+ });
+
+ return maps;
+ }
+
+ @Override
+ protected void execute() {
+ StorageAdminService storageAdminService = get(StorageAdminService.class);
+ List<MapInfo> mapInfo = storageAdminService.getMapInfo();
+ if (outputJson()) {
+ print("%s", json(mapInfo));
+ } else {
+ displayMaps(mapInfo);
+ }
+ }
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/Meters.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/Meters.java
new file mode 100644
index 00000000..76f3813c
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/Meters.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2015 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.cli.net;
+
+import com.google.common.collect.Collections2;
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.meter.Meter;
+import org.onosproject.net.meter.MeterService;
+
+import java.util.Collection;
+
+/**
+ * Add a meter.
+ */
+@Command(scope = "onos", name = "meters",
+ description = "Shows meters")
+public class Meters extends AbstractShellCommand {
+
+ @Argument(index = 0, name = "uri", description = "Device ID",
+ required = false, multiValued = false)
+ String uri = null;
+
+
+ @Override
+ protected void execute() {
+ MeterService service = get(MeterService.class);
+
+ Collection<Meter> meters = service.getAllMeters();
+ if (uri != null) {
+ DeviceId deviceId = DeviceId.deviceId(uri);
+ Collection<Meter> devMeters = Collections2.filter(meters,
+ m -> m.deviceId().equals(deviceId));
+ printMeters(devMeters);
+ } else {
+ printMeters(meters);
+ }
+ }
+
+ private void printMeters(Collection<Meter> meters) {
+ meters.forEach(m -> print(" %s", m));
+ }
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/PartitionsListCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/PartitionsListCommand.java
new file mode 100644
index 00000000..8b3d1660
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/PartitionsListCommand.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2015 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.cli.net;
+
+import java.util.List;
+
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.store.service.PartitionInfo;
+import org.onosproject.store.service.StorageAdminService;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+/**
+ * Command to list the database partitions in the system.
+ */
+@Command(scope = "onos", name = "partitions",
+ description = "Lists information about partitions in the system")
+public class PartitionsListCommand extends AbstractShellCommand {
+
+ private static final String FMT = "%-20s %8s %25s %s";
+
+ /**
+ * Displays partition info as text.
+ *
+ * @param partitionInfo partition descriptions
+ */
+ private void displayPartitions(List<PartitionInfo> partitionInfo) {
+ print("----------------------------------------------------------");
+ print(FMT, "Name", "Term", "Members", "");
+ print("----------------------------------------------------------");
+
+ for (PartitionInfo info : partitionInfo) {
+ boolean first = true;
+ for (String member : info.members()) {
+ if (first) {
+ print(FMT, info.name(), info.term(), member,
+ member.equals(info.leader()) ? "*" : "");
+ first = false;
+ } else {
+ print(FMT, "", "", member,
+ member.equals(info.leader()) ? "*" : "");
+ }
+ }
+ if (!first) {
+ print("----------------------------------------------------------");
+ }
+ }
+ }
+
+ /**
+ * Converts partition info into a JSON object.
+ *
+ * @param partitionInfo partition descriptions
+ */
+ private JsonNode json(List<PartitionInfo> partitionInfo) {
+ ObjectMapper mapper = new ObjectMapper();
+ ArrayNode partitions = mapper.createArrayNode();
+
+ // Create a JSON node for each partition
+ partitionInfo.stream()
+ .forEach(info -> {
+ ObjectNode partition = mapper.createObjectNode();
+
+ // Add each member to the "members" array for this partition
+ ArrayNode members = partition.putArray("members");
+ info.members()
+ .stream()
+ .forEach(members::add);
+
+ // Complete the partition attributes and add it to the array
+ partition.put("name", info.name())
+ .put("term", info.term())
+ .put("leader", info.leader());
+ partitions.add(partition);
+
+ });
+
+ return partitions;
+ }
+
+ @Override
+ protected void execute() {
+ StorageAdminService storageAdminService = get(StorageAdminService.class);
+ List<PartitionInfo> partitionInfo = storageAdminService.getPartitionInfo();
+
+ if (outputJson()) {
+ print("%s", json(partitionInfo));
+ } else {
+ displayPartitions(partitionInfo);
+ }
+ }
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/PathListCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/PathListCommand.java
new file mode 100644
index 00000000..141ae266
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/PathListCommand.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2014 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.cli.net;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.net.Link;
+import org.onosproject.net.Path;
+
+import java.util.Set;
+
+import static org.onosproject.cli.net.LinksListCommand.compactLinkString;
+import static org.onosproject.net.DeviceId.deviceId;
+
+/**
+ * Lists all shortest-paths paths between the specified source and
+ * destination devices.
+ */
+@Command(scope = "onos", name = "paths",
+ description = "Lists all shortest-paths paths between the specified source and destination devices")
+public class PathListCommand extends TopologyCommand {
+
+ private static final String SEP = "==>";
+
+ @Argument(index = 0, name = "src", description = "Source device ID",
+ required = true, multiValued = false)
+ String src = null;
+
+ @Argument(index = 1, name = "dst", description = "Destination device ID",
+ required = true, multiValued = false)
+ String dst = null;
+
+ @Override
+ protected void execute() {
+ init();
+ Set<Path> paths = service.getPaths(topology, deviceId(src), deviceId(dst));
+ if (outputJson()) {
+ print("%s", json(this, paths));
+ } else {
+ for (Path path : paths) {
+ print(pathString(path));
+ }
+ }
+ }
+
+ /**
+ * Produces a JSON array containing the specified paths.
+ *
+ * @param context context to use for looking up codecs
+ * @param paths collection of paths
+ * @return JSON array
+ */
+ public static JsonNode json(AbstractShellCommand context, Iterable<Path> paths) {
+ ObjectMapper mapper = new ObjectMapper();
+ ArrayNode result = mapper.createArrayNode();
+ for (Path path : paths) {
+ result.add(LinksListCommand.json(context, path)
+ .put("cost", path.cost())
+ .set("links", LinksListCommand.json(context, path.links())));
+ }
+ return result;
+ }
+
+ /**
+ * Produces a formatted string representing the specified path.
+ *
+ * @param path network path
+ * @return formatted path string
+ */
+ protected String pathString(Path path) {
+ StringBuilder sb = new StringBuilder();
+ for (Link link : path.links()) {
+ sb.append(compactLinkString(link)).append(SEP);
+ }
+ sb.delete(sb.lastIndexOf(SEP), sb.length());
+ sb.append("; cost=").append(path.cost());
+ return sb.toString();
+ }
+
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/RandomIntentCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/RandomIntentCommand.java
new file mode 100644
index 00000000..d917f904
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/RandomIntentCommand.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2014-2015 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.cli.net;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.CoreService;
+import org.onosproject.net.Host;
+import org.onosproject.net.host.HostService;
+import org.onosproject.net.intent.HostToHostIntent;
+import org.onosproject.net.intent.Intent;
+import org.onosproject.net.intent.IntentService;
+
+import com.google.common.collect.Lists;
+
+/**
+ * Installs bulk point-to-point connectivity intents between random ingress/egress devices.
+ */
+@Command(scope = "onos", name = "push-random-intents",
+ description = "Installs random intents to test throughput")
+public class RandomIntentCommand extends AbstractShellCommand {
+
+ @Argument(index = 0, name = "count",
+ description = "Number of intents to push",
+ required = true, multiValued = false)
+ String countString = null;
+
+ private IntentService service;
+ private HostService hostService;
+ private int count;
+
+ @Override
+ protected void execute() {
+ service = get(IntentService.class);
+ hostService = get(HostService.class);
+
+ count = Integer.parseInt(countString);
+
+ if (count > 0) {
+ Collection<Intent> intents = generateIntents();
+ submitIntents(intents);
+ } else {
+ withdrawIntents();
+ }
+ }
+
+ private Collection<Intent> generateIntents() {
+ List<Host> hosts = Lists.newArrayList(hostService.getHosts());
+ List<Intent> fullMesh = Lists.newArrayList();
+ for (int i = 0; i < hosts.size(); i++) {
+ for (int j = i + 1; j < hosts.size(); j++) {
+ fullMesh.add(HostToHostIntent.builder()
+ .appId(appId())
+ .one(hosts.get(i).id())
+ .two(hosts.get(j).id())
+ .build());
+
+ }
+ }
+ Collections.shuffle(fullMesh);
+ return fullMesh.subList(0, Math.min(count, fullMesh.size()));
+ }
+
+ private void submitIntents(Collection<Intent> intents) {
+ for (Intent intent : intents) {
+ service.submit(intent);
+ }
+ print("Submitted %d host to host intents.", intents.size());
+ }
+
+ private void withdrawIntents() {
+ for (Intent intent : service.getIntents()) {
+ if (appId().equals(intent.appId())) {
+ service.withdraw(intent);
+ }
+ }
+ print("Withdrew all randomly generated host to host intents.");
+ }
+
+ @Override
+ protected ApplicationId appId() {
+ return get(CoreService.class).registerApplication("org.onosproject.cli-random");
+ }
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/ResourceAllocationsCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/ResourceAllocationsCommand.java
new file mode 100644
index 00000000..9a18bfce
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/ResourceAllocationsCommand.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2014 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.cli.net;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.Link;
+import org.onosproject.net.link.LinkService;
+import org.onosproject.net.resource.link.LinkResourceService;
+
+/**
+ * Lists allocations by link. Lists all allocations if link is unspecified.
+ */
+@Command(scope = "onos", name = "resource-allocations",
+ description = "Lists allocations by link. Lists all allocations if link is unspecified.")
+public class ResourceAllocationsCommand extends AbstractShellCommand {
+
+ private static final String FMT = "src=%s/%s, dst=%s/%s, type=%s%s";
+ private static final String COMPACT = "%s/%s-%s/%s";
+
+ @Argument(index = 0, name = "srcString", description = "Link source",
+ required = false, multiValued = false)
+ String srcString = null;
+ @Argument(index = 1, name = "dstString", description = "Link destination",
+ required = false, multiValued = false)
+ String dstString = null;
+
+ @Override
+ protected void execute() {
+ LinkResourceService resourceService = get(LinkResourceService.class);
+ LinkService linkService = get(LinkService.class);
+
+ if (srcString == null || dstString == null) {
+ print("----- Displaying all resource allocations -----");
+ resourceService.getAllocations().forEach(alloc -> print("%s", alloc));
+ return;
+ }
+
+ ConnectPoint src = ConnectPoint.deviceConnectPoint(srcString);
+ ConnectPoint dst = ConnectPoint.deviceConnectPoint(dstString);
+
+ Link link = linkService.getLink(src, dst);
+ if (link != null) {
+ resourceService.getAllocations(link).forEach(alloc -> print("%s", alloc));
+ } else {
+ print("No path found for endpoints: %s, %s", src, dst);
+ }
+ }
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/ResourceAvailableCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/ResourceAvailableCommand.java
new file mode 100644
index 00000000..ab0d3958
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/ResourceAvailableCommand.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2014 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.cli.net;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.Link;
+import org.onosproject.net.link.LinkService;
+import org.onosproject.net.resource.link.LinkResourceService;
+import org.onosproject.net.resource.ResourceRequest;
+
+/**
+ * Lists allocations by link.
+ */
+@Command(scope = "onos", name = "resource-available",
+ description = "Lists available resources by link")
+public class ResourceAvailableCommand extends AbstractShellCommand {
+
+ private static final String FMT = "src=%s/%s, dst=%s/%s, type=%s%s";
+ private static final String COMPACT = "%s/%s-%s/%s";
+
+ @Argument(index = 0, name = "srcString", description = "Link source",
+ required = false, multiValued = false)
+ String srcString = null;
+ @Argument(index = 1, name = "dstString", description = "Link destination",
+ required = false, multiValued = false)
+ String dstString = null;
+
+ @Override
+ protected void execute() {
+ LinkResourceService resourceService = get(LinkResourceService.class);
+ LinkService linkService = get(LinkService.class);
+
+ Iterable<ResourceRequest> itr = null;
+ try {
+ ConnectPoint src = ConnectPoint.deviceConnectPoint(srcString);
+
+ ConnectPoint dst = ConnectPoint.deviceConnectPoint(dstString);
+
+ Link link = linkService.getLink(src, dst);
+
+ itr = resourceService.getAvailableResources(link);
+
+ int lambdaCount = 0;
+ for (ResourceRequest req : itr) {
+ switch (req.type()) {
+ case LAMBDA:
+ lambdaCount++;
+ break;
+ case BANDWIDTH:
+ print("%s", req);
+ break;
+ default:
+ break;
+ }
+ }
+ if (lambdaCount > 0) {
+ print("Number of available lambdas: %d", lambdaCount);
+ }
+
+ } catch (Exception e) {
+ print("Invalid link %s", e.getMessage());
+ }
+ }
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/RoleCompleter.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/RoleCompleter.java
new file mode 100644
index 00000000..0b4fc97d
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/RoleCompleter.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2014 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.cli.net;
+
+import org.apache.karaf.shell.console.Completer;
+import org.apache.karaf.shell.console.completer.StringsCompleter;
+import org.onosproject.net.MastershipRole;
+
+import java.util.List;
+import java.util.SortedSet;
+
+/**
+ * Device mastership role completer.
+ */
+public class RoleCompleter implements Completer {
+ @Override
+ public int complete(String buffer, int cursor, List<String> candidates) {
+ // Delegate string completer
+ StringsCompleter delegate = new StringsCompleter();
+ SortedSet<String> strings = delegate.getStrings();
+ strings.add(MastershipRole.MASTER.toString().toLowerCase());
+ strings.add(MastershipRole.STANDBY.toString().toLowerCase());
+ strings.add(MastershipRole.NONE.toString().toLowerCase());
+
+ // Now let the completer do the work for figuring out what to offer.
+ return delegate.complete(buffer, cursor, candidates);
+ }
+
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/TopologyCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/TopologyCommand.java
new file mode 100644
index 00000000..e1ebd25a
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/TopologyCommand.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2014-2015 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.cli.net;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.commands.Option;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.net.topology.Topology;
+import org.onosproject.net.topology.TopologyProvider;
+import org.onosproject.net.topology.TopologyService;
+
+/**
+ * Lists summary of the current topology.
+ */
+@Command(scope = "onos", name = "topology",
+description = "Lists summary of the current topology")
+public class TopologyCommand extends AbstractShellCommand {
+
+ private static final String FMT = "created=%s, uptime=%s, devices=%d, links=%d, clusters=%d";
+
+ @Option(name = "-r", aliases = "--recompute",
+ description = "Trigger topology re-computation", required = false,
+ multiValued = false)
+ private boolean recompute = false;
+
+ protected TopologyService service;
+ protected Topology topology;
+
+ /**
+ * Initializes the context for all cluster commands.
+ */
+ protected void init() {
+ service = get(TopologyService.class);
+ topology = service.currentTopology();
+ }
+
+ @Override
+ protected void execute() {
+ init();
+ long topologyUptime =
+ Math.max(0, (System.currentTimeMillis() - topology.creationTime()));
+ if (recompute) {
+ get(TopologyProvider.class).triggerRecompute();
+
+ } else if (outputJson()) {
+ print("%s",
+ jsonForEntity(topology, Topology.class));
+ } else {
+ print(FMT, formatCreationTime(topology.creationTime()),
+ formatElapsedTime(topologyUptime),
+ topology.deviceCount(), topology.linkCount(),
+ topology.clusterCount());
+ }
+ }
+
+ /**
+ * Converts millis to a formatted elapsed time string.
+ *
+ * @param millis Duration in millis to convert to a string
+ *
+ * @return Formatted string: "D days, H hrs, M mins, S secs".
+ */
+ private static String formatElapsedTime(long millis) {
+ if (millis < 0) {
+ throw new IllegalArgumentException("Interval less than zero. "
+ + "Possible unsynchronized timestamps");
+ }
+
+ final long days = TimeUnit.MILLISECONDS.toDays(millis);
+ millis -= TimeUnit.DAYS.toMillis(days);
+ final long hours = TimeUnit.MILLISECONDS.toHours(millis);
+ millis -= TimeUnit.HOURS.toMillis(hours);
+ final long minutes = TimeUnit.MILLISECONDS.toMinutes(millis);
+ millis -= TimeUnit.MINUTES.toMillis(minutes);
+ final long seconds = TimeUnit.MILLISECONDS.toSeconds(millis);
+
+ final StringBuilder topologyUptimeString = new StringBuilder(64);
+ topologyUptimeString.append(days);
+ topologyUptimeString.append(" days, ");
+ topologyUptimeString.append(hours);
+ topologyUptimeString.append(" hrs, ");
+ topologyUptimeString.append(minutes);
+ topologyUptimeString.append(" mins, ");
+ topologyUptimeString.append(seconds);
+ topologyUptimeString.append(" secs");
+
+ return (topologyUptimeString.toString());
+ }
+
+ /**
+ * Converts millis to a formatted Date String.
+ *
+ * @param millis Duration in millis to convert to a string
+ *
+ * @return Formatted string: yyyy-MM-dd HH:mm:ss.
+ */
+ private static String formatCreationTime(long millis) {
+ final DateFormat dateFormatter =
+ new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+ Calendar calendar = Calendar.getInstance();
+ calendar.setTimeInMillis(millis);
+ return (dateFormatter.format(calendar.getTime()));
+ }
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/TransactionsCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/TransactionsCommand.java
new file mode 100644
index 00000000..6013a389
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/TransactionsCommand.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2015 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.cli.net;
+
+import java.util.Collection;
+
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.commands.Option;
+import org.onlab.util.Tools;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.store.service.StorageAdminService;
+import org.onosproject.store.service.Transaction;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+/**
+ * CLI to work with database transactions in the system.
+ */
+@Command(scope = "onos", name = "transactions",
+ description = "Utility for viewing and redriving database transactions")
+public class TransactionsCommand extends AbstractShellCommand {
+
+ @Option(name = "-r", aliases = "--redrive",
+ description = "Redrive stuck transactions while removing those that are done",
+ required = false, multiValued = false)
+ private boolean redrive = false;
+
+ private static final String FMT = "%-20s %-15s %-10s";
+
+ /**
+ * Displays transactions as text.
+ *
+ * @param transactions transactions
+ */
+ private void displayTransactions(Collection<Transaction> transactions) {
+ print("---------------------------------------------");
+ print(FMT, "Id", "State", "Updated");
+ print("---------------------------------------------");
+ transactions.forEach(txn -> print(FMT, txn.id(), txn.state(), Tools.timeAgo(txn.lastUpdated())));
+ if (transactions.size() > 0) {
+ print("---------------------------------------------");
+ }
+ }
+
+ /**
+ * Converts collection of transactions into a JSON object.
+ *
+ * @param transactions transactions
+ */
+ private JsonNode json(Collection<Transaction> transactions) {
+ ObjectMapper mapper = new ObjectMapper();
+ ArrayNode txns = mapper.createArrayNode();
+
+ // Create a JSON node for each transaction
+ transactions.stream().forEach(txn -> {
+ ObjectNode txnNode = mapper.createObjectNode();
+ txnNode.put("id", txn.id())
+ .put("state", txn.state().toString())
+ .put("lastUpdated", txn.lastUpdated());
+ txns.add(txnNode);
+ });
+
+ return txns;
+ }
+
+ @Override
+ protected void execute() {
+ StorageAdminService storageAdminService = get(StorageAdminService.class);
+
+ if (redrive) {
+ storageAdminService.redriveTransactions();
+ return;
+ }
+
+ Collection<Transaction> transactions = storageAdminService.getTransactions();
+ if (outputJson()) {
+ print("%s", json(transactions));
+ } else {
+ displayTransactions(transactions);
+ }
+ }
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/TunnelBorrowCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/TunnelBorrowCommand.java
new file mode 100644
index 00000000..3db4e865
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/TunnelBorrowCommand.java
@@ -0,0 +1,212 @@
+/*
+ * Copyright 2014-2015 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.cli.net;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Optional;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.commands.Option;
+import org.onlab.packet.IpAddress;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.DefaultApplicationId;
+import org.onosproject.incubator.net.tunnel.DefaultOpticalTunnelEndPoint;
+import org.onosproject.incubator.net.tunnel.IpTunnelEndPoint;
+import org.onosproject.incubator.net.tunnel.OpticalLogicId;
+import org.onosproject.incubator.net.tunnel.OpticalTunnelEndPoint;
+import org.onosproject.incubator.net.tunnel.Tunnel;
+import org.onosproject.incubator.net.tunnel.TunnelEndPoint;
+import org.onosproject.incubator.net.tunnel.TunnelId;
+import org.onosproject.incubator.net.tunnel.TunnelName;
+import org.onosproject.incubator.net.tunnel.TunnelService;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.provider.ProviderId;
+
+/**
+ * Borrows tunnels. It's used by consumers.
+ */
+@Command(scope = "onos", name = "tunnel-borrow", description = "Borrows tunnels. It's used by consumers.")
+public class TunnelBorrowCommand extends AbstractShellCommand {
+
+ @Argument(index = 0, name = "consumerId",
+ description = "consumer id means application id.", required = true, multiValued = false)
+ String consumerId = null;
+
+ @Option(name = "-s", aliases = "--src", description = "Source tunnel point."
+ + " Only supports for IpTunnelEndPoint and OpticalTunnelEndPoint as end point now."
+ + " If deletess a ODUK or OCH type tunnel, the formatter of this argument is DeviceId-PortNumber."
+ + " Otherwise src means IP address.", required = false, multiValued = false)
+ String src = null;
+
+ @Option(name = "-d", aliases = "--dst", description = "Destination tunnel point."
+ + " Only supports for IpTunnelEndPoint and OpticalTunnelEndPoint as end point now."
+ + " If deletess a ODUK or OCH type tunnel, the formatter of this argument is DeviceId-PortNumber."
+ + " Otherwise dst means IP address.", required = false, multiValued = false)
+ String dst = null;
+
+ @Option(name = "-t", aliases = "--type", description = "The type of tunnels,"
+ + " It includes MPLS, VLAN, VXLAN, GRE, ODUK, OCH", required = false, multiValued = false)
+ String type = null;
+
+ @Option(name = "-i", aliases = "--tunnelId",
+ description = "the tunnel identity.", required = false, multiValued = false)
+ String tunnelId = null;
+
+ @Option(name = "-n", aliases = "--tunnelName",
+ description = "The name of tunnels", required = false, multiValued = false)
+ String tunnelName = null;
+ private static final String FMT = "src=%s, dst=%s,"
+ + "type=%s, state=%s, producerName=%s, tunnelName=%s,"
+ + "groupId=%s";
+
+ @Override
+ protected void execute() {
+ Collection<Tunnel> tunnelSet = null;
+ Tunnel.Type trueType = null;
+ TunnelService service = get(TunnelService.class);
+ ApplicationId appId = new DefaultApplicationId(1, consumerId);
+ ProviderId producerName = new ProviderId("default",
+ "org.onosproject.provider.tunnel.default");
+ if (!isNull(src) && !isNull(dst) && !isNull(type)) {
+ TunnelEndPoint srcPoint = null;
+ TunnelEndPoint dstPoint = null;
+ if ("MPLS".equals(type)) {
+ trueType = Tunnel.Type.MPLS;
+ srcPoint = IpTunnelEndPoint.ipTunnelPoint(IpAddress
+ .valueOf(src));
+ dstPoint = IpTunnelEndPoint.ipTunnelPoint(IpAddress
+ .valueOf(dst));
+ } else if ("VXLAN".equals(type)) {
+ trueType = Tunnel.Type.VXLAN;
+ srcPoint = IpTunnelEndPoint.ipTunnelPoint(IpAddress
+ .valueOf(src));
+ dstPoint = IpTunnelEndPoint.ipTunnelPoint(IpAddress
+ .valueOf(dst));
+ } else if ("GRE".equals(type)) {
+ trueType = Tunnel.Type.GRE;
+ srcPoint = IpTunnelEndPoint.ipTunnelPoint(IpAddress
+ .valueOf(src));
+ dstPoint = IpTunnelEndPoint.ipTunnelPoint(IpAddress
+ .valueOf(dst));
+ } else if ("VLAN".equals(type)) {
+ trueType = Tunnel.Type.VLAN;
+ String[] srcArray = src.split("-");
+ String[] dstArray = dst.split("-");
+ srcPoint = new DefaultOpticalTunnelEndPoint(
+ producerName,
+ Optional.of(DeviceId
+ .deviceId(srcArray[0])),
+ Optional.of(PortNumber
+ .portNumber(srcArray[1])),
+ null,
+ null,
+ OpticalLogicId
+ .logicId(0),
+ true);
+ dstPoint = new DefaultOpticalTunnelEndPoint(
+ producerName,
+ Optional.of(DeviceId
+ .deviceId(dstArray[0])),
+ Optional.of(PortNumber
+ .portNumber(dstArray[1])),
+ null,
+ null,
+ OpticalLogicId
+ .logicId(0),
+ true);
+ } else if ("ODUK".equals(type)) {
+ trueType = Tunnel.Type.ODUK;
+ String[] srcArray = src.split("-");
+ String[] dstArray = dst.split("-");
+ srcPoint = new DefaultOpticalTunnelEndPoint(
+ producerName,
+ Optional.of(DeviceId
+ .deviceId(srcArray[0])),
+ Optional.of(PortNumber
+ .portNumber(srcArray[1])),
+ null,
+ OpticalTunnelEndPoint.Type.LAMBDA,
+ OpticalLogicId
+ .logicId(0),
+ true);
+ dstPoint = new DefaultOpticalTunnelEndPoint(
+ producerName,
+ Optional.of(DeviceId
+ .deviceId(dstArray[0])),
+ Optional.of(PortNumber
+ .portNumber(dstArray[1])),
+ null,
+ OpticalTunnelEndPoint.Type.LAMBDA,
+ OpticalLogicId
+ .logicId(0),
+ true);
+ } else if ("OCH".equals(type)) {
+ trueType = Tunnel.Type.OCH;
+ String[] srcArray = src.split("-");
+ String[] dstArray = dst.split("-");
+ srcPoint = new DefaultOpticalTunnelEndPoint(
+ producerName,
+ Optional.of(DeviceId
+ .deviceId(srcArray[0])),
+ Optional.of(PortNumber
+ .portNumber(srcArray[1])),
+ null,
+ OpticalTunnelEndPoint.Type.TIMESLOT,
+ OpticalLogicId
+ .logicId(0),
+ true);
+ dstPoint = new DefaultOpticalTunnelEndPoint(
+ producerName,
+ Optional.of(DeviceId
+ .deviceId(dstArray[0])),
+ Optional.of(PortNumber
+ .portNumber(dstArray[1])),
+ null,
+ OpticalTunnelEndPoint.Type.TIMESLOT,
+ OpticalLogicId
+ .logicId(0),
+ true);
+ } else {
+ print("Illegal tunnel type. Please input MPLS, VLAN, VXLAN, GRE, ODUK or OCH.");
+ return;
+ }
+ tunnelSet = service.borrowTunnel(appId, srcPoint, dstPoint, trueType);
+ }
+ if (!isNull(tunnelId)) {
+ TunnelId id = TunnelId.valueOf(tunnelId);
+ Tunnel tunnel = service.borrowTunnel(appId, id);
+ tunnelSet = new HashSet<Tunnel>();
+ tunnelSet.add(tunnel);
+ }
+ if (!isNull(tunnelName)) {
+ TunnelName name = TunnelName.tunnelName(tunnelName);
+ tunnelSet = service.borrowTunnel(appId, name);
+ }
+ for (Tunnel tunnel : tunnelSet) {
+ print(FMT, tunnel.src(), tunnel.dst(), tunnel.type(),
+ tunnel.state(), tunnel.providerId(), tunnel.tunnelName(),
+ tunnel.groupId());
+ }
+ }
+
+ private boolean isNull(String s) {
+ return s == null || "".equals(s);
+ }
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/TunnelCreateCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/TunnelCreateCommand.java
new file mode 100644
index 00000000..955df887
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/TunnelCreateCommand.java
@@ -0,0 +1,205 @@
+/*
+ * Copyright 2015 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.cli.net;
+
+import java.util.Optional;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.commands.Option;
+import org.onlab.packet.IpAddress;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.core.DefaultGroupId;
+import org.onosproject.incubator.net.tunnel.DefaultOpticalTunnelEndPoint;
+import org.onosproject.incubator.net.tunnel.DefaultTunnelDescription;
+import org.onosproject.incubator.net.tunnel.IpTunnelEndPoint;
+import org.onosproject.incubator.net.tunnel.OpticalLogicId;
+import org.onosproject.incubator.net.tunnel.OpticalTunnelEndPoint;
+import org.onosproject.incubator.net.tunnel.Tunnel;
+import org.onosproject.incubator.net.tunnel.TunnelDescription;
+import org.onosproject.incubator.net.tunnel.TunnelEndPoint;
+import org.onosproject.incubator.net.tunnel.TunnelId;
+import org.onosproject.incubator.net.tunnel.TunnelName;
+import org.onosproject.incubator.net.tunnel.TunnelProvider;
+import org.onosproject.net.DefaultAnnotations;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.SparseAnnotations;
+import org.onosproject.net.provider.ProviderId;
+
+/**
+ * Supports for creating a tunnel by using IP address and optical as tunnel end
+ * point.
+ */
+@Command(scope = "onos", name = "tunnel-create",
+description = "Supports for creating a tunnel by using IP address and optical as tunnel end point now.")
+public class TunnelCreateCommand extends AbstractShellCommand {
+
+ @Argument(index = 0, name = "src", description = "Source tunnel point."
+ + " Only supports for IpTunnelEndPoint and OpticalTunnelEndPoint as end point now."
+ + " If creates a ODUK or OCH or VLAN type tunnel, the formatter of this argument is DeviceId-PortNumber."
+ + " Otherwise src means IP address.", required = true, multiValued = false)
+ String src = null;
+
+ @Argument(index = 1, name = "dst", description = "Destination tunnel point."
+ + " Only supports for IpTunnelEndPoint and OpticalTunnelEndPoint as end point now."
+ + " If creates a ODUK or OCH or VLAN type tunnel, the formatter of this argument is DeviceId-PortNumber."
+ + " Otherwise dst means IP address.", required = true, multiValued = false)
+ String dst = null;
+ @Argument(index = 2, name = "type", description = "The type of tunnels,"
+ + " It includes MPLS, VLAN, VXLAN, GRE, ODUK, OCH", required = true, multiValued = false)
+ String type = null;
+ @Option(name = "-g", aliases = "--groupId",
+ description = "Group flow table id which a tunnel match up", required = false, multiValued = false)
+ String groupId = "0";
+
+ @Option(name = "-n", aliases = "--tunnelName",
+ description = "The name of tunnels", required = false, multiValued = false)
+ String tunnelName = "onos";
+
+ @Option(name = "-b", aliases = "--bandwidth",
+ description = "The bandwidth attribute of tunnel", required = false, multiValued = false)
+ String bandwidth = "1024";
+
+ private static final String FMT = "The tunnel identity is %s";
+
+ @Override
+ protected void execute() {
+ TunnelProvider service = get(TunnelProvider.class);
+ ProviderId producerName = new ProviderId("default",
+ "org.onosproject.provider.tunnel.default");
+ TunnelEndPoint srcPoint = null;
+ TunnelEndPoint dstPoint = null;
+ Tunnel.Type trueType = null;
+ if ("MPLS".equals(type)) {
+ trueType = Tunnel.Type.MPLS;
+ srcPoint = IpTunnelEndPoint.ipTunnelPoint(IpAddress.valueOf(src));
+ dstPoint = IpTunnelEndPoint.ipTunnelPoint(IpAddress.valueOf(dst));
+ } else if ("VLAN".equals(type)) {
+ trueType = Tunnel.Type.VLAN;
+ String[] srcArray = src.split("/");
+ String[] dstArray = dst.split("/");
+ srcPoint = new DefaultOpticalTunnelEndPoint(
+ producerName,
+ Optional.of(DeviceId
+ .deviceId(srcArray[0])),
+ Optional.of(PortNumber
+ .portNumber(srcArray[1])),
+ null,
+ null,
+ OpticalLogicId
+ .logicId(0),
+ true);
+ dstPoint = new DefaultOpticalTunnelEndPoint(
+ producerName,
+ Optional.of(DeviceId
+ .deviceId(dstArray[0])),
+ Optional.of(PortNumber
+ .portNumber(dstArray[1])),
+ null,
+ null,
+ OpticalLogicId
+ .logicId(0),
+ true);
+ } else if ("VXLAN".equals(type)) {
+ trueType = Tunnel.Type.VXLAN;
+ srcPoint = IpTunnelEndPoint.ipTunnelPoint(IpAddress.valueOf(src));
+ dstPoint = IpTunnelEndPoint.ipTunnelPoint(IpAddress.valueOf(dst));
+ } else if ("GRE".equals(type)) {
+ trueType = Tunnel.Type.GRE;
+ srcPoint = IpTunnelEndPoint.ipTunnelPoint(IpAddress.valueOf(src));
+ dstPoint = IpTunnelEndPoint.ipTunnelPoint(IpAddress.valueOf(dst));
+ } else if ("ODUK".equals(type)) {
+ trueType = Tunnel.Type.ODUK;
+ String[] srcArray = src.split("/");
+ String[] dstArray = dst.split("/");
+ srcPoint = new DefaultOpticalTunnelEndPoint(
+ producerName,
+ Optional.of(DeviceId
+ .deviceId(srcArray[0])),
+ Optional.of(PortNumber
+ .portNumber(srcArray[1])),
+ null,
+ OpticalTunnelEndPoint.Type.LAMBDA,
+ OpticalLogicId
+ .logicId(0),
+ true);
+ dstPoint = new DefaultOpticalTunnelEndPoint(
+ producerName,
+ Optional.of(DeviceId
+ .deviceId(dstArray[0])),
+ Optional.of(PortNumber
+ .portNumber(dstArray[1])),
+ null,
+ OpticalTunnelEndPoint.Type.LAMBDA,
+ OpticalLogicId
+ .logicId(0),
+ true);
+ } else if ("OCH".equals(type)) {
+ trueType = Tunnel.Type.OCH;
+ String[] srcArray = src.split("/");
+ String[] dstArray = dst.split("/");
+ srcPoint = new DefaultOpticalTunnelEndPoint(
+ producerName,
+ Optional.of(DeviceId
+ .deviceId(srcArray[0])),
+ Optional.of(PortNumber
+ .portNumber(srcArray[1])),
+ null,
+ OpticalTunnelEndPoint.Type.TIMESLOT,
+ OpticalLogicId
+ .logicId(0),
+ true);
+ dstPoint = new DefaultOpticalTunnelEndPoint(
+ producerName,
+ Optional.of(DeviceId
+ .deviceId(dstArray[0])),
+ Optional.of(PortNumber
+ .portNumber(dstArray[1])),
+ null,
+ OpticalTunnelEndPoint.Type.TIMESLOT,
+ OpticalLogicId
+ .logicId(0),
+ true);
+ } else {
+ print("Illegal tunnel type. Please input MPLS, VLAN, VXLAN, GRE, ODUK or OCH.");
+ return;
+ }
+
+ SparseAnnotations annotations = DefaultAnnotations
+ .builder()
+ .set("bandwidth", bandwidth == null || "".equals(bandwidth) ? "0" : bandwidth)
+ .build();
+ TunnelDescription tunnel = new DefaultTunnelDescription(
+ null,
+ srcPoint,
+ dstPoint,
+ trueType,
+ new DefaultGroupId(Integer.parseInt(groupId)),
+ producerName,
+ TunnelName
+ .tunnelName(tunnelName),
+ null,
+ annotations);
+ TunnelId tunnelId = service.tunnelAdded(tunnel);
+ if (tunnelId == null) {
+ error("Create tunnel failed.");
+ return;
+ }
+ print(FMT, tunnelId.id());
+ }
+
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/TunnelQueryCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/TunnelQueryCommand.java
new file mode 100644
index 00000000..c60337c5
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/TunnelQueryCommand.java
@@ -0,0 +1,224 @@
+/*
+ * Copyright 2014-2015 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.cli.net;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Optional;
+
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.commands.Option;
+import org.onlab.packet.IpAddress;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.incubator.net.tunnel.DefaultOpticalTunnelEndPoint;
+import org.onosproject.incubator.net.tunnel.IpTunnelEndPoint;
+import org.onosproject.incubator.net.tunnel.OpticalLogicId;
+import org.onosproject.incubator.net.tunnel.OpticalTunnelEndPoint;
+import org.onosproject.incubator.net.tunnel.Tunnel;
+import org.onosproject.incubator.net.tunnel.TunnelEndPoint;
+import org.onosproject.incubator.net.tunnel.TunnelId;
+import org.onosproject.incubator.net.tunnel.TunnelService;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.Link;
+import org.onosproject.net.Path;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.provider.ProviderId;
+
+/**
+ * Supports for querying tunnels. It's used by consumers.
+ */
+@Command(scope = "onos", name = "tunnels", description = "Supports for querying tunnels."
+ + " It's used by consumers.")
+public class TunnelQueryCommand extends AbstractShellCommand {
+ @Option(name = "-s", aliases = "--src", description = "Source tunnel point."
+ + " Only supports for IpTunnelEndPoint and OpticalTunnelEndPoint as end point now."
+ + " If deletess a ODUK or OCH type tunnel, the formatter of this argument is DeviceId-PortNumber."
+ + " Otherwise src means IP address.", required = false, multiValued = false)
+ String src = null;
+ @Option(name = "-d", aliases = "--dst", description = "Destination tunnel point."
+ + " Only supports for IpTunnelEndPoint and OpticalTunnelEndPoint as end point now."
+ + " If deletess a ODUK or OCH type tunnel, the formatter of this argument is DeviceId-PortNumber."
+ + " Otherwise dst means IP address.", required = false, multiValued = false)
+ String dst = null;
+
+ @Option(name = "-t", aliases = "--type", description = "The type of tunnels,"
+ + " It includes MPLS, VLAN, VXLAN, GRE, ODUK, OCH", required = false, multiValued = false)
+ String type = null;
+
+ @Option(name = "-i", aliases = "--tunnelId",
+ description = "the tunnel identity.", required = false, multiValued = false)
+ String tunnelId = null;
+
+ private static final String FMT = "tunnelId=%s, src=%s, dst=%s,"
+ + "type=%s, state=%s, producerName=%s, tunnelName=%s,"
+ + "groupId=%s, path=%s%s";
+
+ @Override
+ protected void execute() {
+ Tunnel.Type trueType = null;
+ TunnelService service = get(TunnelService.class);
+ ProviderId producerName = new ProviderId("default",
+ "org.onosproject.provider.tunnel.default");
+ Collection<Tunnel> tunnelSet = null;
+ if (isNull(src) && isNull(dst) && isNull(type) && isNull(tunnelId)) {
+ tunnelSet = service.queryAllTunnels();
+ }
+
+ if (!isNull(src) && !isNull(dst) && !isNull(type)) {
+ TunnelEndPoint srcPoint = null;
+ TunnelEndPoint dstPoint = null;
+ if ("MPLS".equals(type) || "VXLAN".equals(type)
+ || "GRE".equals(type)) {
+ srcPoint = IpTunnelEndPoint.ipTunnelPoint(IpAddress
+ .valueOf(src));
+ dstPoint = IpTunnelEndPoint.ipTunnelPoint(IpAddress
+ .valueOf(dst));
+ } else if ("VLAN".equals(type)) {
+ String[] srcArray = src.split("/");
+ String[] dstArray = dst.split("/");
+ srcPoint = new DefaultOpticalTunnelEndPoint(
+ producerName,
+ Optional.of(DeviceId
+ .deviceId(srcArray[0])),
+ Optional.of(PortNumber
+ .portNumber(srcArray[1])),
+ null,
+ null,
+ OpticalLogicId
+ .logicId(0),
+ true);
+ dstPoint = new DefaultOpticalTunnelEndPoint(
+ producerName,
+ Optional.of(DeviceId
+ .deviceId(dstArray[0])),
+ Optional.of(PortNumber
+ .portNumber(dstArray[1])),
+ null,
+ null,
+ OpticalLogicId
+ .logicId(0),
+ true);
+ } else if ("ODUK".equals(type)) {
+ String[] srcArray = src.split("/");
+ String[] dstArray = dst.split("/");
+ srcPoint = new DefaultOpticalTunnelEndPoint(
+ producerName,
+ Optional.of(DeviceId
+ .deviceId(srcArray[0])),
+ Optional.of(PortNumber
+ .portNumber(srcArray[1])),
+ null,
+ OpticalTunnelEndPoint.Type.LAMBDA,
+ OpticalLogicId
+ .logicId(0),
+ true);
+ dstPoint = new DefaultOpticalTunnelEndPoint(
+ producerName,
+ Optional.of(DeviceId
+ .deviceId(dstArray[0])),
+ Optional.of(PortNumber
+ .portNumber(dstArray[1])),
+ null,
+ OpticalTunnelEndPoint.Type.LAMBDA,
+ OpticalLogicId
+ .logicId(0),
+ true);
+ } else if ("OCH".equals(type)) {
+ String[] srcArray = src.split("/");
+ String[] dstArray = dst.split("/");
+ srcPoint = new DefaultOpticalTunnelEndPoint(
+ producerName,
+ Optional.of(DeviceId
+ .deviceId(srcArray[0])),
+ Optional.of(PortNumber
+ .portNumber(srcArray[1])),
+ null,
+ OpticalTunnelEndPoint.Type.TIMESLOT,
+ OpticalLogicId
+ .logicId(0),
+ true);
+ dstPoint = new DefaultOpticalTunnelEndPoint(
+ producerName,
+ Optional.of(DeviceId
+ .deviceId(dstArray[0])),
+ Optional.of(PortNumber
+ .portNumber(dstArray[1])),
+ null,
+ OpticalTunnelEndPoint.Type.TIMESLOT,
+ OpticalLogicId
+ .logicId(0),
+ true);
+ } else {
+ print("Illegal tunnel type. Please input MPLS, VLAN, VXLAN, GRE, ODUK or OCH.");
+ return;
+ }
+ tunnelSet = service.queryTunnel(srcPoint, dstPoint);
+ }
+ if (!isNull(type)) {
+ if ("MPLS".equals(type)) {
+ trueType = Tunnel.Type.MPLS;
+ } else if ("VLAN".equals(type)) {
+ trueType = Tunnel.Type.VLAN;
+ } else if ("VXLAN".equals(type)) {
+ trueType = Tunnel.Type.VXLAN;
+ } else if ("GRE".equals(type)) {
+ trueType = Tunnel.Type.GRE;
+ } else if ("ODUK".equals(type)) {
+ trueType = Tunnel.Type.ODUK;
+ } else if ("OCH".equals(type)) {
+ trueType = Tunnel.Type.OCH;
+ } else {
+ print("Illegal tunnel type. Please input MPLS, VLAN, VXLAN, GRE, ODUK or OCH.");
+ return;
+ }
+ tunnelSet = service.queryTunnel(trueType);
+ }
+ if (!isNull(tunnelId)) {
+ TunnelId id = TunnelId.valueOf(tunnelId);
+ Tunnel tunnel = service.queryTunnel(id);
+ tunnelSet = new HashSet<Tunnel>();
+ tunnelSet.add(tunnel);
+ }
+ if (tunnelSet != null) {
+ for (Tunnel tunnel : tunnelSet) {
+ print(FMT, tunnel.tunnelId().id(), tunnel.src().toString(), tunnel.dst().toString(),
+ tunnel.type(), tunnel.state(), tunnel.providerId(),
+ tunnel.tunnelName(), tunnel.groupId(),
+ showPath(tunnel.path()),
+ annotations(tunnel.annotations()));
+ }
+ }
+ }
+
+ private String showPath(Path path) {
+ if (path == null) {
+ return "null";
+ }
+ StringBuilder builder = new StringBuilder("(");
+ for (Link link : path.links()) {
+ builder.append("(DeviceId:" + link.src().deviceId() + " Port:"
+ + link.src().port().toString());
+ builder.append(" DeviceId:" + link.dst().deviceId() + " Port:"
+ + link.dst().port().toString() + ")");
+ }
+ builder.append(annotations(path.annotations()) + ")");
+ return builder.toString();
+ }
+
+ private boolean isNull(String s) {
+ return s == null || "".equals(s);
+ }
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/TunnelQuerySubscriptionCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/TunnelQuerySubscriptionCommand.java
new file mode 100644
index 00000000..92db9268
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/TunnelQuerySubscriptionCommand.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2014-2015 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.cli.net;
+
+import java.util.Collection;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.DefaultApplicationId;
+import org.onosproject.incubator.net.tunnel.TunnelService;
+import org.onosproject.incubator.net.tunnel.TunnelSubscription;
+
+/**
+ * Query all tunnel subscriptions of consumer by consumer id.
+ * It's used by consumers.
+ */
+@Command(scope = "onos", name = "tunnel-subscriptions",
+ description = "Query all request orders of consumer by consumer id. It's used by consumers.")
+public class TunnelQuerySubscriptionCommand extends AbstractShellCommand {
+ @Argument(index = 0, name = "consumerId",
+ description = "consumer id means provider id",
+ required = true, multiValued = false)
+ String consumerId = null;
+ private static final String FMT = "appId=%s, src=%s, dst=%s,"
+ + "type=%s, tunnelId=%s";
+
+ @Override
+ protected void execute() {
+ TunnelService service = get(TunnelService.class);
+ ApplicationId applicationId = new DefaultApplicationId(1, consumerId);
+ Collection<TunnelSubscription> tunnelSet = service.queryTunnelSubscription(applicationId);
+ for (TunnelSubscription order : tunnelSet) {
+ print(FMT, order.consumerId(), order.src(), order.dst(),
+ order.type(), order.tunnelId());
+ }
+ }
+
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/TunnelRemoveCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/TunnelRemoveCommand.java
new file mode 100644
index 00000000..7d42c2d0
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/TunnelRemoveCommand.java
@@ -0,0 +1,203 @@
+/*
+ * Copyright 2014-2015 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.cli.net;
+
+import java.util.Collection;
+import java.util.Optional;
+
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.commands.Option;
+import org.onlab.packet.IpAddress;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.incubator.net.tunnel.DefaultOpticalTunnelEndPoint;
+import org.onosproject.incubator.net.tunnel.DefaultTunnelDescription;
+import org.onosproject.incubator.net.tunnel.IpTunnelEndPoint;
+import org.onosproject.incubator.net.tunnel.OpticalLogicId;
+import org.onosproject.incubator.net.tunnel.OpticalTunnelEndPoint;
+import org.onosproject.incubator.net.tunnel.Tunnel;
+import org.onosproject.incubator.net.tunnel.TunnelDescription;
+import org.onosproject.incubator.net.tunnel.TunnelEndPoint;
+import org.onosproject.incubator.net.tunnel.TunnelId;
+import org.onosproject.incubator.net.tunnel.TunnelProvider;
+import org.onosproject.incubator.net.tunnel.TunnelService;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.provider.ProviderId;
+
+/**
+ * Supports for removing tunnels. It's used by producers.
+ */
+@Command(scope = "onos", name = "tunnel-remove", description = "Supports for removing tunnels. It's used by producers.")
+public class TunnelRemoveCommand extends AbstractShellCommand {
+ @Option(name = "-s", aliases = "--src", description = "Source tunnel point."
+ + " Only supports for IpTunnelEndPoint and OpticalTunnelEndPoint as end point now."
+ + " If deletess a ODUK or OCH type tunnel, the formatter of this argument is DeviceId-PortNumber."
+ + " Otherwise src means IP address.", required = false, multiValued = false)
+ String src = null;
+ @Option(name = "-d", aliases = "--dst", description = "Destination tunnel point."
+ + " Only supports for IpTunnelEndPoint and OpticalTunnelEndPoint as end point now."
+ + " If deletess a ODUK or OCH type tunnel, the formatter of this argument is DeviceId-PortNumber."
+ + " Otherwise dst means IP address.", required = false, multiValued = false)
+ String dst = null;
+
+ @Option(name = "-t", aliases = "--type", description = "The type of tunnels,"
+ + " It includes MPLS, VLAN, VXLAN, GRE, ODUK, OCH", required = false, multiValued = false)
+ String type = null;
+
+ @Option(name = "-i", aliases = "--tunnelId",
+ description = "the tunnel identity.", required = false, multiValued = false)
+ String tunnelId = null;
+
+ @Override
+ protected void execute() {
+ TunnelDescription tunnel = null;
+ TunnelProvider service = get(TunnelProvider.class);
+ ProviderId producerName = new ProviderId("default",
+ "org.onosproject.provider.tunnel.default");
+ if (!isNull(src) && !isNull(dst) && !isNull(type)) {
+ TunnelEndPoint srcPoint = null;
+ TunnelEndPoint dstPoint = null;
+ Tunnel.Type trueType = null;
+ if ("MPLS".equals(type)) {
+ trueType = Tunnel.Type.MPLS;
+ srcPoint = IpTunnelEndPoint.ipTunnelPoint(IpAddress
+ .valueOf(src));
+ dstPoint = IpTunnelEndPoint.ipTunnelPoint(IpAddress
+ .valueOf(dst));
+ } else if ("VLAN".equals(type)) {
+ trueType = Tunnel.Type.VLAN;
+ srcPoint = IpTunnelEndPoint.ipTunnelPoint(IpAddress
+ .valueOf(src));
+ dstPoint = IpTunnelEndPoint.ipTunnelPoint(IpAddress
+ .valueOf(dst));
+ } else if ("VXLAN".equals(type)) {
+ trueType = Tunnel.Type.VXLAN;
+ srcPoint = IpTunnelEndPoint.ipTunnelPoint(IpAddress
+ .valueOf(src));
+ dstPoint = IpTunnelEndPoint.ipTunnelPoint(IpAddress
+ .valueOf(dst));
+ } else if ("GRE".equals(type)) {
+ trueType = Tunnel.Type.GRE;
+ srcPoint = IpTunnelEndPoint.ipTunnelPoint(IpAddress
+ .valueOf(src));
+ dstPoint = IpTunnelEndPoint.ipTunnelPoint(IpAddress
+ .valueOf(dst));
+ } else if ("ODUK".equals(type)) {
+ trueType = Tunnel.Type.ODUK;
+ String[] srcArray = src.split("/");
+ String[] dstArray = dst.split("/");
+ srcPoint = new DefaultOpticalTunnelEndPoint(
+ producerName,
+ Optional.of(DeviceId
+ .deviceId(srcArray[0])),
+ Optional.of(PortNumber
+ .portNumber(srcArray[1])),
+ null,
+ OpticalTunnelEndPoint.Type.LAMBDA,
+ OpticalLogicId
+ .logicId(0),
+ true);
+ dstPoint = new DefaultOpticalTunnelEndPoint(
+ producerName,
+ Optional.of(DeviceId
+ .deviceId(dstArray[0])),
+ Optional.of(PortNumber
+ .portNumber(dstArray[1])),
+ null,
+ OpticalTunnelEndPoint.Type.LAMBDA,
+ OpticalLogicId
+ .logicId(0),
+ true);
+ } else if ("OCH".equals(type)) {
+ trueType = Tunnel.Type.OCH;
+ String[] srcArray = src.split("/");
+ String[] dstArray = dst.split("/");
+ srcPoint = new DefaultOpticalTunnelEndPoint(
+ producerName,
+ Optional.of(DeviceId
+ .deviceId(srcArray[0])),
+ Optional.of(PortNumber
+ .portNumber(srcArray[1])),
+ null,
+ OpticalTunnelEndPoint.Type.LAMBDA,
+ OpticalLogicId
+ .logicId(0),
+ true);
+ dstPoint = new DefaultOpticalTunnelEndPoint(
+ producerName,
+ Optional.of(DeviceId
+ .deviceId(dstArray[0])),
+ Optional.of(PortNumber
+ .portNumber(dstArray[1])),
+ null,
+ OpticalTunnelEndPoint.Type.LAMBDA,
+ OpticalLogicId
+ .logicId(0),
+ true);
+ } else {
+ print("Illegal tunnel type. Please input MPLS, VLAN, VXLAN, GRE, ODUK or OCH.");
+ return;
+ }
+
+ tunnel = new DefaultTunnelDescription(null, srcPoint, dstPoint,
+ trueType, null, producerName,
+ null, null);
+ service.tunnelRemoved(tunnel);
+ return;
+ }
+ if (!isNull(tunnelId)) {
+ TunnelId id = TunnelId.valueOf(tunnelId);
+ tunnel = new DefaultTunnelDescription(id, null, null, null, null,
+ producerName, null, null);
+ service.tunnelRemoved(tunnel);
+ return;
+ }
+
+ if (!isNull(type)) {
+ Tunnel.Type trueType = null;
+ Collection<Tunnel> tunnelSet = null;
+ TunnelService tunnelService = get(TunnelService.class);
+ if ("MPLS".equals(type)) {
+ trueType = Tunnel.Type.MPLS;
+ } else if ("VLAN".equals(type)) {
+ trueType = Tunnel.Type.VLAN;
+ } else if ("VXLAN".equals(type)) {
+ trueType = Tunnel.Type.VXLAN;
+ } else if ("GRE".equals(type)) {
+ trueType = Tunnel.Type.GRE;
+ } else if ("ODUK".equals(type)) {
+ trueType = Tunnel.Type.ODUK;
+ } else if ("OCH".equals(type)) {
+ trueType = Tunnel.Type.OCH;
+ } else {
+ print("Illegal tunnel type. Please input MPLS, VLAN, VXLAN, GRE, ODUK or OCH.");
+ return;
+ }
+ tunnelSet = tunnelService.queryTunnel(trueType);
+ if (tunnelSet != null) {
+ for (Tunnel tunnelTemp : tunnelSet) {
+ tunnel = new DefaultTunnelDescription(tunnelTemp.tunnelId(), null, null, null, null,
+ producerName, null, null);
+ service.tunnelRemoved(tunnel);
+ }
+ }
+ }
+ }
+
+ private boolean isNull(String s) {
+ return s == null || "".equals(s);
+ }
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/TunnelReturnCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/TunnelReturnCommand.java
new file mode 100644
index 00000000..2b7d7bbd
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/TunnelReturnCommand.java
@@ -0,0 +1,198 @@
+/*
+ * Copyright 2014-2015 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.cli.net;
+
+import java.util.Optional;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.commands.Option;
+import org.onlab.packet.IpAddress;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.DefaultApplicationId;
+import org.onosproject.incubator.net.tunnel.DefaultOpticalTunnelEndPoint;
+import org.onosproject.incubator.net.tunnel.IpTunnelEndPoint;
+import org.onosproject.incubator.net.tunnel.OpticalLogicId;
+import org.onosproject.incubator.net.tunnel.OpticalTunnelEndPoint;
+import org.onosproject.incubator.net.tunnel.Tunnel;
+import org.onosproject.incubator.net.tunnel.TunnelEndPoint;
+import org.onosproject.incubator.net.tunnel.TunnelId;
+import org.onosproject.incubator.net.tunnel.TunnelName;
+import org.onosproject.incubator.net.tunnel.TunnelService;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.provider.ProviderId;
+
+/**
+ * Returns tunnels. It's used by consumers.
+ */
+@Command(scope = "onos", name = "tunnel-return",
+description = "Returns tunnels. It's used by consumers.")
+public class TunnelReturnCommand extends AbstractShellCommand {
+ @Argument(index = 0, name = "consumerId",
+ description = "consumer id means application id.", required = true, multiValued = false)
+ String consumerId = null;
+
+ @Option(name = "-s", aliases = "--src", description = "Source tunnel point."
+ + " Only supports for IpTunnelEndPoint and OpticalTunnelEndPoint as end point now."
+ + " If deletess a ODUK or OCH type tunnel, the formatter of this argument is DeviceId-PortNumber."
+ + " Otherwise src means IP address.", required = false, multiValued = false)
+ String src = null;
+
+ @Option(name = "-d", aliases = "--dst", description = "Destination tunnel point."
+ + " Only supports for IpTunnelEndPoint and OpticalTunnelEndPoint as end point now."
+ + " If deletess a ODUK or OCH type tunnel, the formatter of this argument is DeviceId-PortNumber."
+ + " Otherwise dst means IP address.", required = false, multiValued = false)
+ String dst = null;
+
+ @Option(name = "-t", aliases = "--type", description = "The type of tunnels,"
+ + " It includes MPLS, VLAN, VXLAN, GRE, ODUK, OCH", required = false, multiValued = false)
+ String type = null;
+
+ @Option(name = "-i", aliases = "--tunnelId",
+ description = "the tunnel identity.", required = false, multiValued = false)
+ String tunnelId = null;
+
+ @Option(name = "-n", aliases = "--tunnelName",
+ description = "The name of tunnels", required = false, multiValued = false)
+ String tunnelName = null;
+
+ @Override
+ protected void execute() {
+ Tunnel.Type trueType = null;
+ TunnelService service = get(TunnelService.class);
+ ApplicationId appId = new DefaultApplicationId(1, consumerId);
+ ProviderId producerName = new ProviderId("default",
+ "org.onosproject.provider.tunnel.default");
+ if (!isNull(src) && !isNull(dst) && !isNull(type)) {
+ TunnelEndPoint srcPoint = null;
+ TunnelEndPoint dstPoint = null;
+ if ("MPLS".equals(type)) {
+ trueType = Tunnel.Type.MPLS;
+ srcPoint = IpTunnelEndPoint.ipTunnelPoint(IpAddress
+ .valueOf(src));
+ dstPoint = IpTunnelEndPoint.ipTunnelPoint(IpAddress
+ .valueOf(dst));
+ } else if ("VXLAN".equals(type)) {
+ trueType = Tunnel.Type.VXLAN;
+ srcPoint = IpTunnelEndPoint.ipTunnelPoint(IpAddress
+ .valueOf(src));
+ dstPoint = IpTunnelEndPoint.ipTunnelPoint(IpAddress
+ .valueOf(dst));
+ } else if ("GRE".equals(type)) {
+ trueType = Tunnel.Type.GRE;
+ srcPoint = IpTunnelEndPoint.ipTunnelPoint(IpAddress
+ .valueOf(src));
+ dstPoint = IpTunnelEndPoint.ipTunnelPoint(IpAddress
+ .valueOf(dst));
+ } else if ("VLAN".equals(type)) {
+ trueType = Tunnel.Type.VLAN;
+ String[] srcArray = src.split("-");
+ String[] dstArray = dst.split("-");
+ srcPoint = new DefaultOpticalTunnelEndPoint(
+ producerName,
+ Optional.of(DeviceId
+ .deviceId(srcArray[0])),
+ Optional.of(PortNumber
+ .portNumber(srcArray[1])),
+ null,
+ null,
+ OpticalLogicId
+ .logicId(0),
+ true);
+ dstPoint = new DefaultOpticalTunnelEndPoint(
+ producerName,
+ Optional.of(DeviceId
+ .deviceId(dstArray[0])),
+ Optional.of(PortNumber
+ .portNumber(dstArray[1])),
+ null,
+ null,
+ OpticalLogicId
+ .logicId(0),
+ true);
+ } else if ("ODUK".equals(type)) {
+ trueType = Tunnel.Type.ODUK;
+ String[] srcArray = src.split("-");
+ String[] dstArray = dst.split("-");
+ srcPoint = new DefaultOpticalTunnelEndPoint(
+ producerName,
+ Optional.of(DeviceId
+ .deviceId(srcArray[0])),
+ Optional.of(PortNumber
+ .portNumber(srcArray[1])),
+ null,
+ OpticalTunnelEndPoint.Type.LAMBDA,
+ OpticalLogicId
+ .logicId(0),
+ true);
+ dstPoint = new DefaultOpticalTunnelEndPoint(
+ producerName,
+ Optional.of(DeviceId
+ .deviceId(dstArray[0])),
+ Optional.of(PortNumber
+ .portNumber(dstArray[1])),
+ null,
+ OpticalTunnelEndPoint.Type.LAMBDA,
+ OpticalLogicId
+ .logicId(0),
+ true);
+ } else if ("OCH".equals(type)) {
+ trueType = Tunnel.Type.OCH;
+ String[] srcArray = src.split("-");
+ String[] dstArray = dst.split("-");
+ srcPoint = new DefaultOpticalTunnelEndPoint(
+ producerName,
+ Optional.of(DeviceId
+ .deviceId(srcArray[0])),
+ Optional.of(PortNumber
+ .portNumber(srcArray[1])),
+ null,
+ OpticalTunnelEndPoint.Type.TIMESLOT,
+ OpticalLogicId
+ .logicId(0),
+ true);
+ dstPoint = new DefaultOpticalTunnelEndPoint(
+ producerName,
+ Optional.of(DeviceId
+ .deviceId(dstArray[0])),
+ Optional.of(PortNumber
+ .portNumber(dstArray[1])),
+ null,
+ OpticalTunnelEndPoint.Type.TIMESLOT,
+ OpticalLogicId
+ .logicId(0),
+ true);
+ } else {
+ print("Illegal tunnel type. Please input MPLS, VLAN, VXLAN, GRE, ODUK or OCH.");
+ return;
+ }
+ service.returnTunnel(appId, srcPoint, dstPoint, trueType);
+ }
+ if (!isNull(tunnelId)) {
+ TunnelId id = TunnelId.valueOf(tunnelId);
+ service.returnTunnel(appId, id);
+ }
+ if (!isNull(tunnelName)) {
+ TunnelName name = TunnelName.tunnelName(tunnelName);
+ service.returnTunnel(appId, name);
+ }
+ }
+ private boolean isNull(String s) {
+ return s == null || "".equals(s);
+ }
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/TunnelUpdateCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/TunnelUpdateCommand.java
new file mode 100644
index 00000000..d7065571
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/TunnelUpdateCommand.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2014-2015 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.cli.net;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.commands.Option;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.incubator.net.tunnel.DefaultTunnelDescription;
+import org.onosproject.incubator.net.tunnel.TunnelDescription;
+import org.onosproject.incubator.net.tunnel.TunnelId;
+import org.onosproject.incubator.net.tunnel.TunnelProvider;
+import org.onosproject.net.DefaultAnnotations;
+import org.onosproject.net.SparseAnnotations;
+
+/**
+ * Supports for updating a tunnel by tunnel identity.
+ * It's used by producers.
+ */
+@Command(scope = "onos", name = "tunnel-update",
+description = "Supports for updating a tunnel by tunnel identity."
+ + " It's used by producers.")
+public class TunnelUpdateCommand extends AbstractShellCommand {
+ @Argument(index = 0, name = "tunnelId", description = "the tunnel identity.",
+ required = true, multiValued = false)
+ String tunnelId = null;
+
+ @Option(name = "-b", aliases = "--bandwidth",
+ description = "The bandwidth attribute of tunnel", required = false, multiValued = false)
+ String bandwidth = null;
+
+ @Override
+ protected void execute() {
+ TunnelProvider service = get(TunnelProvider.class);
+ TunnelId id = TunnelId.valueOf(tunnelId);
+ SparseAnnotations annotations = DefaultAnnotations
+ .builder()
+ .set("bandwidth", bandwidth)
+ .build();
+ TunnelDescription tunnel = new DefaultTunnelDescription(id, null,
+ null,
+ null, null,
+ null,
+ null, null, annotations);
+ service.tunnelUpdated(tunnel);
+ }
+
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/WipeOutCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/WipeOutCommand.java
new file mode 100644
index 00000000..c842acff
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/WipeOutCommand.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2014-2015 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.cli.net;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.net.Device;
+import org.onosproject.net.Host;
+import org.onosproject.net.Link;
+import org.onosproject.net.device.DeviceAdminService;
+import org.onosproject.net.host.HostAdminService;
+import org.onosproject.net.intent.Intent;
+import org.onosproject.net.intent.IntentService;
+import org.onosproject.net.intent.IntentState;
+import org.onosproject.net.link.LinkAdminService;
+
+/**
+ * Wipes-out the entire network information base, i.e. devices, links, hosts, intents.
+ */
+@Command(scope = "onos", name = "wipe-out",
+ description = "Wipes-out the entire network information base, i.e. devices, links, hosts")
+public class WipeOutCommand extends ClustersListCommand {
+
+ private static final String PLEASE = "please";
+
+ @Argument(index = 0, name = "please", description = "Confirmation phrase",
+ required = false, multiValued = false)
+ String please = null;
+
+ @Override
+ protected void execute() {
+ if (please == null || !please.equals(PLEASE)) {
+ print("I'm afraid I can't do that!\nSay: %s", PLEASE);
+ return;
+ }
+
+ wipeOutIntents();
+ wipeOutHosts();
+ wipeOutDevices();
+ wipeOutLinks();
+ }
+
+ private void wipeOutIntents() {
+ print("Wiping intents");
+ IntentService intentService = get(IntentService.class);
+ for (Intent intent : intentService.getIntents()) {
+ if (intentService.getIntentState(intent.key()) != IntentState.WITHDRAWN) {
+ intentService.withdraw(intent);
+ }
+ intentService.purge(intent);
+ }
+ }
+
+ private void wipeOutHosts() {
+ print("Wiping hosts");
+ HostAdminService hostAdminService = get(HostAdminService.class);
+ while (hostAdminService.getHostCount() > 0) {
+ try {
+ for (Host host : hostAdminService.getHosts()) {
+ hostAdminService.removeHost(host.id());
+ }
+ } catch (Exception e) {
+ log.warn("Unable to wipe-out hosts", e);
+ }
+ }
+ }
+
+ private void wipeOutDevices() {
+ print("Wiping devices");
+ DeviceAdminService deviceAdminService = get(DeviceAdminService.class);
+ while (deviceAdminService.getDeviceCount() > 0) {
+ try {
+ for (Device device : deviceAdminService.getDevices()) {
+ deviceAdminService.removeDevice(device.id());
+ }
+ } catch (Exception e) {
+ log.warn("Unable to wipe-out devices", e);
+ }
+ }
+ }
+
+ private void wipeOutLinks() {
+ print("Wiping links");
+ LinkAdminService linkAdminService = get(LinkAdminService.class);
+ while (linkAdminService.getLinkCount() > 0) {
+ try {
+ for (Link link : linkAdminService.getLinks()) {
+ linkAdminService.removeLinks(link.src());
+ linkAdminService.removeLinks(link.dst());
+ }
+ } catch (Exception e) {
+ log.warn("Unable to wipe-out links", e);
+ }
+ }
+ }
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/package-info.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/package-info.java
new file mode 100644
index 00000000..fb4ba016
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/package-info.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2014 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.
+ */
+
+/**
+ * Administrative console command-line extensions for interacting with the
+ * network model &amp; services.
+ */
+package org.onosproject.cli.net;
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/package-info.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/package-info.java
new file mode 100644
index 00000000..4d9d3690
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2014 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.
+ */
+
+/**
+ * Administrative console command-line extensions.
+ */
+package org.onosproject.cli;
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/security/ReviewApplicationNameCompleter.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/security/ReviewApplicationNameCompleter.java
new file mode 100644
index 00000000..73744f3c
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/security/ReviewApplicationNameCompleter.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2015 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.cli.security;
+
+import org.apache.karaf.shell.console.completer.StringsCompleter;
+import org.onosproject.app.ApplicationService;
+import org.onosproject.app.ApplicationState;
+import org.onosproject.cli.AbstractCompleter;
+import org.onosproject.core.Application;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.SortedSet;
+
+import static org.onosproject.app.ApplicationState.INSTALLED;
+import static org.onosproject.cli.AbstractShellCommand.get;
+
+/**
+ * Application name completer for security review command.
+ */
+public class ReviewApplicationNameCompleter extends AbstractCompleter {
+ @Override
+ public int complete(String buffer, int cursor, List<String> candidates) {
+ // Delegate string completer
+ StringsCompleter delegate = new StringsCompleter();
+
+ ApplicationService service = get(ApplicationService.class);
+ Iterator<Application> it = service.getApplications().iterator();
+ SortedSet<String> strings = delegate.getStrings();
+ while (it.hasNext()) {
+ Application app = it.next();
+ ApplicationState state = service.getState(app.id());
+// if (previousApps.contains(app.id().name())) {
+// continue;
+// }
+ if (state == INSTALLED) {
+ strings.add(app.id().name());
+ }
+ }
+
+ // Now let the completer do the work for figuring out what to offer.
+ return delegate.complete(buffer, cursor, candidates);
+ }
+} \ No newline at end of file
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/security/ReviewCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/security/ReviewCommand.java
new file mode 100644
index 00000000..9d17eb23
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/security/ReviewCommand.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2015 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.cli.security;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.app.ApplicationAdminService;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.core.Application;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.security.SecurityAdminService;
+import org.onosproject.security.SecurityUtil;
+
+import java.security.Permission;
+import java.util.List;
+import java.util.Map;
+
+
+/**
+ * Application security policy review commands.
+ */
+@Command(scope = "onos", name = "review",
+ description = "Application security policy review interface")
+public class ReviewCommand extends AbstractShellCommand {
+
+ @Argument(index = 0, name = "name", description = "Application name",
+ required = true, multiValued = false)
+ String name = null;
+
+ @Argument(index = 1, name = "accept", description = "Option to accept policy",
+ required = false, multiValued = false)
+ String accept = null;
+
+ @Override
+ protected void execute() {
+ ApplicationAdminService applicationAdminService = get(ApplicationAdminService.class);
+ ApplicationId appId = applicationAdminService.getId(name);
+ if (appId == null) {
+ print("No such application: %s", name);
+ return;
+ }
+ Application app = applicationAdminService.getApplication(appId);
+ SecurityAdminService smService = SecurityUtil.getSecurityService();
+ if (smService == null) {
+ print("Security Mode is disabled");
+ return;
+ }
+ if (accept == null) {
+ smService.review(appId);
+ printPolicy(smService, app);
+ } else if (accept.trim().equals("accept")) {
+ smService.acceptPolicy(appId);
+ printPolicy(smService, app);
+ } else {
+ print("Unknown command");
+ }
+ }
+
+ private void printPolicy(SecurityAdminService smService, Application app) {
+ print("\n*******************************");
+ print(" SM-ONOS APP REVIEW ");
+ print("*******************************");
+
+ print("Application name: %s ", app.id().name());
+ print("Application role: " + app.role());
+ print("\nDeveloper specified permissions: ");
+ printMap(smService.getPrintableSpecifiedPermissions(app.id()));
+ print("\nPermissions granted: ");
+ printMap(smService.getPrintableGrantedPermissions(app.id()));
+ print("\nAdditional permissions requested on runtime (POLICY VIOLATIONS): ");
+ printMap(smService.getPrintableRequestedPermissions(app.id()));
+ print("");
+
+ }
+ private void printMap(Map<Integer, List<Permission>> assortedMap) {
+ for (Integer type : assortedMap.keySet()) {
+ switch (type) {
+ case 0:
+ for (Permission perm: assortedMap.get(0)) {
+ print("\t[APP PERMISSION] " + perm.getName());
+ }
+ break;
+ case 1:
+ for (Permission perm: assortedMap.get(1)) {
+ print("\t[NB-ADMIN SERVICE] " + perm.getName() + "(" + perm.getActions() + ")");
+ }
+ break;
+ case 2:
+ for (Permission perm: assortedMap.get(2)) {
+ print("\t[NB SERVICE] " + perm.getName() + "(" + perm.getActions() + ")");
+ }
+ break;
+ case 3:
+ for (Permission perm: assortedMap.get(3)) {
+ print("\t[Other SERVICE] " + perm.getName() + "(" + perm.getActions() + ")");
+ }
+ break;
+ case 4:
+ for (Permission perm: assortedMap.get(4)) {
+ print("\t[Other] " + perm.getClass().getSimpleName() +
+ " " + perm.getName() + " (" + perm.getActions() + ")");
+ }
+ default:
+ break;
+ }
+ }
+ }
+}
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/security/package-info.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/security/package-info.java
new file mode 100644
index 00000000..e634edab
--- /dev/null
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/security/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2015 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 commands for managing security permissions.
+ */
+package org.onosproject.cli.security; \ No newline at end of file