Add ability to remove patches
Change-Id: Ia777213f4e1a5c3f7b3b583b932dfea7590076f1
diff --git a/apps/patchpanel/src/main/java/org/onosproject/patchpanel/cli/PatchListCommand.java b/apps/patchpanel/src/main/java/org/onosproject/patchpanel/cli/PatchListCommand.java
new file mode 100644
index 0000000..9d8f088
--- /dev/null
+++ b/apps/patchpanel/src/main/java/org/onosproject/patchpanel/cli/PatchListCommand.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * This class defines the cli command for the PatchPanel class. It creates
+ * an instance of the PatchPanelService class to call it's method addPatch().
+ * The command takes 2 parameters, 2 connectPoints.
+ */
+package org.onosproject.patchpanel.cli;
+
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.patchpanel.impl.Patch;
+import org.onosproject.patchpanel.impl.PatchPanelService;
+
+/**
+ * Lists the patches.
+ */
+@Command(scope = "onos", name = "patches",
+ description = "Lists the patches")
+public class PatchListCommand extends AbstractShellCommand {
+
+ private static final String FORMAT = "%s: %s <-> %s";
+
+ @Override
+ protected void execute() {
+ PatchPanelService patchPanelService = get(PatchPanelService.class);
+
+ patchPanelService.getPatches().forEach(this::print);
+ }
+
+ private void print(Patch patch) {
+ print(FORMAT, patch.id(), patch.port1(), patch.port2());
+ }
+
+}
diff --git a/apps/patchpanel/src/main/java/org/onosproject/patchpanel/cli/PatchRemoveCommand.java b/apps/patchpanel/src/main/java/org/onosproject/patchpanel/cli/PatchRemoveCommand.java
new file mode 100644
index 0000000..429cd50
--- /dev/null
+++ b/apps/patchpanel/src/main/java/org/onosproject/patchpanel/cli/PatchRemoveCommand.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * This class defines the cli command for the PatchPanel class. It creates
+ * an instance of the PatchPanelService class to call it's method addPatch().
+ * The command takes 2 parameters, 2 connectPoints.
+ */
+package org.onosproject.patchpanel.cli;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.patchpanel.impl.PatchId;
+import org.onosproject.patchpanel.impl.PatchPanelService;
+
+/**
+ * Removes a patch.
+ */
+@Command(scope = "onos", name = "patch-remove",
+ description = "Removes a patch")
+public class PatchRemoveCommand extends AbstractShellCommand {
+
+ @Argument(index = 0, name = "patchId", description = "ID of patch to remove",
+ required = true, multiValued = false)
+ String id = null;
+
+ private PatchPanelService patchPanelService;
+
+ @Override
+ protected void execute() {
+ patchPanelService = get(PatchPanelService.class);
+ boolean done = false;
+
+ PatchId patchId = PatchId.patchId(Integer.parseInt(id));
+
+ done = patchPanelService.removePatch(patchId);
+
+ if (done) {
+ log.info("This patch has been removed");
+ } else {
+ log.info("This patch was NOT removed");
+ }
+
+ }
+
+}
diff --git a/apps/patchpanel/src/main/java/org/onosproject/patchpanel/impl/Patch.java b/apps/patchpanel/src/main/java/org/onosproject/patchpanel/impl/Patch.java
new file mode 100644
index 0000000..3b1c821
--- /dev/null
+++ b/apps/patchpanel/src/main/java/org/onosproject/patchpanel/impl/Patch.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.patchpanel.impl;
+
+import org.onosproject.net.ConnectPoint;
+
+/**
+ * Abstraction of a patch between two ports on a switch.
+ */
+public class Patch {
+
+ private final PatchId patchId;
+ private final ConnectPoint port1;
+ private final ConnectPoint port2;
+
+ /**
+ * Creates a new patch.
+ *
+ * @param patchId patch ID
+ * @param port1 first switch port
+ * @param port2 second switch port
+ */
+ public Patch(PatchId patchId, ConnectPoint port1, ConnectPoint port2) {
+ this.patchId = patchId;
+ this.port1 = port1;
+ this.port2 = port2;
+ }
+
+ /**
+ * Gets the patch ID.
+ *
+ * @return patch ID
+ */
+ public PatchId id() {
+ return patchId;
+ }
+
+ /**
+ * Gets the first connect point.
+ *
+ * @return connect point
+ */
+ public ConnectPoint port1() {
+ return port1;
+ }
+
+ /**
+ * Gets the second connect point.
+ *
+ * @return connect point
+ */
+ public ConnectPoint port2() {
+ return port2;
+ }
+}
diff --git a/apps/patchpanel/src/main/java/org/onosproject/patchpanel/impl/PatchId.java b/apps/patchpanel/src/main/java/org/onosproject/patchpanel/impl/PatchId.java
new file mode 100644
index 0000000..d40cb21
--- /dev/null
+++ b/apps/patchpanel/src/main/java/org/onosproject/patchpanel/impl/PatchId.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.patchpanel.impl;
+
+import org.onlab.util.Identifier;
+
+/**
+ * Identifier of a patch.
+ */
+public final class PatchId extends Identifier<Integer> {
+
+ private PatchId(int id) {
+ super(id);
+ }
+
+ /**
+ * Creates a new patch based of an integer.
+ *
+ * @param id backing value
+ * @return patch ID
+ */
+ public static PatchId patchId(int id) {
+ return new PatchId(id);
+ }
+}
diff --git a/apps/patchpanel/src/main/java/org/onosproject/patchpanel/impl/PatchPanel.java b/apps/patchpanel/src/main/java/org/onosproject/patchpanel/impl/PatchPanel.java
index b08be7e..e10b097 100644
--- a/apps/patchpanel/src/main/java/org/onosproject/patchpanel/impl/PatchPanel.java
+++ b/apps/patchpanel/src/main/java/org/onosproject/patchpanel/impl/PatchPanel.java
@@ -16,27 +16,37 @@
package org.onosproject.patchpanel.impl;
-import org.apache.felix.scr.annotations.Component;
-import org.apache.felix.scr.annotations.Reference;
-import org.apache.felix.scr.annotations.Service;
-import org.apache.felix.scr.annotations.ReferenceCardinality;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.apache.felix.scr.annotations.Service;
import org.onosproject.cli.net.ConnectPointCompleter;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DeviceId;
import org.onosproject.net.PortNumber;
import org.onosproject.net.flow.DefaultFlowRule;
-import org.onosproject.net.flow.FlowRuleService;
-import org.onosproject.net.flow.FlowRule;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.DefaultTrafficTreatment;
+import org.onosproject.net.flow.FlowRule;
+import org.onosproject.net.flow.FlowRuleService;
import org.onosproject.net.packet.PacketPriority;
-import org.onosproject.net.ConnectPoint;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.util.ArrayList;
-import java.util.List;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
/**
* This class acts as a software patch panel application.
@@ -47,6 +57,8 @@
@Service
public class PatchPanel implements PatchPanelService {
+ private final Logger log = LoggerFactory.getLogger(getClass());
+
// OSGI: help bundle plugin discover runtime package dependency.
@SuppressWarnings("unused")
private ConnectPointCompleter connectPointCompleter;
@@ -57,14 +69,17 @@
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected CoreService coreService;
- private List<ConnectPoint> previous = new ArrayList<>();
- private final Logger log = LoggerFactory.getLogger(getClass());
+ private Map<PatchId, Patch> patches;
+
private ApplicationId appId;
- private ConnectPoint cp1, cp2;
+
+ private AtomicInteger ids = new AtomicInteger();
@Activate
protected void activate() throws NullPointerException {
+ patches = new HashMap<>();
+
appId = coreService.registerApplication("org.onosproject.patchpanel");
log.info("Started");
}
@@ -75,25 +90,60 @@
}
@Override
- public boolean addPatch(ConnectPoint num, ConnectPoint num2) {
- cp1 = num;
- cp2 = num2;
- if ((cp1.port().equals(cp2.port())) || (previous.contains(cp1) || previous.contains(cp2))) {
+ public boolean addPatch(ConnectPoint cp1, ConnectPoint cp2) {
+ checkNotNull(cp1);
+ checkNotNull(cp2);
+
+ checkArgument(cp1.deviceId().equals(cp2.deviceId()), "Ports must be on the same device");
+ checkArgument(!cp1.equals(cp2), "Ports cannot be the same");
+
+ if (patches.values().stream()
+ .filter(patch -> patch.port1().equals(cp1) || patch.port1().equals(cp2)
+ || patch.port2().equals(cp1) || patch.port2().equals(cp2))
+ .findAny().isPresent()) {
log.info("One or both of these ports are already in use, NO FLOW");
return false;
- } else {
- previous.add(cp1);
- previous.add(cp2);
- setFlowRuleService();
- return true;
}
+
+ Patch patch = new Patch(PatchId.patchId(ids.incrementAndGet()), cp1, cp2);
+
+ patches.put(patch.id(), patch);
+
+ setFlowRuleService(patch);
+
+ return true;
}
- public void setFlowRuleService() {
- PortNumber outPort = cp2.port();
- PortNumber inPort = cp1.port();
+ @Override
+ public boolean removePatch(PatchId id) {
+ Patch patch = patches.remove(id);
+ if (patch == null) {
+ return false;
+ }
+
+ removePatchFlows(patch);
+ return true;
+ }
+
+ @Override
+ public Set<Patch> getPatches() {
+ return ImmutableSet.copyOf(patches.values());
+ }
+
+ public void setFlowRuleService(Patch patch) {
+ createFlowRules(patch).forEach(flowRuleService::applyFlowRules);
+ }
+
+ private void removePatchFlows(Patch patch) {
+ createFlowRules(patch).forEach(flowRuleService::removeFlowRules);
+ }
+
+ private Collection<FlowRule> createFlowRules(Patch patch) {
+ DeviceId deviceId = patch.port1().deviceId();
+ PortNumber outPort = patch.port2().port();
+ PortNumber inPort = patch.port1().port();
FlowRule fr = DefaultFlowRule.builder()
- .forDevice(cp1.deviceId())
+ .forDevice(deviceId)
.withSelector(DefaultTrafficSelector.builder().matchInPort(inPort).build())
.withTreatment(DefaultTrafficTreatment.builder().setOutput(outPort).build())
.withPriority(PacketPriority.REACTIVE.priorityValue())
@@ -101,15 +151,13 @@
.fromApp(appId).build();
FlowRule fr2 = DefaultFlowRule.builder()
- .forDevice(cp1.deviceId())
+ .forDevice(deviceId)
.withSelector(DefaultTrafficSelector.builder().matchInPort(outPort).build())
.withTreatment(DefaultTrafficTreatment.builder().setOutput(inPort).build())
.withPriority(PacketPriority.REACTIVE.priorityValue())
.makePermanent()
.fromApp(appId).build();
- flowRuleService.applyFlowRules(fr, fr2);
-
+ return ImmutableList.of(fr, fr2);
}
-
}
diff --git a/apps/patchpanel/src/main/java/org/onosproject/patchpanel/impl/PatchPanelService.java b/apps/patchpanel/src/main/java/org/onosproject/patchpanel/impl/PatchPanelService.java
index affb6a5..4ece312 100644
--- a/apps/patchpanel/src/main/java/org/onosproject/patchpanel/impl/PatchPanelService.java
+++ b/apps/patchpanel/src/main/java/org/onosproject/patchpanel/impl/PatchPanelService.java
@@ -15,8 +15,11 @@
*/
package org.onosproject.patchpanel.impl;
+
import org.onosproject.net.ConnectPoint;
+import java.util.Set;
+
/**
* A service for the patch panel application to export and use with the cli.
*/
@@ -30,4 +33,19 @@
* @return true if the patch was created, false otherwise
*/
boolean addPatch(ConnectPoint cp, ConnectPoint cp2);
+
+ /**
+ * Removes an existing patch.
+ *
+ * @param id patch ID
+ * @return true if the patch was removed, otherwise false.
+ */
+ boolean removePatch(PatchId id);
+
+ /**
+ * Gets the set of patches in the system.
+ *
+ * @return set of patches
+ */
+ Set<Patch> getPatches();
}
diff --git a/apps/patchpanel/src/main/resources/OSGI-INF/blueprint/shell-config.xml b/apps/patchpanel/src/main/resources/OSGI-INF/blueprint/shell-config.xml
index b881168..1db5a5d 100644
--- a/apps/patchpanel/src/main/resources/OSGI-INF/blueprint/shell-config.xml
+++ b/apps/patchpanel/src/main/resources/OSGI-INF/blueprint/shell-config.xml
@@ -21,6 +21,12 @@
<ref component-id="ConnectPointCompleter"/>
</completers>
</command>
+ <command>
+ <action class="org.onosproject.patchpanel.cli.PatchRemoveCommand"/>
+ </command>
+ <command>
+ <action class="org.onosproject.patchpanel.cli.PatchListCommand"/>
+ </command>
</command-bundle>
<bean id="ConnectPointCompleter" class="org.onosproject.cli.net.ConnectPointCompleter"/>
</blueprint>