Committed by
Gerrit Code Review
Add basic ability to add and remove interfaces
Change-Id: I11fd764304a4e7ab298336f3033a4417ba4be28d
Showing
6 changed files
with
290 additions
and
11 deletions
1 | +/* | ||
2 | + * Copyright 2015 Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | + | ||
17 | +package org.onosproject.cli.net; | ||
18 | + | ||
19 | +import com.google.common.collect.Sets; | ||
20 | +import org.apache.karaf.shell.commands.Command; | ||
21 | +import org.apache.karaf.shell.commands.Option; | ||
22 | +import org.onlab.packet.MacAddress; | ||
23 | +import org.onlab.packet.VlanId; | ||
24 | +import org.onosproject.cli.AbstractShellCommand; | ||
25 | +import org.onosproject.incubator.net.intf.Interface; | ||
26 | +import org.onosproject.incubator.net.intf.InterfaceAdminService; | ||
27 | +import org.onosproject.net.ConnectPoint; | ||
28 | +import org.onosproject.net.host.InterfaceIpAddress; | ||
29 | + | ||
30 | +import java.util.Set; | ||
31 | + | ||
32 | +/** | ||
33 | + * Adds a new interface configuration. | ||
34 | + */ | ||
35 | +@Command(scope = "onos", name = "add-interface", | ||
36 | + description = "Adds a new configured interface") | ||
37 | +public class InterfaceAddCommand extends AbstractShellCommand { | ||
38 | + | ||
39 | + @Option(name = "-c", aliases = "--connectPoint", | ||
40 | + description = "Device port that the interface is associated with", | ||
41 | + required = true, multiValued = false) | ||
42 | + private String connectPoint = null; | ||
43 | + | ||
44 | + @Option(name = "-m", aliases = "--mac", | ||
45 | + description = "MAC address of the interface", | ||
46 | + required = true, multiValued = false) | ||
47 | + private String mac = null; | ||
48 | + | ||
49 | + @Option(name = "-i", aliases = "--ip", | ||
50 | + description = "IP address configured on the interface\n" + | ||
51 | + "(e.g. 10.0.1.1/24). Can be specified multiple times.", | ||
52 | + required = false, multiValued = true) | ||
53 | + private String[] ips = null; | ||
54 | + | ||
55 | + @Option(name = "-v", aliases = "--vlan", | ||
56 | + description = "VLAN configured on the interface", | ||
57 | + required = false, multiValued = false) | ||
58 | + private String vlan = null; | ||
59 | + | ||
60 | + @Override | ||
61 | + protected void execute() { | ||
62 | + InterfaceAdminService interfaceService = get(InterfaceAdminService.class); | ||
63 | + | ||
64 | + Set<InterfaceIpAddress> ipAddresses = Sets.newHashSet(); | ||
65 | + if (ips != null) { | ||
66 | + for (String strIp : ips) { | ||
67 | + ipAddresses.add(InterfaceIpAddress.valueOf(strIp)); | ||
68 | + } | ||
69 | + } | ||
70 | + | ||
71 | + VlanId vlanId = vlan == null ? VlanId.NONE : VlanId.vlanId(Short.parseShort(vlan)); | ||
72 | + | ||
73 | + Interface intf = new Interface(ConnectPoint.deviceConnectPoint(connectPoint), | ||
74 | + ipAddresses, MacAddress.valueOf(mac), vlanId); | ||
75 | + | ||
76 | + interfaceService.add(intf); | ||
77 | + } | ||
78 | + | ||
79 | +} |
1 | +/* | ||
2 | + * Copyright 2015 Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | + | ||
17 | +package org.onosproject.cli.net; | ||
18 | + | ||
19 | +import org.apache.karaf.shell.commands.Argument; | ||
20 | +import org.apache.karaf.shell.commands.Command; | ||
21 | +import org.onlab.packet.VlanId; | ||
22 | +import org.onosproject.cli.AbstractShellCommand; | ||
23 | +import org.onosproject.incubator.net.intf.InterfaceAdminService; | ||
24 | +import org.onosproject.net.ConnectPoint; | ||
25 | + | ||
26 | +/** | ||
27 | + * Removes an interface configuration. | ||
28 | + */ | ||
29 | +@Command(scope = "onos", name = "remove-interface", | ||
30 | + description = "Removes a configured interface") | ||
31 | +public class InterfaceRemoveCommand extends AbstractShellCommand { | ||
32 | + | ||
33 | + @Argument(index = 0, name = "connectPoint", | ||
34 | + description = "Connect point of the interface", | ||
35 | + required = true, multiValued = false) | ||
36 | + private String connectPoint = null; | ||
37 | + | ||
38 | + @Argument(index = 1, name = "vlan", | ||
39 | + description = "Interface vlan", | ||
40 | + required = true, multiValued = false) | ||
41 | + private String vlan = null; | ||
42 | + | ||
43 | + @Override | ||
44 | + protected void execute() { | ||
45 | + InterfaceAdminService interfaceService = get(InterfaceAdminService.class); | ||
46 | + | ||
47 | + interfaceService.remove(ConnectPoint.deviceConnectPoint(connectPoint), | ||
48 | + VlanId.vlanId(Short.parseShort(vlan))); | ||
49 | + } | ||
50 | + | ||
51 | +} |
... | @@ -352,6 +352,19 @@ | ... | @@ -352,6 +352,19 @@ |
352 | <action class="org.onosproject.cli.net.InterfacesListCommand"/> | 352 | <action class="org.onosproject.cli.net.InterfacesListCommand"/> |
353 | </command> | 353 | </command> |
354 | <command> | 354 | <command> |
355 | + <action class="org.onosproject.cli.net.InterfaceAddCommand"/> | ||
356 | + <optional-completers> | ||
357 | + <entry key="-c" value-ref="connectPointCompleter"/> | ||
358 | + <entry key="--connectPoint" value-ref="connectPointCompleter"/> | ||
359 | + </optional-completers> | ||
360 | + </command> | ||
361 | + <command> | ||
362 | + <action class="org.onosproject.cli.net.InterfaceRemoveCommand"/> | ||
363 | + <completers> | ||
364 | + <ref component-id="connectPointCompleter"/> | ||
365 | + </completers> | ||
366 | + </command> | ||
367 | + <command> | ||
355 | <action class="org.onosproject.cli.net.GroupsListCommand"/> | 368 | <action class="org.onosproject.cli.net.GroupsListCommand"/> |
356 | </command> | 369 | </command> |
357 | 370 | ... | ... |
... | @@ -17,13 +17,15 @@ | ... | @@ -17,13 +17,15 @@ |
17 | package org.onosproject.incubator.net.config.basics; | 17 | package org.onosproject.incubator.net.config.basics; |
18 | 18 | ||
19 | import com.fasterxml.jackson.databind.JsonNode; | 19 | import com.fasterxml.jackson.databind.JsonNode; |
20 | +import com.fasterxml.jackson.databind.node.ArrayNode; | ||
21 | +import com.fasterxml.jackson.databind.node.ObjectNode; | ||
20 | import com.google.common.annotations.Beta; | 22 | import com.google.common.annotations.Beta; |
21 | import com.google.common.collect.Sets; | 23 | import com.google.common.collect.Sets; |
22 | import org.onlab.packet.MacAddress; | 24 | import org.onlab.packet.MacAddress; |
23 | import org.onlab.packet.VlanId; | 25 | import org.onlab.packet.VlanId; |
24 | -import org.onosproject.net.config.Config; | ||
25 | import org.onosproject.incubator.net.intf.Interface; | 26 | import org.onosproject.incubator.net.intf.Interface; |
26 | import org.onosproject.net.ConnectPoint; | 27 | import org.onosproject.net.ConnectPoint; |
28 | +import org.onosproject.net.config.Config; | ||
27 | import org.onosproject.net.host.InterfaceIpAddress; | 29 | import org.onosproject.net.host.InterfaceIpAddress; |
28 | 30 | ||
29 | import java.util.Set; | 31 | import java.util.Set; |
... | @@ -37,7 +39,6 @@ public class InterfaceConfig extends Config<ConnectPoint> { | ... | @@ -37,7 +39,6 @@ public class InterfaceConfig extends Config<ConnectPoint> { |
37 | public static final String MAC = "mac"; | 39 | public static final String MAC = "mac"; |
38 | public static final String VLAN = "vlan"; | 40 | public static final String VLAN = "vlan"; |
39 | 41 | ||
40 | - public static final String IP_MISSING_ERROR = "Must have at least one IP address"; | ||
41 | public static final String MAC_MISSING_ERROR = "Must have a MAC address for each interface"; | 42 | public static final String MAC_MISSING_ERROR = "Must have a MAC address for each interface"; |
42 | public static final String CONFIG_VALUE_ERROR = "Error parsing config value"; | 43 | public static final String CONFIG_VALUE_ERROR = "Error parsing config value"; |
43 | 44 | ||
... | @@ -53,9 +54,6 @@ public class InterfaceConfig extends Config<ConnectPoint> { | ... | @@ -53,9 +54,6 @@ public class InterfaceConfig extends Config<ConnectPoint> { |
53 | try { | 54 | try { |
54 | for (JsonNode intfNode : array) { | 55 | for (JsonNode intfNode : array) { |
55 | Set<InterfaceIpAddress> ips = getIps(intfNode); | 56 | Set<InterfaceIpAddress> ips = getIps(intfNode); |
56 | - if (ips.isEmpty()) { | ||
57 | - throw new ConfigException(IP_MISSING_ERROR); | ||
58 | - } | ||
59 | 57 | ||
60 | if (intfNode.path(MAC).isMissingNode()) { | 58 | if (intfNode.path(MAC).isMissingNode()) { |
61 | throw new ConfigException(MAC_MISSING_ERROR); | 59 | throw new ConfigException(MAC_MISSING_ERROR); |
... | @@ -63,10 +61,7 @@ public class InterfaceConfig extends Config<ConnectPoint> { | ... | @@ -63,10 +61,7 @@ public class InterfaceConfig extends Config<ConnectPoint> { |
63 | 61 | ||
64 | MacAddress mac = MacAddress.valueOf(intfNode.path(MAC).asText()); | 62 | MacAddress mac = MacAddress.valueOf(intfNode.path(MAC).asText()); |
65 | 63 | ||
66 | - VlanId vlan = VlanId.NONE; | 64 | + VlanId vlan = getVlan(intfNode); |
67 | - if (!intfNode.path(VLAN).isMissingNode()) { | ||
68 | - vlan = VlanId.vlanId(Short.valueOf(intfNode.path(VLAN).asText())); | ||
69 | - } | ||
70 | 65 | ||
71 | interfaces.add(new Interface(subject, ips, mac, vlan)); | 66 | interfaces.add(new Interface(subject, ips, mac, vlan)); |
72 | } | 67 | } |
... | @@ -77,13 +72,64 @@ public class InterfaceConfig extends Config<ConnectPoint> { | ... | @@ -77,13 +72,64 @@ public class InterfaceConfig extends Config<ConnectPoint> { |
77 | return interfaces; | 72 | return interfaces; |
78 | } | 73 | } |
79 | 74 | ||
75 | + /** | ||
76 | + * Adds an interface to the config. | ||
77 | + * | ||
78 | + * @param intf interface to add | ||
79 | + */ | ||
80 | + public void addInterface(Interface intf) { | ||
81 | + ObjectNode intfNode = array.addObject(); | ||
82 | + intfNode.put(MAC, intf.mac().toString()); | ||
83 | + | ||
84 | + if (!intf.ipAddresses().isEmpty()) { | ||
85 | + intfNode.set(IPS, putIps(intf.ipAddresses())); | ||
86 | + } | ||
87 | + | ||
88 | + if (!intf.vlan().equals(VlanId.NONE)) { | ||
89 | + intfNode.put(VLAN, intf.vlan().toString()); | ||
90 | + } | ||
91 | + } | ||
92 | + | ||
93 | + /** | ||
94 | + * Removes an interface from the config. | ||
95 | + * | ||
96 | + * @param intf interface to remove | ||
97 | + */ | ||
98 | + public void removeInterface(Interface intf) { | ||
99 | + for (int i = 0; i < array.size(); i++) { | ||
100 | + if (intf.vlan().equals(getVlan(node))) { | ||
101 | + array.remove(i); | ||
102 | + break; | ||
103 | + } | ||
104 | + } | ||
105 | + } | ||
106 | + | ||
107 | + private VlanId getVlan(JsonNode node) { | ||
108 | + VlanId vlan = VlanId.NONE; | ||
109 | + if (!node.path(VLAN).isMissingNode()) { | ||
110 | + vlan = VlanId.vlanId(Short.valueOf(node.path(VLAN).asText())); | ||
111 | + } | ||
112 | + return vlan; | ||
113 | + } | ||
114 | + | ||
80 | private Set<InterfaceIpAddress> getIps(JsonNode node) { | 115 | private Set<InterfaceIpAddress> getIps(JsonNode node) { |
81 | Set<InterfaceIpAddress> ips = Sets.newHashSet(); | 116 | Set<InterfaceIpAddress> ips = Sets.newHashSet(); |
82 | 117 | ||
83 | JsonNode ipsNode = node.get(IPS); | 118 | JsonNode ipsNode = node.get(IPS); |
84 | - ipsNode.forEach(jsonNode -> ips.add(InterfaceIpAddress.valueOf(jsonNode.asText()))); | 119 | + if (ipsNode != null) { |
120 | + ipsNode.forEach(jsonNode -> | ||
121 | + ips.add(InterfaceIpAddress.valueOf(jsonNode.asText()))); | ||
122 | + } | ||
85 | 123 | ||
86 | return ips; | 124 | return ips; |
87 | } | 125 | } |
88 | 126 | ||
127 | + private ArrayNode putIps(Set<InterfaceIpAddress> intfIpAddresses) { | ||
128 | + ArrayNode ipArray = mapper.createArrayNode(); | ||
129 | + | ||
130 | + intfIpAddresses.forEach(i -> ipArray.add(i.toString())); | ||
131 | + | ||
132 | + return ipArray; | ||
133 | + } | ||
134 | + | ||
89 | } | 135 | } | ... | ... |
incubator/api/src/main/java/org/onosproject/incubator/net/intf/InterfaceAdminService.java
0 → 100644
1 | +/* | ||
2 | + * Copyright 2015 Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | + | ||
17 | +package org.onosproject.incubator.net.intf; | ||
18 | + | ||
19 | +import org.onlab.packet.VlanId; | ||
20 | +import org.onosproject.net.ConnectPoint; | ||
21 | + | ||
22 | +/** | ||
23 | + * Provides a means to modify the interfaces configuration. | ||
24 | + */ | ||
25 | +public interface InterfaceAdminService { | ||
26 | + /** | ||
27 | + * Adds a new interface configuration to the system. | ||
28 | + * | ||
29 | + * @param intf interface to add | ||
30 | + */ | ||
31 | + void add(Interface intf); | ||
32 | + | ||
33 | + /** | ||
34 | + * Removes an interface configuration from the system. | ||
35 | + * | ||
36 | + * @param connectPoint connect point of the interface | ||
37 | + * @param vlanId vlan id | ||
38 | + */ | ||
39 | + void remove(ConnectPoint connectPoint, VlanId vlanId); | ||
40 | +} |
... | @@ -29,6 +29,7 @@ import org.onlab.packet.VlanId; | ... | @@ -29,6 +29,7 @@ import org.onlab.packet.VlanId; |
29 | import org.onosproject.incubator.net.config.basics.ConfigException; | 29 | import org.onosproject.incubator.net.config.basics.ConfigException; |
30 | import org.onosproject.incubator.net.config.basics.InterfaceConfig; | 30 | import org.onosproject.incubator.net.config.basics.InterfaceConfig; |
31 | import org.onosproject.incubator.net.intf.Interface; | 31 | import org.onosproject.incubator.net.intf.Interface; |
32 | +import org.onosproject.incubator.net.intf.InterfaceAdminService; | ||
32 | import org.onosproject.incubator.net.intf.InterfaceService; | 33 | import org.onosproject.incubator.net.intf.InterfaceService; |
33 | import org.onosproject.net.ConnectPoint; | 34 | import org.onosproject.net.ConnectPoint; |
34 | import org.onosproject.net.config.NetworkConfigEvent; | 35 | import org.onosproject.net.config.NetworkConfigEvent; |
... | @@ -50,7 +51,8 @@ import static java.util.stream.Collectors.toSet; | ... | @@ -50,7 +51,8 @@ import static java.util.stream.Collectors.toSet; |
50 | */ | 51 | */ |
51 | @Service | 52 | @Service |
52 | @Component(immediate = true) | 53 | @Component(immediate = true) |
53 | -public class InterfaceManager implements InterfaceService { | 54 | +public class InterfaceManager implements InterfaceService, |
55 | + InterfaceAdminService { | ||
54 | 56 | ||
55 | private final Logger log = LoggerFactory.getLogger(getClass()); | 57 | private final Logger log = LoggerFactory.getLogger(getClass()); |
56 | 58 | ||
... | @@ -153,6 +155,54 @@ public class InterfaceManager implements InterfaceService { | ... | @@ -153,6 +155,54 @@ public class InterfaceManager implements InterfaceService { |
153 | interfaces.remove(port); | 155 | interfaces.remove(port); |
154 | } | 156 | } |
155 | 157 | ||
158 | + @Override | ||
159 | + public void add(Interface intf) { | ||
160 | + if (interfaces.containsKey(intf.connectPoint())) { | ||
161 | + boolean conflict = interfaces.get(intf.connectPoint()).stream() | ||
162 | + .filter(i -> i.connectPoint().equals(intf.connectPoint())) | ||
163 | + .filter(i -> i.mac().equals(intf.mac())) | ||
164 | + .filter(i -> i.vlan().equals(intf.vlan())) | ||
165 | + .findAny().isPresent(); | ||
166 | + | ||
167 | + if (conflict) { | ||
168 | + log.error("Can't add interface because it conflicts with existing config"); | ||
169 | + return; | ||
170 | + } | ||
171 | + } | ||
172 | + | ||
173 | + InterfaceConfig config = | ||
174 | + configService.addConfig(intf.connectPoint(), CONFIG_CLASS); | ||
175 | + | ||
176 | + config.addInterface(intf); | ||
177 | + | ||
178 | + configService.applyConfig(intf.connectPoint(), CONFIG_CLASS, config.node()); | ||
179 | + } | ||
180 | + | ||
181 | + @Override | ||
182 | + public void remove(ConnectPoint connectPoint, VlanId vlanId) { | ||
183 | + Optional<Interface> intf = interfaces.get(connectPoint).stream() | ||
184 | + .filter(i -> i.vlan().equals(vlanId)) | ||
185 | + .findAny(); | ||
186 | + | ||
187 | + if (!intf.isPresent()) { | ||
188 | + log.error("Can't find interface {}/{} to remove", connectPoint, vlanId); | ||
189 | + return; | ||
190 | + } | ||
191 | + | ||
192 | + InterfaceConfig config = configService.addConfig(intf.get().connectPoint(), CONFIG_CLASS); | ||
193 | + config.removeInterface(intf.get()); | ||
194 | + | ||
195 | + try { | ||
196 | + if (config.getInterfaces().isEmpty()) { | ||
197 | + configService.removeConfig(connectPoint, CONFIG_CLASS); | ||
198 | + } else { | ||
199 | + configService.applyConfig(intf.get().connectPoint(), CONFIG_CLASS, config.node()); | ||
200 | + } | ||
201 | + } catch (ConfigException e) { | ||
202 | + log.error("Error reading interfaces JSON", e); | ||
203 | + } | ||
204 | + } | ||
205 | + | ||
156 | /** | 206 | /** |
157 | * Listener for network config events. | 207 | * Listener for network config events. |
158 | */ | 208 | */ | ... | ... |
-
Please register or login to post a comment