sanghoshin
Committed by Gerrit Code Review

SONA: openstackSwitching

 - Added event handlers  (DEVICE_XX, PORT_XXX) and tested with mininet
 - Added default flow rule setup for ARP and DHCP
 - Added neutron network API handler
 - Added the feature to populate flow rules for the same subnet
 - Added the feature to populate flow rules for VMs in other Cnode using Nicira ext.
 - Modified the directory structure
 - Fixed nicira ext handling logic
 - Fixed neutron network API handler
 - Added the tenant isolation feature by checking the source IP address

Change-Id: I076d21f3c90f458727e33cb36b47d9b14ccfd68f
1 +<?xml version="1.0" encoding="UTF-8"?>
2 +<!--
3 + ~ Copyright 2015 Open Networking Laboratory
4 + ~
5 + ~ Licensed under the Apache License, Version 2.0 (the "License");
6 + ~ you may not use this file except in compliance with the License.
7 + ~ You may obtain a copy of the License at
8 + ~
9 + ~ http://www.apache.org/licenses/LICENSE-2.0
10 + ~
11 + ~ Unless required by applicable law or agreed to in writing, software
12 + ~ distributed under the License is distributed on an "AS IS" BASIS,
13 + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 + ~ See the License for the specific language governing permissions and
15 + ~ limitations under the License.
16 + -->
17 +<project xmlns="http://maven.apache.org/POM/4.0.0"
18 + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
19 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
20 + <modelVersion>4.0.0</modelVersion>
21 +
22 + <parent>
23 + <groupId>org.onosproject</groupId>
24 + <artifactId>onos-apps</artifactId>
25 + <version>1.4.0-SNAPSHOT</version>
26 + <relativePath>../pom.xml</relativePath>
27 + </parent>
28 +
29 + <artifactId>onos-app-openstackswitching</artifactId>
30 + <packaging>bundle</packaging>
31 +
32 + <description>SONA Openstack Switching applications</description>
33 + <properties>
34 + <onos.version>1.4.0-SNAPSHOT</onos.version>
35 + <onos.app.name>org.onosproject.openstackswitching</onos.app.name>
36 + <web.context>/onos/openstackswitching</web.context>
37 + <api.version>1.0.0</api.version>
38 + <api.title>ONOS OpenStack Switching REST API</api.title>
39 + <api.description>
40 + APIs for receiving Neutron information.
41 + </api.description>
42 + <api.package>org.onosproject.openstackswitching.web</api.package>
43 + <onos.app.origin>SKT, Inc.</onos.app.origin>
44 + </properties>
45 +
46 +
47 + <dependencies>
48 + <dependency>
49 + <groupId>org.onosproject</groupId>
50 + <artifactId>onos-rest</artifactId>
51 + <version>${project.version}</version>
52 + </dependency>
53 + <dependency>
54 + <groupId>org.onosproject</groupId>
55 + <artifactId>onlab-rest</artifactId>
56 + <version>${project.version}</version>
57 + </dependency>
58 + <dependency>
59 + <groupId>javax.ws.rs</groupId>
60 + <artifactId>jsr311-api</artifactId>
61 + <version>1.1.1</version>
62 + </dependency>
63 + <dependency>
64 + <groupId>com.sun.jersey</groupId>
65 + <artifactId>jersey-servlet</artifactId>
66 + </dependency>
67 + <dependency>
68 + <groupId>com.fasterxml.jackson.core</groupId>
69 + <artifactId>jackson-databind</artifactId>
70 + </dependency>
71 + <dependency>
72 + <groupId>com.fasterxml.jackson.core</groupId>
73 + <artifactId>jackson-annotations</artifactId>
74 + </dependency>
75 + <dependency>
76 + <groupId>org.osgi</groupId>
77 + <artifactId>org.osgi.compendium</artifactId>
78 + </dependency>
79 + <dependency>
80 + <groupId>org.osgi</groupId>
81 + <artifactId>org.osgi.core</artifactId>
82 + </dependency>
83 + </dependencies>
84 +
85 + <build>
86 + <plugins>
87 + <plugin>
88 + <groupId>org.apache.felix</groupId>
89 + <artifactId>maven-bundle-plugin</artifactId>
90 + <extensions>true</extensions>
91 + <configuration>
92 + <instructions>
93 + <_wab>src/main/webapp/</_wab>
94 + <Bundle-SymbolicName>
95 + ${project.groupId}.${project.artifactId}
96 + </Bundle-SymbolicName>
97 + <Import-Package>
98 + org.slf4j,
99 + org.osgi.framework,
100 + javax.ws.rs,
101 + javax.ws.rs.core,
102 + com.sun.jersey.api.core,
103 + com.sun.jersey.spi.container.servlet,
104 + com.sun.jersey.server.impl.container.servlet,
105 + com.fasterxml.jackson.databind,
106 + com.fasterxml.jackson.databind.node,
107 + com.fasterxml.jackson.core,
108 + org.apache.karaf.shell.commands,
109 + com.google.common.*,
110 + org.onlab.packet.*,
111 + org.onosproject.*
112 + </Import-Package>
113 + <Web-ContextPath>${web.context}</Web-ContextPath>
114 + </instructions>
115 + </configuration>
116 + </plugin>
117 + </plugins>
118 + </build>
119 +
120 +
121 +</project>
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 +package org.onosproject.openstackswitching;
17 +
18 +import org.onosproject.net.packet.InboundPacket;
19 +import org.slf4j.Logger;
20 +import org.slf4j.LoggerFactory;
21 +
22 +import java.util.HashMap;
23 +
24 +/**
25 + * It handles ARP packet from VMs.
26 + */
27 +public class OpenstackArpHandler {
28 +
29 + private static Logger log = LoggerFactory
30 + .getLogger(OpenstackArpHandler.class);
31 +
32 + HashMap<String, OpenstackPort> openstackPortHashMap;
33 +
34 + /**
35 + * Returns OpenstackArpHandler reference.
36 + *
37 + * @param openstackPortMap
38 + */
39 + public OpenstackArpHandler(HashMap<String, OpenstackPort> openstackPortMap) {
40 + this.openstackPortHashMap = openstackPortMap;
41 + }
42 +
43 + /**
44 + * Processes ARP packets.
45 + *
46 + * @param pkt ARP request packet
47 + */
48 + public void processPacketIn(InboundPacket pkt) {
49 + log.warn("Received an ARP packet");
50 + }
51 +}
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 +package org.onosproject.openstackswitching;
17 +
18 +import org.onosproject.net.packet.InboundPacket;
19 +import org.slf4j.Logger;
20 +import org.slf4j.LoggerFactory;
21 +
22 +/**
23 + * It handles DHCP request packets.
24 + */
25 +public class OpenstackDhcpHandler {
26 +
27 + private static Logger log = LoggerFactory
28 + .getLogger(OpenstackDhcpHandler.class);
29 +
30 + /**
31 + * Returns OpenstackDhcpHandler reference.
32 + */
33 + public OpenstackDhcpHandler() {
34 +
35 + }
36 +
37 + /**
38 + * Processes DHCP request packets.
39 + *
40 + * @param pkt DHCP request packet
41 + */
42 + public void processPacketIn(InboundPacket pkt) {
43 + log.warn("Received a DHCP packet");
44 + }
45 +}
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 +package org.onosproject.openstackswitching;
17 +
18 +import static com.google.common.base.Preconditions.checkNotNull;
19 +
20 +
21 +/**
22 + * Represents the network information given by Neutron.
23 + */
24 +public final class OpenstackNetwork {
25 +
26 + private String name;
27 + private String tenantId;
28 + private String segmentId;
29 + private String networkType;
30 + private String id;
31 +
32 + /**
33 + * Returns the builder object of the OpenstackNetwork class.
34 + *
35 + * @return OpenstackNetwork builder object
36 + */
37 + public static OpenstackNetwork.Builder builder() {
38 + return new Builder();
39 + }
40 +
41 + private OpenstackNetwork(String name, String tenantId, String id, String sid,
42 + String type) {
43 + this.name = checkNotNull(name);
44 + this.tenantId = checkNotNull(tenantId);
45 + this.segmentId = checkNotNull(sid);
46 + this.id = checkNotNull(id);
47 + this.networkType = checkNotNull(type);
48 + }
49 +
50 + public String name() {
51 + return this.name;
52 + }
53 +
54 + public String tenantId() {
55 + return this.tenantId;
56 + }
57 +
58 + public String id() {
59 + return this.id;
60 + }
61 +
62 + public String segmentId() {
63 + return this.segmentId;
64 + }
65 +
66 + public String networkType() {
67 + return this.networkType;
68 + }
69 +
70 + public static final class Builder {
71 + private String name;
72 + private String tenantId;
73 + private String id;
74 + private String sid;
75 + private String networkType;
76 +
77 + public Builder name(String name) {
78 + this.name = name;
79 +
80 + return this;
81 + }
82 +
83 + public Builder tenantId(String tenantId) {
84 + this.tenantId = tenantId;
85 +
86 + return this;
87 + }
88 +
89 + public Builder id(String id) {
90 + this.id = id;
91 +
92 + return this;
93 + }
94 +
95 + public Builder segmentId(String sid) {
96 + this.sid = sid;
97 +
98 + return this;
99 + }
100 +
101 + public Builder networkType(String type) {
102 + this.networkType = type;
103 +
104 + return this;
105 + }
106 +
107 + public OpenstackNetwork build() {
108 + return new OpenstackNetwork(name, tenantId, id, sid, networkType);
109 + }
110 +
111 + }
112 +}
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 +package org.onosproject.openstackswitching;
17 +
18 +import com.google.common.collect.Lists;
19 +import org.onlab.packet.Ip4Address;
20 +import org.onlab.packet.MacAddress;
21 +
22 +import java.util.HashMap;
23 +import java.util.List;
24 +
25 +import static com.google.common.base.Preconditions.checkNotNull;
26 +
27 +/**
28 + * It represents the Openstack Port information.
29 + */
30 +public final class OpenstackPort {
31 +
32 + public enum PortStatus {
33 + UP,
34 + DOWN
35 + }
36 +
37 + private PortStatus status;
38 + private String name;
39 + // FIX_ME
40 + private String allowedAddressPairs;
41 + private boolean adminStateUp;
42 + private String networkId;
43 + private String tenantId;
44 + private String deviceOwner;
45 + private MacAddress macAddress;
46 + // <subnet id, ip address>
47 + private HashMap<String, Ip4Address> fixedIps;
48 + private String id;
49 + private List<String> securityGroups;
50 + private String deviceId;
51 +
52 + private OpenstackPort(PortStatus status, String name, boolean adminStateUp,
53 + String networkId, String tenantId, String deviceOwner,
54 + MacAddress macAddress, HashMap fixedIps, String id,
55 + List<String> securityGroups, String deviceId) {
56 +
57 + this.status = status;
58 + this.name = name;
59 + this.adminStateUp = adminStateUp;
60 + this.networkId = checkNotNull(networkId);
61 + this.tenantId = checkNotNull(tenantId);
62 + this.deviceOwner = deviceOwner;
63 + this.macAddress = checkNotNull(macAddress);
64 + this.fixedIps = checkNotNull(fixedIps);
65 + this.id = checkNotNull(id);
66 + this.securityGroups = securityGroups;
67 + this.deviceId = deviceId;
68 + }
69 +
70 +
71 +
72 + /**
73 + * Returns OpenstackPort builder object.
74 + *
75 + * @return OpenstackPort builder
76 + */
77 + public static OpenstackPort.Builder builder() {
78 + return new Builder();
79 + }
80 +
81 + /**
82 + * Returns port status.
83 + *
84 + * @return port status
85 + */
86 + public PortStatus status() {
87 + return status;
88 + }
89 +
90 + /**
91 + * Returns port name.
92 + *
93 + * @return port name
94 + */
95 + public String name() {
96 + return name;
97 + }
98 +
99 + /**
100 + * Returns whether admin state up or not.
101 + *
102 + * @return true if admin state up, false otherwise
103 + */
104 + public boolean isAdminStateUp() {
105 + return adminStateUp;
106 + }
107 +
108 + /**
109 + * Returns network ID.
110 + *
111 + * @return network ID
112 + */
113 + public String networkId() {
114 + return networkId;
115 + }
116 +
117 + /**
118 + * Returns device owner.
119 + *
120 + * @return device owner
121 + */
122 + public String deviceOwner() {
123 + return deviceOwner;
124 + }
125 +
126 + /**
127 + * Returns mac address.
128 + *
129 + * @return mac address
130 + */
131 + public MacAddress macAddress() {
132 + return macAddress;
133 + }
134 +
135 + /**
136 + * Returns the fixed IP information.
137 + *
138 + * @return fixed IP info
139 + */
140 + public HashMap fixedIps() {
141 + return fixedIps;
142 + }
143 +
144 + /**
145 + * Returns port ID.
146 + *
147 + * @return port ID
148 + */
149 + public String id() {
150 + return id;
151 + }
152 +
153 + /**
154 + * Returns security group information.
155 + *
156 + * @return security group info
157 + */
158 + public List<String> securityGroups() {
159 + return securityGroups;
160 + }
161 +
162 + /**
163 + * Returns device ID.
164 + *
165 + * @return device ID
166 + */
167 + public String deviceId() {
168 + return deviceId;
169 + }
170 +
171 + // TODO : Implement the following functions when necessary
172 + //@Override
173 + //public void equals(Object that) {
174 + //
175 + //}
176 + //
177 + //@Override
178 + //public int hashCode() {
179 + //
180 + //}
181 +
182 + /**
183 + * OpenstackPort Builder class.
184 + */
185 + public static final class Builder {
186 +
187 + private PortStatus status;
188 + private String name;
189 + // FIX_ME
190 + private String allowedAddressPairs;
191 + private boolean adminStateUp;
192 + private String networkId;
193 + private String tenantId;
194 + private String deviceOwner;
195 + private MacAddress macAddress;
196 + // list of hash map <subnet id, ip address>
197 + private HashMap<String, Ip4Address> fixedIps;
198 + private String id;
199 + private List<String> securityGroups;
200 + private String deviceId;
201 +
202 + Builder() {
203 + fixedIps = new HashMap<>();
204 + securityGroups = Lists.newArrayList();
205 + }
206 +
207 + /**
208 + * Sets port status.
209 + *
210 + * @param status port status
211 + * @return Builder object
212 + */
213 + public Builder portStatus(PortStatus status) {
214 + this.status = status;
215 +
216 + return this;
217 + }
218 +
219 + /**
220 + * Sets port name.
221 + *
222 + * @param name port name
223 + * @return Builder object
224 + */
225 + public Builder name(String name) {
226 + this.name = name;
227 +
228 + return this;
229 + }
230 +
231 + /**
232 + * Sets whether admin state up or not.
233 + *
234 + * @param isAdminStateUp true if admin state is up, false otherwise
235 + * @return Builder object
236 + */
237 + public Builder adminState(boolean isAdminStateUp) {
238 + this.adminStateUp = isAdminStateUp;
239 +
240 + return this;
241 + }
242 +
243 + /**
244 + * Sets network ID.
245 + *
246 + * @param networkId network ID
247 + * @return Builder object
248 + */
249 + public Builder netwrokId(String networkId) {
250 + this.networkId = networkId;
251 +
252 + return this;
253 + }
254 +
255 + /**
256 + * Sets tenant ID.
257 + *
258 + * @param tenantId tenant ID
259 + * @return Builder object
260 + */
261 + public Builder tenantId(String tenantId) {
262 + this.tenantId = tenantId;
263 +
264 + return this;
265 + }
266 +
267 + /**
268 + * Sets device owner.
269 + *
270 + * @param owner device owner
271 + * @return Builder object
272 + */
273 + public Builder deviceOwner(String owner) {
274 + this.deviceOwner = owner;
275 +
276 + return this;
277 + }
278 +
279 + /**
280 + * Sets MAC address of the port.
281 + *
282 + * @param mac MAC address
283 + * @return Builder object
284 + */
285 + public Builder macAddress(MacAddress mac) {
286 + this.macAddress = mac;
287 +
288 + return this;
289 + }
290 +
291 + /**
292 + * Sets Fixed IP address information.
293 + *
294 + * @param fixedIpList Fixed IP info
295 + * @return Builder object
296 + */
297 + public Builder fixedIps(HashMap<String, Ip4Address> fixedIpList) {
298 + fixedIps.putAll(fixedIpList);
299 +
300 + return this;
301 + }
302 +
303 + /**
304 + * Sets ID of the port.
305 + *
306 + * @param id ID of the port
307 + * @return Builder object
308 + */
309 + public Builder id(String id) {
310 + this.id = id;
311 +
312 + return this;
313 + }
314 +
315 + /**
316 + * Sets security group of the port.
317 + *
318 + * @param securityGroup security group of the port
319 + * @return Builder object
320 + */
321 + public Builder securityGroup(String securityGroup) {
322 + securityGroups.add(securityGroup);
323 +
324 + return this;
325 + }
326 +
327 + /**
328 + * Sets device ID of the port.
329 + *
330 + * @param deviceId device ID
331 + * @return Builder object
332 + */
333 + public Builder deviceId(String deviceId) {
334 + this.deviceId = deviceId;
335 +
336 + return this;
337 + }
338 +
339 + /**
340 + * Builds an OpenstackPort object.
341 + *
342 + * @return OpenstackPort objecet
343 + */
344 + public OpenstackPort build() {
345 + return new OpenstackPort(status, name, adminStateUp, networkId, networkId,
346 + deviceOwner, macAddress, fixedIps, id, securityGroups, deviceId);
347 + }
348 + }
349 +}
350 +
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 +package org.onosproject.openstackswitching;
17 +
18 +import com.google.common.collect.Lists;
19 +import com.google.common.collect.Maps;
20 +import org.apache.felix.scr.annotations.Activate;
21 +import org.apache.felix.scr.annotations.Component;
22 +import org.apache.felix.scr.annotations.Deactivate;
23 +import org.apache.felix.scr.annotations.Reference;
24 +import org.apache.felix.scr.annotations.ReferenceCardinality;
25 +import org.apache.felix.scr.annotations.Service;
26 +import org.onlab.packet.Ethernet;
27 +import org.onlab.packet.IPv4;
28 +import org.onlab.packet.Ip4Address;
29 +import org.onlab.packet.Ip4Prefix;
30 +import org.onlab.packet.MacAddress;
31 +import org.onlab.packet.UDP;
32 +import org.onosproject.core.ApplicationId;
33 +import org.onosproject.core.CoreService;
34 +import org.onosproject.net.Device;
35 +import org.onosproject.net.DeviceId;
36 +import org.onosproject.net.Port;
37 +import org.onosproject.net.device.DeviceEvent;
38 +import org.onosproject.net.device.DeviceListener;
39 +import org.onosproject.net.device.DeviceService;
40 +import org.onosproject.net.flowobjective.FlowObjectiveService;
41 +import org.onosproject.net.packet.InboundPacket;
42 +import org.onosproject.net.packet.PacketContext;
43 +import org.onosproject.net.packet.PacketProcessor;
44 +import org.onosproject.net.packet.PacketService;
45 +import org.slf4j.Logger;
46 +import org.slf4j.LoggerFactory;
47 +
48 +import java.util.HashMap;
49 +import java.util.List;
50 +import java.util.concurrent.ExecutorService;
51 +import java.util.concurrent.Executors;
52 +
53 +@SuppressWarnings("ALL")
54 +@Service
55 +@Component(immediate = true)
56 +/**
57 + * It populates forwarding rules for VMs created by Openstack.
58 + */
59 +public class OpenstackSwitchingManager implements OpenstackSwitchingService {
60 +
61 + private static Logger log = LoggerFactory
62 + .getLogger(OpenstackSwitchingManager.class);
63 +
64 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
65 + protected CoreService coreService;
66 +
67 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
68 + protected PacketService packetService;
69 +
70 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
71 + protected DeviceService deviceService;
72 +
73 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
74 + protected FlowObjectiveService flowObjectiveService;
75 +
76 +
77 + public static final int DHCP_PORT = 67;
78 +
79 + private ApplicationId appId;
80 + private OpenstackArpHandler arpHandler;
81 + private OpenstackDhcpHandler dhcpHandler = new OpenstackDhcpHandler();
82 + private OpenstackSwitchingRulePopulator rulePopulator;
83 + private ExecutorService deviceEventExcutorService = Executors.newFixedThreadPool(10);
84 +
85 + private InternalPacketProcessor internalPacketProcessor = new InternalPacketProcessor();
86 + private InternalDeviceListener internalDeviceListener = new InternalDeviceListener();
87 +
88 + // Map <port_id, OpenstackPort>
89 + private HashMap<String, OpenstackPort> openstackPortMap;
90 + // Map <network_id, OpenstackNetwork>
91 + private HashMap<String, OpenstackNetwork> openstackNetworkMap;
92 + // Map <vni, List <Entry <portName, host ip>>
93 + private HashMap<String, List<PortInfo>> vniPortMap;
94 + private HashMap<Ip4Address, Port> tunnelPortMap;
95 +
96 +
97 + @Activate
98 + protected void activate() {
99 + appId = coreService
100 + .registerApplication("org.onosproject.openstackswitching");
101 + rulePopulator = new OpenstackSwitchingRulePopulator(appId, flowObjectiveService);
102 + packetService.addProcessor(internalPacketProcessor, PacketProcessor.director(1));
103 + deviceService.addListener(internalDeviceListener);
104 +
105 + openstackPortMap = Maps.newHashMap();
106 + openstackNetworkMap = Maps.newHashMap();
107 + vniPortMap = Maps.newHashMap();
108 + tunnelPortMap = Maps.newHashMap();
109 +
110 + arpHandler = new OpenstackArpHandler(openstackPortMap);
111 +
112 + log.info("Started");
113 + }
114 +
115 + @Deactivate
116 + protected void deactivate() {
117 + packetService.removeProcessor(internalPacketProcessor);
118 + deviceService.removeListener(internalDeviceListener);
119 +
120 + deviceEventExcutorService.shutdown();
121 +
122 + log.info("Stopped");
123 + }
124 +
125 + @Override
126 + public void createPorts(OpenstackPort openstackPort) {
127 + openstackPortMap.put(openstackPort.id(), openstackPort);
128 + }
129 +
130 + @Override
131 + public void deletePorts() {
132 +
133 + }
134 +
135 + @Override
136 + public void updatePorts() {
137 +
138 + }
139 +
140 + @Override
141 + public void createNetwork(OpenstackNetwork openstackNetwork) {
142 + openstackNetworkMap.put(openstackNetwork.id(), openstackNetwork);
143 + }
144 +
145 + private void processDeviceAdded(Device device) {
146 + log.warn("device {} is added", device.id());
147 + rulePopulator.populateDefaultRules(device.id());
148 + }
149 +
150 + private void processPortAdded(Device device, Port port) {
151 + // TODO: Simplify the data structure to store the network info
152 + // TODO: Make it stateless
153 + // TODO: All the logics need to be processed inside of the rulePopulator class
154 + synchronized (vniPortMap) {
155 + log.warn("port {} is updated", port.toString());
156 +
157 + updatePortMaps(device, port);
158 + if (!port.annotations().value("portName").equals("vxlan")) {
159 + populateFlowRulesForTrafficToSameCnode(device, port);
160 + populateFlowRulesForTrafficToDifferentCnode(device, port);
161 + }
162 + }
163 + }
164 +
165 + private void processPortRemoved(Device device, Port port) {
166 + log.warn("port {} is removed", port.toString());
167 + // TODO: need to update the vniPortMap
168 + }
169 +
170 + /**
171 + * Populates the flow rules for traffic to VMs in different Cnode using
172 + * Nicira extention.
173 + *
174 + * @param device device to put rules
175 + * @param port port information of the VM
176 + */
177 + private void populateFlowRulesForTrafficToDifferentCnode(Device device, Port port) {
178 + String portName = port.annotations().value("portName");
179 + String channelId = device.annotations().value("channelId");
180 + Ip4Address hostIpAddress = Ip4Address.valueOf(channelId.split(":")[0]);
181 + Ip4Address fixedIp = getFixedIpAddressForPort(portName);
182 + // TODO: Avoid duplicate flow rule set up for VMs in other Cnode
183 + // (possibly avoided by flowrule subsystem?)
184 + if (tunnelPortMap.get(hostIpAddress) == null) {
185 + log.warn("There is no tunnel port information");
186 + return;
187 + }
188 + String vni = getVniForPort(portName);
189 + MacAddress vmMac = getVmMacAddressForPort(portName);
190 + if (!vniPortMap.isEmpty() && vniPortMap.get(vni) != null) {
191 + for (PortInfo portInfo : vniPortMap.get(vni)) {
192 + if (!portInfo.portName.equals(portName) &&
193 + !portInfo.hostIp.equals(hostIpAddress)) {
194 + MacAddress vmMacx = getVmMacAddressForPort(portInfo.portName);
195 + rulePopulator.populateForwardingRuleForOtherCnode(vni,
196 + device.id(), portInfo.hostIp, portInfo.fixedIp, vmMacx,
197 + tunnelPortMap.get(hostIpAddress).number(),
198 + portInfo.deviceId, hostIpAddress, fixedIp, vmMac,
199 + tunnelPortMap.get(portInfo.hostIp).number());
200 + }
201 + }
202 + }
203 + }
204 +
205 + /**
206 + * Populates the flow rules for traffic to VMs in the same Cnode as the sender.
207 + *
208 + * @param device device to put the rules
209 + * @param port port info of the VM
210 + */
211 + private void populateFlowRulesForTrafficToSameCnode(Device device, Port port) {
212 + Ip4Prefix cidr = getCidrForPort(port.annotations().value("portName"));
213 + Ip4Address vmIp = getFixedIpAddressForPort(port.annotations().value("portName"));
214 + if (vmIp != null) {
215 + rulePopulator.populateForwardingRule(vmIp, device.id(), port, cidr);
216 + }
217 + }
218 +
219 + /**
220 + * Updates the port maps using the port information.
221 + *
222 + * @param device device info
223 + * @param port port of the VM
224 + */
225 + private void updatePortMaps(Device device, Port port) {
226 + String portName = port.annotations().value("portName");
227 + String channelId = device.annotations().value("channelId");
228 + Ip4Address hostIpAddress = Ip4Address.valueOf(channelId.split(":")[0]);
229 + if (portName.startsWith("vxlan")) {
230 + tunnelPortMap.put(hostIpAddress, port);
231 + } else {
232 + String vni = getVniForPort(portName);
233 + Ip4Address fixedIp = getFixedIpAddressForPort(portName);
234 + if (vniPortMap.get(vni) == null) {
235 + vniPortMap.put(vni, Lists.newArrayList());
236 + }
237 + vniPortMap.get(vni).add(new PortInfo(device.id(), portName, fixedIp, hostIpAddress));
238 + }
239 + }
240 +
241 + /**
242 + * Returns CIDR information from the subnet map for the port.
243 + *
244 + * @param portName port name of the port of the VM
245 + * @return CIDR of the VNI of the VM
246 + */
247 + private Ip4Prefix getCidrForPort(String portName) {
248 + String networkId = null;
249 + String uuid = portName.substring(3);
250 + OpenstackPort port = openstackPortMap.values().stream()
251 + .filter(p -> p.id().startsWith(uuid))
252 + .findFirst().get();
253 + if (port == null) {
254 + log.warn("No port information for port {}", portName);
255 + return null;
256 + }
257 +
258 + //OpenstackSubnet subnet = openstackSubnetMap.values().stream()
259 + // .filter(s -> s.networkId().equals(port.networkId()))
260 + // .findFirst().get();
261 + //if (subnet == null) {
262 + // log.warn("No subnet information for network {}", subnet.id());
263 + // return null;
264 + //}
265 +
266 + //return Ip4Prefix.valueOf(subnet.cidr());
267 + return null;
268 + }
269 +
270 + /**
271 + * Returns the VNI of the VM of the port.
272 + *
273 + * @param portName VM port
274 + * @return VNI
275 + */
276 + private String getVniForPort(String portName) {
277 + String networkId = null;
278 + String uuid = portName.substring(3);
279 + OpenstackPort port = openstackPortMap.values().stream()
280 + .filter(p -> p.id().startsWith(uuid))
281 + .findFirst().get();
282 + if (port == null) {
283 + log.warn("No port information for port {}", portName);
284 + return null;
285 + }
286 + OpenstackNetwork network = openstackNetworkMap.values().stream()
287 + .filter(n -> n.id().equals(port.networkId()))
288 + .findFirst().get();
289 + if (network == null) {
290 + log.warn("No VNI information for network {}", network.id());
291 + return null;
292 + }
293 +
294 + return network.segmentId();
295 + }
296 +
297 + /**
298 + * Returns the Fixed IP address of the VM.
299 + *
300 + * @param portName VM port info
301 + * @return IP address of the VM
302 + */
303 + private Ip4Address getFixedIpAddressForPort(String portName) {
304 +
305 + // FIXME - For now we use the information stored from neutron Rest API call.
306 + // TODO - Later, the information needs to be extracted from Neutron on-demand.
307 + String uuid = portName.substring(3);
308 + OpenstackPort port = openstackPortMap.values().stream()
309 + .filter(p -> p.id().startsWith(uuid))
310 + .findFirst().get();
311 +
312 + if (port == null) {
313 + log.error("There is no port information for port name {}", portName);
314 + return null;
315 + }
316 +
317 + if (port.fixedIps().isEmpty()) {
318 + log.error("There is no fixed IP info in the port information");
319 + return null;
320 + }
321 +
322 + return (Ip4Address) port.fixedIps().values().toArray()[0];
323 + }
324 +
325 + /**
326 + * Returns the MAC address of the VM of the port.
327 + *
328 + * @param portName VM port
329 + * @return MAC address of the VM
330 + */
331 + private MacAddress getVmMacAddressForPort(String portName) {
332 +
333 + String uuid = portName.substring(3);
334 + OpenstackPort port = openstackPortMap.values().stream()
335 + .filter(p -> p.id().startsWith(uuid))
336 + .findFirst().get();
337 +
338 + if (port == null) {
339 + log.error("There is no mac information for port name {}", portName);
340 + return null;
341 + }
342 +
343 + return port.macAddress();
344 + }
345 +
346 + private class InternalPacketProcessor implements PacketProcessor {
347 +
348 + @Override
349 + public void process(PacketContext context) {
350 +
351 + if (context.isHandled()) {
352 + return;
353 + }
354 +
355 + InboundPacket pkt = context.inPacket();
356 + Ethernet ethernet = pkt.parsed();
357 +
358 + if (ethernet.getEtherType() == Ethernet.TYPE_ARP) {
359 + arpHandler.processPacketIn(pkt);
360 + } else if (ethernet.getEtherType() == Ethernet.TYPE_IPV4) {
361 + IPv4 ipPacket = (IPv4) ethernet.getPayload();
362 +
363 + if (ipPacket.getProtocol() == IPv4.PROTOCOL_UDP) {
364 + UDP udpPacket = (UDP) ipPacket.getPayload();
365 + if (udpPacket.getDestinationPort() == DHCP_PORT) {
366 + dhcpHandler.processPacketIn(pkt);
367 + }
368 + }
369 + }
370 + }
371 + }
372 +
373 + private class InternalDeviceListener implements DeviceListener {
374 +
375 + @Override
376 + public void event(DeviceEvent event) {
377 + deviceEventExcutorService.execute(new InternalEventHandler(event));
378 + }
379 + }
380 +
381 + private class InternalEventHandler implements Runnable {
382 +
383 + volatile DeviceEvent deviceEvent;
384 +
385 + InternalEventHandler(DeviceEvent deviceEvent) {
386 + this.deviceEvent = deviceEvent;
387 + }
388 +
389 + @Override
390 + public void run() {
391 + switch (deviceEvent.type()) {
392 + case DEVICE_ADDED:
393 + processDeviceAdded((Device) deviceEvent.subject());
394 + break;
395 + case DEVICE_UPDATED:
396 + Port port = (Port) deviceEvent.subject();
397 + if (port.isEnabled()) {
398 + processPortAdded((Device) deviceEvent.subject(), deviceEvent.port());
399 + }
400 + break;
401 + case DEVICE_AVAILABILITY_CHANGED:
402 + Device device = (Device) deviceEvent.subject();
403 + if (deviceService.isAvailable(device.id())) {
404 + processDeviceAdded(device);
405 + }
406 + break;
407 + case PORT_ADDED:
408 + processPortAdded((Device) deviceEvent.subject(), deviceEvent.port());
409 + break;
410 + case PORT_UPDATED:
411 + processPortAdded((Device) deviceEvent.subject(), deviceEvent.port());
412 + break;
413 + case PORT_REMOVED:
414 + processPortRemoved((Device) deviceEvent.subject(), deviceEvent.port());
415 + break;
416 + default:
417 + break;
418 + }
419 + }
420 + }
421 +
422 + private final class PortInfo {
423 + DeviceId deviceId;
424 + String portName;
425 + Ip4Address fixedIp;
426 + Ip4Address hostIp;
427 +
428 + private PortInfo(DeviceId deviceId, String portName, Ip4Address fixedIp,
429 + Ip4Address hostIp) {
430 + this.deviceId = deviceId;
431 + this.portName = portName;
432 + this.fixedIp = fixedIp;
433 + this.hostIp = hostIp;
434 + }
435 + }
436 +
437 +}
...\ No newline at end of file ...\ No newline at end of file
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.openstackswitching;
18 +
19 +import org.onlab.packet.Ethernet;
20 +import org.onlab.packet.IPv4;
21 +import org.onlab.packet.Ip4Address;
22 +import org.onlab.packet.Ip4Prefix;
23 +import org.onlab.packet.MacAddress;
24 +import org.onlab.packet.TpPort;
25 +import org.onosproject.core.ApplicationId;
26 +import org.onosproject.net.DeviceId;
27 +import org.onosproject.net.Port;
28 +import org.onosproject.net.PortNumber;
29 +import org.onosproject.net.flow.DefaultTrafficSelector;
30 +import org.onosproject.net.flow.DefaultTrafficTreatment;
31 +import org.onosproject.net.flow.TrafficSelector;
32 +import org.onosproject.net.flow.TrafficTreatment;
33 +import org.onosproject.net.flowobjective.DefaultForwardingObjective;
34 +import org.onosproject.net.flowobjective.FlowObjectiveService;
35 +import org.onosproject.net.flowobjective.ForwardingObjective;
36 +import org.slf4j.Logger;
37 +import org.slf4j.LoggerFactory;
38 +
39 +/**
40 + * It populates switching flow rules.
41 + *
42 + */
43 +public class OpenstackSwitchingRulePopulator {
44 +
45 + private static Logger log = LoggerFactory
46 + .getLogger(OpenstackSwitchingRulePopulator.class);
47 +
48 + private FlowObjectiveService flowObjectiveService;
49 + private ApplicationId appId;
50 +
51 + /**
52 + * Returns OpenstackSwitchingRule reference.
53 + * @param flowObjectiveService FlowObjectiveService reference
54 + */
55 + public OpenstackSwitchingRulePopulator(ApplicationId appId,
56 + FlowObjectiveService flowObjectiveService) {
57 + this.flowObjectiveService = flowObjectiveService;
58 + this.appId = appId;
59 + }
60 +
61 + /**
62 + * Populates flows rules for forwarding packets to and from VMs.
63 + *
64 + * @return true if it succeeds to populate rules, false otherwise.
65 + */
66 + public boolean populateForwardingRule(Ip4Address ip, DeviceId id, Port port, Ip4Prefix cidr) {
67 +
68 +
69 + setFlowRuleForVMsInSameCnode(ip, id, port, cidr);
70 +
71 + return true;
72 + }
73 +
74 + /**
75 + * Populates the common flows rules for all VMs.
76 + *
77 + * - Send ARP packets to the controller
78 + * - Send DHCP packets to the controller
79 + *
80 + * @param id Device ID to populates rules to
81 + */
82 + public void populateDefaultRules(DeviceId id) {
83 +
84 + //setFlowRuleForDHCP(id);
85 + setFlowRuleForArp(id);
86 +
87 + log.warn("Default rule has been set");
88 + }
89 +
90 + /**
91 + * Populates the forwarding rules for VMs with the same VNI but in other Code.
92 + *
93 + * @param vni VNI for the networks
94 + * @param id device ID to populates the flow rules
95 + * @param hostIp host IP address of the VM
96 + * @param vmIp fixed IP address for the VM
97 + * @param idx device ID for OVS of the other VM
98 + * @param hostIpx host IP address of the other VM
99 + * @param vmIpx fixed IP address of the other VM
100 + */
101 + public void populateForwardingRuleForOtherCnode(String vni, DeviceId id, Ip4Address hostIp,
102 + Ip4Address vmIp, MacAddress vmMac, PortNumber tunnelPort,
103 + DeviceId idx, Ip4Address hostIpx,
104 + Ip4Address vmIpx, MacAddress vmMacx, PortNumber tunnelPortx) {
105 + setVxLanFlowRule(vni, id, hostIp, vmIp, vmMac, tunnelPort);
106 + setVxLanFlowRule(vni, idx, hostIpx, vmIpx, vmMacx, tunnelPortx);
107 + }
108 +
109 + /**
110 + * Populates the flow rules for DHCP packets from VMs.
111 + *
112 + * @param id device ID to set the rules
113 + */
114 + private void setFlowRuleForDHCP(DeviceId id) {
115 + TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
116 + TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
117 +
118 + sBuilder.matchEthType(Ethernet.TYPE_IPV4)
119 + .matchIPProtocol(IPv4.PROTOCOL_UDP)
120 + .matchUdpDst(TpPort.tpPort(OpenstackSwitchingManager.DHCP_PORT));
121 + tBuilder.setOutput(PortNumber.CONTROLLER);
122 +
123 + ForwardingObjective fo = DefaultForwardingObjective.builder()
124 + .withSelector(sBuilder.build())
125 + .withTreatment(tBuilder.build())
126 + .withPriority(5000)
127 + .withFlag(ForwardingObjective.Flag.VERSATILE)
128 + .fromApp(appId)
129 + .add();
130 +
131 + flowObjectiveService.forward(id, fo);
132 + }
133 +
134 + /**
135 + * Populates the flow rules for ARP packets from VMs.
136 + *
137 + * @param id device ID to put rules.
138 + */
139 + private void setFlowRuleForArp(DeviceId id) {
140 + TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
141 + TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
142 +
143 + sBuilder.matchEthType(Ethernet.TYPE_ARP);
144 + tBuilder.setOutput(PortNumber.CONTROLLER);
145 +
146 + ForwardingObjective fo = DefaultForwardingObjective.builder()
147 + .withSelector(sBuilder.build())
148 + .withTreatment(tBuilder.build())
149 + .withPriority(5000)
150 + .withFlag(ForwardingObjective.Flag.VERSATILE)
151 + .fromApp(appId)
152 + .add();
153 +
154 + flowObjectiveService.forward(id, fo);
155 + }
156 +
157 + /**
158 + * Sets the flow rules for traffic between VMs in the same Cnode.
159 + *
160 + * @param ip4Address VM IP address
161 + * @param id device ID to put rules
162 + * @param port VM port
163 + * @param cidr subnet info of the VMs
164 + */
165 + private void setFlowRuleForVMsInSameCnode(Ip4Address ip4Address, DeviceId id,
166 + Port port, Ip4Prefix cidr) {
167 + TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
168 + TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
169 +
170 + sBuilder.matchEthType(Ethernet.TYPE_IPV4)
171 + .matchIPDst(ip4Address.toIpPrefix())
172 + .matchIPSrc(cidr);
173 + tBuilder.setOutput(port.number());
174 +
175 + ForwardingObjective fo = DefaultForwardingObjective.builder()
176 + .withSelector(sBuilder.build())
177 + .withTreatment(tBuilder.build())
178 + .withPriority(5000)
179 + .withFlag(ForwardingObjective.Flag.VERSATILE)
180 + .fromApp(appId)
181 + .add();
182 +
183 + flowObjectiveService.forward(id, fo);
184 + }
185 +
186 + /**
187 + * Sets the flow rules between traffic from VMs in different Cnode.
188 + *
189 + * @param vni VNI
190 + * @param id device ID
191 + * @param hostIp host IP of the VM
192 + * @param vmIp fixed IP of the VM
193 + * @param vmMac MAC address of the VM
194 + * @param tunnelPort tunnel port to forward traffic to
195 + */
196 + private void setVxLanFlowRule(String vni, DeviceId id, Ip4Address hostIp,
197 + Ip4Address vmIp, MacAddress vmMac, PortNumber tunnelPort) {
198 + TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
199 + TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
200 +
201 + sBuilder.matchEthType(Ethernet.TYPE_IPV4)
202 + .matchIPDst(vmIp.toIpPrefix());
203 + tBuilder.setTunnelId(Long.parseLong(vni))
204 + //.setTunnelDst() <- for Nicira ext
205 + //.setEthDst(vmMac)
206 + .setOutput(tunnelPort);
207 +
208 + ForwardingObjective fo = DefaultForwardingObjective.builder()
209 + .withSelector(sBuilder.build())
210 + .withTreatment(tBuilder.build())
211 + .withPriority(5000)
212 + .withFlag(ForwardingObjective.Flag.VERSATILE)
213 + .fromApp(appId)
214 + .add();
215 +
216 + flowObjectiveService.forward(id, fo);
217 + }
218 +}
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 +package org.onosproject.openstackswitching;
17 +
18 +/**
19 + * It handles port management REST API from Openstack for VMs.
20 + */
21 +public interface OpenstackSwitchingService {
22 +
23 + /**
24 + * Store the port information created by Openstack.
25 + *
26 + * @param openstackPort port information
27 + */
28 + void createPorts(OpenstackPort openstackPort);
29 +
30 + /**
31 + * Removes flow rules corresponding to the port removed by Openstack.
32 + *
33 + */
34 + void deletePorts();
35 +
36 + /**
37 + * Updates flow rules corresponding to the port information updated by Openstack.
38 + *
39 + */
40 + void updatePorts();
41 +
42 + /**
43 + * Store the network information created by openstack.
44 + *
45 + * @param openstackNetwork network information
46 + */
47 + void createNetwork(OpenstackNetwork openstackNetwork);
48 +
49 +}
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 +package org.onosproject.openstackswitching.web;
17 +
18 +import com.fasterxml.jackson.databind.JsonNode;
19 +import com.fasterxml.jackson.databind.node.ObjectNode;
20 +import org.onosproject.codec.CodecContext;
21 +import org.onosproject.codec.JsonCodec;
22 +import org.onosproject.openstackswitching.OpenstackNetwork;
23 +import org.slf4j.Logger;
24 +import org.slf4j.LoggerFactory;
25 +
26 +/**
27 + * Implementation of the OpenstackNetwork Codec.
28 + *
29 + */
30 +public class OpenstackNetworkCodec extends JsonCodec<OpenstackNetwork> {
31 +
32 + protected static final Logger log = LoggerFactory
33 + .getLogger(OpenstackNetworkCodec.class);
34 +
35 + private static final String NETWORK = "network";
36 + private static final String NAME = "name";
37 + private static final String TENANT_ID = "tenant_id";
38 + private static final String SEGMENTATION_ID = "provider:segmentation_id";
39 + private static final String NETWORK_TYPE = "provider:network_type";
40 + private static final String ID = "id";
41 +
42 + @Override
43 + public OpenstackNetwork decode(ObjectNode json, CodecContext context) {
44 +
45 + JsonNode networkInfo = json.get(NETWORK);
46 +
47 + String name = networkInfo.path(NAME).asText();
48 + String tenantId = networkInfo.path(TENANT_ID).asText();
49 + String id = networkInfo.path(ID).asText();
50 +
51 + OpenstackNetwork.Builder onb = OpenstackNetwork.builder();
52 + onb.name(name)
53 + .tenantId(tenantId)
54 + .id(id);
55 +
56 + if (!networkInfo.path(NETWORK_TYPE).isMissingNode()) {
57 + onb.name(networkInfo.path(NETWORK_TYPE).asText());
58 + onb.segmentId(networkInfo.path(SEGMENTATION_ID).asText());
59 + }
60 +
61 + return onb.build();
62 + }
63 +
64 +}
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 +package org.onosproject.openstackswitching.web;
17 +
18 +import com.fasterxml.jackson.databind.ObjectMapper;
19 +import com.fasterxml.jackson.databind.node.ObjectNode;
20 +import org.onosproject.openstackswitching.OpenstackNetwork;
21 +import org.onosproject.openstackswitching.OpenstackSwitchingService;
22 +import org.onosproject.rest.AbstractWebResource;
23 +import org.slf4j.Logger;
24 +import org.slf4j.LoggerFactory;
25 +
26 +import javax.ws.rs.Consumes;
27 +import javax.ws.rs.POST;
28 +import javax.ws.rs.Path;
29 +import javax.ws.rs.Produces;
30 +import javax.ws.rs.core.MediaType;
31 +import javax.ws.rs.core.Response;
32 +import java.io.InputStream;
33 +
34 +@Path("networks")
35 +public class OpenstackNetworkWebResource extends AbstractWebResource {
36 +
37 + protected static final Logger log = LoggerFactory
38 + .getLogger(OpenstackNetworkWebResource.class);
39 +
40 + private static final OpenstackNetworkCodec NETWORK_CODEC = new OpenstackNetworkCodec();
41 +
42 + @POST
43 + @Consumes(MediaType.APPLICATION_JSON)
44 + @Produces(MediaType.APPLICATION_JSON)
45 + public Response createNetwork(InputStream input) {
46 + try {
47 + ObjectMapper mapper = new ObjectMapper();
48 + ObjectNode networkNode = (ObjectNode) mapper.readTree(input);
49 +
50 + OpenstackNetwork openstackNetwork = NETWORK_CODEC.decode(networkNode, this);
51 +
52 + OpenstackSwitchingService switchingService = get(OpenstackSwitchingService.class);
53 + switchingService.createNetwork(openstackNetwork);
54 + return Response.status(Response.Status.OK).build();
55 + } catch (Exception e) {
56 + log.error("Creates VirtualPort failed because of exception {}",
57 + e.toString());
58 + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(e.toString())
59 + .build();
60 + }
61 + }
62 +}
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 +package org.onosproject.openstackswitching.web;
17 +
18 +import com.fasterxml.jackson.databind.JsonNode;
19 +import com.fasterxml.jackson.databind.node.ArrayNode;
20 +import com.fasterxml.jackson.databind.node.ObjectNode;
21 +import org.onlab.packet.Ip4Address;
22 +import org.onlab.packet.MacAddress;
23 +import org.onosproject.codec.CodecContext;
24 +import org.onosproject.codec.JsonCodec;
25 +import org.onosproject.openstackswitching.OpenstackPort;
26 +import org.slf4j.Logger;
27 +import org.slf4j.LoggerFactory;
28 +
29 +import java.util.HashMap;
30 +
31 +/**
32 + * It encodes and decodes the OpenstackPort.
33 + */
34 +public class OpenstackPortCodec extends JsonCodec<OpenstackPort> {
35 +
36 + private static Logger log = LoggerFactory
37 + .getLogger(OpenstackPortCodec.class);
38 +
39 + // JSON field names
40 + private static final String PORT = "port";
41 + private static final String STATUS = "status";
42 + private static final String NAME = "name";
43 + private static final String ADDRESS_PAIR = "allowed_address_pairs";
44 + private static final String ADMIN_STATUS = "admin_status";
45 + private static final String NETWORK_ID = "network_id";
46 + private static final String TENANT_ID = "tenant_id";
47 + private static final String DEVICE_OWNER = "device_owner";
48 + private static final String MAC_ADDRESS = "mac_address";
49 + private static final String FIXED_IPS = "fixed_ips";
50 + private static final String SUBNET_ID = "subnet_id";
51 + private static final String IP_ADDRESS = "ip_address";
52 + private static final String ID = "id";
53 + private static final String SECURITY_GROUPS = "security_groups";
54 + private static final String DEVICE_ID = "device_id";
55 +
56 + @Override
57 + public OpenstackPort decode(ObjectNode json, CodecContext context) {
58 +
59 + HashMap<String, Ip4Address> fixedIpMap = new HashMap<>();
60 + JsonNode portInfo = json.get(PORT);
61 +
62 + String status = portInfo.path(STATUS).asText();
63 + String name = portInfo.path(NAME).asText();
64 + boolean adminStateUp = portInfo.path(ADMIN_STATUS).asBoolean();
65 + String networkId = portInfo.path(NETWORK_ID).asText();
66 + String tenantId = portInfo.path(TENANT_ID).asText();
67 + String deviceOwner = portInfo.path(DEVICE_OWNER).asText();
68 + String macStr = portInfo.path(MAC_ADDRESS).asText();
69 + ArrayNode fixedIpList = (ArrayNode) portInfo.path(FIXED_IPS);
70 + for (JsonNode fixedIpInfo: fixedIpList) {
71 + String subnetId = fixedIpInfo.path(SUBNET_ID).asText();
72 + String ipAddressStr = fixedIpInfo.path(IP_ADDRESS).asText();
73 + if (ipAddressStr != null) {
74 + Ip4Address ipAddress = Ip4Address.valueOf(ipAddressStr);
75 + fixedIpMap.put(subnetId, ipAddress);
76 + }
77 + }
78 + String id = portInfo.path(ID).asText();
79 + String securityGroups = portInfo.path(SECURITY_GROUPS).asText();
80 + String deviceId = portInfo.path(DEVICE_ID).asText();
81 +
82 + OpenstackPort.Builder openstackPortBuilder = OpenstackPort.builder();
83 + openstackPortBuilder.portStatus(OpenstackPort.PortStatus.valueOf(status))
84 + .name(name)
85 + .adminState(adminStateUp)
86 + .netwrokId(networkId)
87 + .tenantId(tenantId)
88 + .deviceOwner(deviceOwner)
89 + .macAddress(MacAddress.valueOf(macStr))
90 + .fixedIps(fixedIpMap)
91 + .id(id)
92 + .deviceId(deviceId);
93 +
94 + // FIX ME
95 + if (!securityGroups.isEmpty()) {
96 + openstackPortBuilder.securityGroup(securityGroups);
97 + }
98 +
99 + OpenstackPort openstackPort = openstackPortBuilder.build();
100 +
101 + return openstackPort;
102 + }
103 +
104 +}
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 +package org.onosproject.openstackswitching.web;
17 +
18 +import com.fasterxml.jackson.databind.ObjectMapper;
19 +import com.fasterxml.jackson.databind.node.ObjectNode;
20 +import org.onosproject.openstackswitching.OpenstackPort;
21 +import org.onosproject.openstackswitching.OpenstackSwitchingService;
22 +import org.onosproject.rest.AbstractWebResource;
23 +import org.slf4j.Logger;
24 +import org.slf4j.LoggerFactory;
25 +
26 +import javax.ws.rs.Consumes;
27 +import javax.ws.rs.DELETE;
28 +import javax.ws.rs.POST;
29 +import javax.ws.rs.PUT;
30 +import javax.ws.rs.Path;
31 +import javax.ws.rs.Produces;
32 +import javax.ws.rs.core.MediaType;
33 +import javax.ws.rs.core.Response;
34 +import java.io.InputStream;
35 +
36 +@Path("ports")
37 +public class OpenstackPortWebResource extends AbstractWebResource {
38 +
39 + protected static final Logger log = LoggerFactory
40 + .getLogger(OpenstackPortWebResource.class);
41 +
42 + private static final OpenstackPortCodec PORT_CODEC = new OpenstackPortCodec();
43 +
44 + @POST
45 + @Consumes(MediaType.APPLICATION_JSON)
46 + @Produces(MediaType.APPLICATION_JSON)
47 + public Response createPorts(InputStream input) {
48 + try {
49 + ObjectMapper mapper = new ObjectMapper();
50 + ObjectNode portNode = (ObjectNode) mapper.readTree(input);
51 +
52 + OpenstackPort openstackPort = PORT_CODEC.decode(portNode, this);
53 +
54 + OpenstackSwitchingService switchingService = get(OpenstackSwitchingService.class);
55 + switchingService.createPorts(openstackPort);
56 + log.info("REST API ports is called with {}", portNode.toString());
57 + return Response.status(Response.Status.OK).build();
58 + } catch (Exception e) {
59 + log.error("Creates VirtualPort failed because of exception {}",
60 + e.toString());
61 + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(e.toString())
62 + .build();
63 + }
64 + }
65 +
66 + @DELETE
67 + @Consumes(MediaType.APPLICATION_JSON)
68 + @Produces(MediaType.APPLICATION_JSON)
69 + public Response deletesPorts(InputStream input) {
70 + try {
71 + ObjectMapper mapper = new ObjectMapper();
72 + ObjectNode portNode = (ObjectNode) mapper.readTree(input);
73 +
74 + OpenstackSwitchingService switchingService = get(OpenstackSwitchingService.class);
75 + switchingService.deletePorts();
76 + log.info("REST API ports is called with {}", portNode.toString());
77 + return Response.status(Response.Status.OK).build();
78 + } catch (Exception e) {
79 + log.error("Delete VirtualPort failed because of exception {}",
80 + e.toString());
81 + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(e.toString())
82 + .build();
83 + }
84 + }
85 +
86 + @PUT
87 + @Path("{id}")
88 + @Consumes(MediaType.APPLICATION_JSON)
89 + @Produces(MediaType.APPLICATION_JSON)
90 + public Response updatePorts(InputStream input) {
91 + try {
92 + ObjectMapper mapper = new ObjectMapper();
93 + ObjectNode portNode = (ObjectNode) mapper.readTree(input);
94 +
95 + OpenstackSwitchingService switchingService = get(OpenstackSwitchingService.class);
96 + switchingService.updatePorts();
97 + log.info("REST API ports is called with {}", portNode.toString());
98 + return Response.status(Response.Status.OK).build();
99 + } catch (Exception e) {
100 + log.error("Update VirtualPort failed because of exception {}",
101 + e.toString());
102 + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(e.toString())
103 + .build();
104 + }
105 + }
106 +}
1 +<?xml version="1.0" encoding="UTF-8"?>
2 +<!--
3 + ~ Copyright 2015 Open Networking Laboratory
4 + ~
5 + ~ Licensed under the Apache License, Version 2.0 (the "License");
6 + ~ you may not use this file except in compliance with the License.
7 + ~ You may obtain a copy of the License at
8 + ~
9 + ~ http://www.apache.org/licenses/LICENSE-2.0
10 + ~
11 + ~ Unless required by applicable law or agreed to in writing, software
12 + ~ distributed under the License is distributed on an "AS IS" BASIS,
13 + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 + ~ See the License for the specific language governing permissions and
15 + ~ limitations under the License.
16 + -->
17 +<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee"
18 + xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
19 + xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
20 + id="ONOS" version="2.5">
21 + <display-name>Openstack Switching REST API v1.0</display-name>
22 +
23 + <servlet>
24 + <servlet-name>JAX-RS Service</servlet-name>
25 + <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
26 + <init-param>
27 + <param-name>com.sun.jersey.config.property.resourceConfigClass</param-name>
28 + <param-value>com.sun.jersey.api.core.ClassNamesResourceConfig</param-value>
29 + </init-param>
30 + <init-param>
31 + <param-name>com.sun.jersey.config.property.classnames</param-name>
32 + <param-value>
33 + org.onosproject.openstackswitching.web.OpenstackPortWebResource,
34 + org.onosproject.openstackswitching.web.OpenstackNetworkWebResource
35 + </param-value>
36 + </init-param>
37 + <load-on-startup>1</load-on-startup>
38 + </servlet>
39 +
40 + <servlet-mapping>
41 + <servlet-name>JAX-RS Service</servlet-name>
42 + <url-pattern>/*</url-pattern>
43 + </servlet-mapping>
44 +</web-app>
...@@ -13,10 +13,7 @@ ...@@ -13,10 +13,7 @@
13 ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 ~ See the License for the specific language governing permissions and 14 ~ See the License for the specific language governing permissions and
15 ~ limitations under the License. 15 ~ limitations under the License.
16 - --> 16 + --><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
17 -<project xmlns="http://maven.apache.org/POM/4.0.0"
18 - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
19 - xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
20 <modelVersion>4.0.0</modelVersion> 17 <modelVersion>4.0.0</modelVersion>
21 18
22 <parent> 19 <parent>
...@@ -60,6 +57,7 @@ ...@@ -60,6 +57,7 @@
60 <module>igmp</module> 57 <module>igmp</module>
61 <module>pim</module> 58 <module>pim</module>
62 <module>mlb</module> 59 <module>mlb</module>
60 + <module>openstackswitching</module>
63 </modules> 61 </modules>
64 62
65 <properties> 63 <properties>
......