Committed by
Gerrit Code Review
SONA : OpenstackSwitching
- Stateless Neutron data handling - Supports Nicira ext. Change-Id: I31db161bbd06a03e2d8e6ee6abfb033215898ee7
Showing
16 changed files
with
629 additions
and
401 deletions
... | @@ -32,7 +32,8 @@ public final class OpenstackPort { | ... | @@ -32,7 +32,8 @@ public final class OpenstackPort { |
32 | 32 | ||
33 | public enum PortStatus { | 33 | public enum PortStatus { |
34 | UP, | 34 | UP, |
35 | - DOWN | 35 | + DOWN, |
36 | + ACTIVE | ||
36 | } | 37 | } |
37 | 38 | ||
38 | private PortStatus status; | 39 | private PortStatus status; | ... | ... |
... | @@ -15,6 +15,8 @@ | ... | @@ -15,6 +15,8 @@ |
15 | */ | 15 | */ |
16 | package org.onosproject.openstackswitching; | 16 | package org.onosproject.openstackswitching; |
17 | 17 | ||
18 | +import org.onosproject.net.Port; | ||
19 | + | ||
18 | import java.util.Collection; | 20 | import java.util.Collection; |
19 | 21 | ||
20 | /** | 22 | /** |
... | @@ -64,6 +66,14 @@ public interface OpenstackSwitchingService { | ... | @@ -64,6 +66,14 @@ public interface OpenstackSwitchingService { |
64 | Collection<OpenstackPort> ports(String networkId); | 66 | Collection<OpenstackPort> ports(String networkId); |
65 | 67 | ||
66 | /** | 68 | /** |
69 | + * Returns port information for the port given. | ||
70 | + * | ||
71 | + * @param port port reference | ||
72 | + * @return port information | ||
73 | + */ | ||
74 | + OpenstackPort port(Port port); | ||
75 | + | ||
76 | + /** | ||
67 | * Returns port information for the port ID given. | 77 | * Returns port information for the port ID given. |
68 | * | 78 | * |
69 | * @param portId Port ID | 79 | * @param portId Port ID | ... | ... |
... | @@ -16,11 +16,13 @@ | ... | @@ -16,11 +16,13 @@ |
16 | --> | 16 | --> |
17 | <features xmlns="http://karaf.apache.org/xmlns/features/v1.2.0" name="${project.artifactId}-${project.version}"> | 17 | <features xmlns="http://karaf.apache.org/xmlns/features/v1.2.0" name="${project.artifactId}-${project.version}"> |
18 | <repository>mvn:${project.groupId}/${project.artifactId}/${project.version}/xml/features</repository> | 18 | <repository>mvn:${project.groupId}/${project.artifactId}/${project.version}/xml/features</repository> |
19 | - <feature name="onos-app-openstackswitching" version="${project.version}" | 19 | + <feature name="${project.artifactId}" version="${project.version}" |
20 | description="${project.description}"> | 20 | description="${project.description}"> |
21 | <feature>onos-api</feature> | 21 | <feature>onos-api</feature> |
22 | <bundle>mvn:${project.groupId}/onos-app-openstackswitching/${project.version}</bundle> | 22 | <bundle>mvn:${project.groupId}/onos-app-openstackswitching/${project.version}</bundle> |
23 | <bundle>mvn:${project.groupId}/onos-app-dhcp-api/${project.version}</bundle> | 23 | <bundle>mvn:${project.groupId}/onos-app-dhcp-api/${project.version}</bundle> |
24 | <bundle>mvn:${project.groupId}/onos-app-dhcp/${project.version}</bundle> | 24 | <bundle>mvn:${project.groupId}/onos-app-dhcp/${project.version}</bundle> |
25 | + <bundle>mvn:com.sun.jersey/jersey-client/1.19</bundle> | ||
26 | + <bundle>mvn:${project.groupId}/${project.artifactId}/${project.version}</bundle> | ||
25 | </feature> | 27 | </feature> |
26 | </features> | 28 | </features> | ... | ... |
... | @@ -90,6 +90,11 @@ | ... | @@ -90,6 +90,11 @@ |
90 | <artifactId>onos-app-dhcp-api</artifactId> | 90 | <artifactId>onos-app-dhcp-api</artifactId> |
91 | <version>${project.version}</version> | 91 | <version>${project.version}</version> |
92 | </dependency> | 92 | </dependency> |
93 | + <dependency> | ||
94 | + <groupId>com.sun.jersey</groupId> | ||
95 | + <artifactId>jersey-client</artifactId> | ||
96 | + <version>1.19</version> | ||
97 | + </dependency> | ||
93 | </dependencies> | 98 | </dependencies> |
94 | 99 | ||
95 | <build> | 100 | <build> |
... | @@ -110,6 +115,7 @@ | ... | @@ -110,6 +115,7 @@ |
110 | javax.ws.rs, | 115 | javax.ws.rs, |
111 | javax.ws.rs.core, | 116 | javax.ws.rs.core, |
112 | com.sun.jersey.api.core, | 117 | com.sun.jersey.api.core, |
118 | + com.sun.jersey.api.client, | ||
113 | com.sun.jersey.spi.container.servlet, | 119 | com.sun.jersey.spi.container.servlet, |
114 | com.sun.jersey.server.impl.container.servlet, | 120 | com.sun.jersey.server.impl.container.servlet, |
115 | com.fasterxml.jackson.databind, | 121 | com.fasterxml.jackson.databind, | ... | ... |
... | @@ -28,7 +28,8 @@ import org.onosproject.net.packet.PacketService; | ... | @@ -28,7 +28,8 @@ import org.onosproject.net.packet.PacketService; |
28 | import org.slf4j.Logger; | 28 | import org.slf4j.Logger; |
29 | import org.slf4j.LoggerFactory; | 29 | import org.slf4j.LoggerFactory; |
30 | import java.nio.ByteBuffer; | 30 | import java.nio.ByteBuffer; |
31 | -import java.util.Map; | 31 | + |
32 | +import static com.google.common.base.Preconditions.checkNotNull; | ||
32 | 33 | ||
33 | /** | 34 | /** |
34 | * Handles ARP packet from VMs. | 35 | * Handles ARP packet from VMs. |
... | @@ -38,16 +39,16 @@ public class OpenstackArpHandler { | ... | @@ -38,16 +39,16 @@ public class OpenstackArpHandler { |
38 | private static Logger log = LoggerFactory | 39 | private static Logger log = LoggerFactory |
39 | .getLogger(OpenstackArpHandler.class); | 40 | .getLogger(OpenstackArpHandler.class); |
40 | private PacketService packetService; | 41 | private PacketService packetService; |
41 | - private Map<String, OpenstackPort> openstackPortMap; | 42 | + private OpenstackRestHandler restHandler; |
42 | 43 | ||
43 | /** | 44 | /** |
44 | * Returns OpenstackArpHandler reference. | 45 | * Returns OpenstackArpHandler reference. |
45 | * | 46 | * |
46 | - * @param openstackPortMap | 47 | + * @param restHandler rest API handler reference |
47 | - * @param packetService | 48 | + * @param packetService PacketService reference |
48 | */ | 49 | */ |
49 | - public OpenstackArpHandler(Map<String, OpenstackPort> openstackPortMap, PacketService packetService) { | 50 | + public OpenstackArpHandler(OpenstackRestHandler restHandler, PacketService packetService) { |
50 | - this.openstackPortMap = openstackPortMap; | 51 | + this.restHandler = checkNotNull(restHandler); |
51 | this.packetService = packetService; | 52 | this.packetService = packetService; |
52 | } | 53 | } |
53 | 54 | ||
... | @@ -68,8 +69,9 @@ public class OpenstackArpHandler { | ... | @@ -68,8 +69,9 @@ public class OpenstackArpHandler { |
68 | //Searches the Dst MAC Address based on openstackPortMap | 69 | //Searches the Dst MAC Address based on openstackPortMap |
69 | MacAddress macAddress = null; | 70 | MacAddress macAddress = null; |
70 | 71 | ||
71 | - OpenstackPort openstackPort = openstackPortMap.values().stream().filter(e -> e.fixedIps(). | 72 | + OpenstackPort openstackPort = restHandler.getPorts().stream(). |
72 | - containsValue(Ip4Address.valueOf(dstIPAddress))).findAny().orElse(null); | 73 | + filter(e -> e.fixedIps().containsValue(Ip4Address.valueOf( |
74 | + dstIPAddress))).findAny().orElse(null); | ||
73 | 75 | ||
74 | if (openstackPort != null) { | 76 | if (openstackPort != null) { |
75 | macAddress = openstackPort.macAddress(); | 77 | macAddress = openstackPort.macAddress(); | ... | ... |
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.fasterxml.jackson.databind.ObjectMapper; | ||
19 | +import com.fasterxml.jackson.databind.node.ArrayNode; | ||
20 | +import com.fasterxml.jackson.databind.node.ObjectNode; | ||
21 | +import com.google.common.collect.Lists; | ||
22 | +import com.sun.jersey.api.client.Client; | ||
23 | +import com.sun.jersey.api.client.WebResource; | ||
24 | +import org.onosproject.openstackswitching.web.OpenstackNetworkCodec; | ||
25 | +import org.onosproject.openstackswitching.web.OpenstackPortCodec; | ||
26 | +import org.onosproject.openstackswitching.web.OpenstackSubnetCodec; | ||
27 | +import org.slf4j.Logger; | ||
28 | +import javax.ws.rs.core.MediaType; | ||
29 | +import java.io.IOException; | ||
30 | +import java.util.Collection; | ||
31 | +import java.util.List; | ||
32 | + | ||
33 | +import static com.google.common.base.Preconditions.checkNotNull; | ||
34 | +import static com.google.common.net.MediaType.JSON_UTF_8; | ||
35 | +import static org.slf4j.LoggerFactory.getLogger; | ||
36 | + | ||
37 | +/** | ||
38 | + * Handles REST Calls to Openstack Neutron. | ||
39 | + * | ||
40 | + */ | ||
41 | +public class OpenstackRestHandler { | ||
42 | + | ||
43 | + private final Logger log = getLogger(getClass()); | ||
44 | + private String neutronUrl; | ||
45 | + private String keystoneUrl; | ||
46 | + private String tokenId; | ||
47 | + private String userName; | ||
48 | + private String pass; | ||
49 | + | ||
50 | + /** | ||
51 | + * Creates OpenstackRestHandler instance. | ||
52 | + * | ||
53 | + * @param cfg OpenstackSwitchingConfig reference | ||
54 | + */ | ||
55 | + public OpenstackRestHandler(OpenstackSwitchingConfig cfg) { | ||
56 | + this.neutronUrl = checkNotNull(cfg.neutronServer()); | ||
57 | + this.keystoneUrl = checkNotNull(cfg.keystoneServer()); | ||
58 | + this.userName = checkNotNull(cfg.userName()); | ||
59 | + this.pass = checkNotNull(cfg.password()); | ||
60 | + } | ||
61 | + | ||
62 | + /** | ||
63 | + * Returns network information stored in Neutron. | ||
64 | + * | ||
65 | + * @return List of OpenstackNetwork | ||
66 | + */ | ||
67 | + public Collection<OpenstackNetwork> getNetworks() { | ||
68 | + | ||
69 | + WebResource.Builder builder = getClientBuilder(neutronUrl + "networks"); | ||
70 | + String response = builder.accept(MediaType.APPLICATION_JSON_TYPE). | ||
71 | + header("X-Auth-Token", getToken()).get(String.class); | ||
72 | + | ||
73 | + ObjectMapper mapper = new ObjectMapper(); | ||
74 | + List<OpenstackNetwork> openstackNetworks = Lists.newArrayList(); | ||
75 | + try { | ||
76 | + ObjectNode node = (ObjectNode) mapper.readTree(response); | ||
77 | + ArrayNode networkList = (ArrayNode) node.path("networks"); | ||
78 | + OpenstackNetworkCodec networkCodec = new OpenstackNetworkCodec(); | ||
79 | + networkList.forEach(n -> openstackNetworks.add(networkCodec.decode((ObjectNode) n, null))); | ||
80 | + } catch (IOException e) { | ||
81 | + e.printStackTrace(); | ||
82 | + } | ||
83 | + | ||
84 | + log.debug("networks response:" + response); | ||
85 | + openstackNetworks.forEach(n -> log.debug("network ID: {}", n.id())); | ||
86 | + | ||
87 | + return openstackNetworks; | ||
88 | + } | ||
89 | + | ||
90 | + /** | ||
91 | + * Returns port information stored in Neutron. | ||
92 | + * | ||
93 | + * @return List of OpenstackPort | ||
94 | + */ | ||
95 | + public Collection<OpenstackPort> getPorts() { | ||
96 | + | ||
97 | + WebResource.Builder builder = getClientBuilder(neutronUrl + "ports"); | ||
98 | + String response = builder.accept(MediaType.APPLICATION_JSON_TYPE). | ||
99 | + header("X-Auth-Token", getToken()).get(String.class); | ||
100 | + | ||
101 | + ObjectMapper mapper = new ObjectMapper(); | ||
102 | + List<OpenstackPort> openstackPorts = Lists.newArrayList(); | ||
103 | + try { | ||
104 | + ObjectNode node = (ObjectNode) mapper.readTree(response); | ||
105 | + ArrayNode portList = (ArrayNode) node.path("ports"); | ||
106 | + OpenstackPortCodec portCodec = new OpenstackPortCodec(); | ||
107 | + portList.forEach(p -> openstackPorts.add(portCodec.decode((ObjectNode) p, null))); | ||
108 | + } catch (IOException e) { | ||
109 | + e.printStackTrace(); | ||
110 | + } | ||
111 | + | ||
112 | + log.debug("port response:" + response); | ||
113 | + openstackPorts.forEach(n -> log.debug("port ID: {}", n.id())); | ||
114 | + | ||
115 | + return openstackPorts; | ||
116 | + } | ||
117 | + | ||
118 | + /** | ||
119 | + * Returns Subnet information in Neutron. | ||
120 | + * | ||
121 | + * @return List of OpenstackSubnet | ||
122 | + */ | ||
123 | + public Collection<OpenstackSubnet> getSubnets() { | ||
124 | + | ||
125 | + WebResource.Builder builder = getClientBuilder(neutronUrl + "subnets"); | ||
126 | + String response = builder.accept(MediaType.APPLICATION_JSON_TYPE). | ||
127 | + header("X-Auth-Token", getToken()).get(String.class); | ||
128 | + | ||
129 | + ObjectMapper mapper = new ObjectMapper(); | ||
130 | + List<OpenstackSubnet> subnets = Lists.newArrayList(); | ||
131 | + try { | ||
132 | + ObjectNode node = (ObjectNode) mapper.readTree(response); | ||
133 | + ArrayNode subnetList = (ArrayNode) node.path("subnets"); | ||
134 | + OpenstackSubnetCodec subnetCodec = new OpenstackSubnetCodec(); | ||
135 | + subnetList.forEach(s -> subnets.add(subnetCodec.decode((ObjectNode) s, null))); | ||
136 | + } catch (IOException e) { | ||
137 | + e.printStackTrace(); | ||
138 | + } | ||
139 | + | ||
140 | + log.debug("subnets response:" + response); | ||
141 | + subnets.forEach(s -> log.debug("subnet ID: {}", s.id())); | ||
142 | + | ||
143 | + return subnets; | ||
144 | + } | ||
145 | + | ||
146 | + private WebResource.Builder getClientBuilder(String uri) { | ||
147 | + Client client = Client.create(); | ||
148 | + WebResource resource = client.resource(uri); | ||
149 | + return resource.accept(JSON_UTF_8.toString()) | ||
150 | + .type(JSON_UTF_8.toString()); | ||
151 | + } | ||
152 | + | ||
153 | + private String getToken() { | ||
154 | + if (isTokenInvalid()) { | ||
155 | + String request = "{\"auth\": {\"tenantName\": \"admin\", " + | ||
156 | + "\"passwordCredentials\": {\"username\": \"" + | ||
157 | + userName + "\",\"password\": \"" + pass + "\"}}}"; | ||
158 | + WebResource.Builder builder = getClientBuilder(keystoneUrl + "tokens"); | ||
159 | + String response = builder.accept(MediaType.APPLICATION_JSON).post(String.class, request); | ||
160 | + | ||
161 | + ObjectMapper mapper = new ObjectMapper(); | ||
162 | + try { | ||
163 | + ObjectNode node = (ObjectNode) mapper.readTree(response); | ||
164 | + tokenId = node.path("access").path("token").path("id").asText(); | ||
165 | + } catch (IOException e) { | ||
166 | + e.printStackTrace(); | ||
167 | + } | ||
168 | + log.debug("token response:" + response); | ||
169 | + } | ||
170 | + | ||
171 | + return tokenId; | ||
172 | + } | ||
173 | + | ||
174 | + private boolean isTokenInvalid() { | ||
175 | + //TODO: validation check for the existing token | ||
176 | + return true; | ||
177 | + } | ||
178 | + | ||
179 | +} |
... | @@ -24,6 +24,10 @@ import org.onosproject.net.config.basics.BasicElementConfig; | ... | @@ -24,6 +24,10 @@ import org.onosproject.net.config.basics.BasicElementConfig; |
24 | */ | 24 | */ |
25 | public class OpenstackSwitchingConfig extends Config<ApplicationId> { | 25 | public class OpenstackSwitchingConfig extends Config<ApplicationId> { |
26 | public static final String DONOTPUSH = "do_not_push_flows"; | 26 | public static final String DONOTPUSH = "do_not_push_flows"; |
27 | + public static final String NEUTRON_SERVER = "neutron_server"; | ||
28 | + public static final String KEYSTONE_SERVER = "keystone_server"; | ||
29 | + public static final String USER_NAME = "user_name"; | ||
30 | + public static final String PASSWORD = "password"; | ||
27 | 31 | ||
28 | /** | 32 | /** |
29 | * Returns the flag whether the app pushes flows or not. | 33 | * Returns the flag whether the app pushes flows or not. |
... | @@ -36,6 +40,42 @@ public class OpenstackSwitchingConfig extends Config<ApplicationId> { | ... | @@ -36,6 +40,42 @@ public class OpenstackSwitchingConfig extends Config<ApplicationId> { |
36 | } | 40 | } |
37 | 41 | ||
38 | /** | 42 | /** |
43 | + * Returns the Neutron server IP address. | ||
44 | + * | ||
45 | + * @return Neutron server IP | ||
46 | + */ | ||
47 | + public String neutronServer() { | ||
48 | + return get(NEUTRON_SERVER, ""); | ||
49 | + } | ||
50 | + | ||
51 | + /** | ||
52 | + * Returns the Keystone server IP address. | ||
53 | + * | ||
54 | + * @return Keystone server IP | ||
55 | + */ | ||
56 | + public String keystoneServer() { | ||
57 | + return get(KEYSTONE_SERVER, ""); | ||
58 | + } | ||
59 | + | ||
60 | + /** | ||
61 | + * Returns the username for openstack. | ||
62 | + * | ||
63 | + * @return username for openstack | ||
64 | + */ | ||
65 | + public String userName() { | ||
66 | + return get(USER_NAME, ""); | ||
67 | + } | ||
68 | + | ||
69 | + /** | ||
70 | + * Returns the password for openstack. | ||
71 | + * | ||
72 | + * @return password for openstack | ||
73 | + */ | ||
74 | + public String password() { | ||
75 | + return get(PASSWORD, ""); | ||
76 | + } | ||
77 | + | ||
78 | + /** | ||
39 | * Sets the flag whether the app pushes flows or not. | 79 | * Sets the flag whether the app pushes flows or not. |
40 | * | 80 | * |
41 | * @param flag the flag whether the app pushes flows or not | 81 | * @param flag the flag whether the app pushes flows or not |
... | @@ -44,4 +84,44 @@ public class OpenstackSwitchingConfig extends Config<ApplicationId> { | ... | @@ -44,4 +84,44 @@ public class OpenstackSwitchingConfig extends Config<ApplicationId> { |
44 | public BasicElementConfig doNotPushFlows(boolean flag) { | 84 | public BasicElementConfig doNotPushFlows(boolean flag) { |
45 | return (BasicElementConfig) setOrClear(DONOTPUSH, flag); | 85 | return (BasicElementConfig) setOrClear(DONOTPUSH, flag); |
46 | } | 86 | } |
87 | + | ||
88 | + /** | ||
89 | + * Sets the neutron server IP address. | ||
90 | + * | ||
91 | + * @param url neutron server IP address | ||
92 | + * @return itself | ||
93 | + */ | ||
94 | + public BasicElementConfig neutronServer(String url) { | ||
95 | + return (BasicElementConfig) setOrClear(NEUTRON_SERVER, url); | ||
96 | + } | ||
97 | + | ||
98 | + /** | ||
99 | + * Sets the keystone server IP address. | ||
100 | + * | ||
101 | + * @param url keystone server IP address | ||
102 | + * @return itself | ||
103 | + */ | ||
104 | + public BasicElementConfig keystoneServer(String url) { | ||
105 | + return (BasicElementConfig) setOrClear(KEYSTONE_SERVER, url); | ||
106 | + } | ||
107 | + | ||
108 | + /** | ||
109 | + * Sets the username for openstack. | ||
110 | + * | ||
111 | + * @param username user name for openstack | ||
112 | + * @return itself | ||
113 | + */ | ||
114 | + public BasicElementConfig userName(String username) { | ||
115 | + return (BasicElementConfig) setOrClear(USER_NAME, username); | ||
116 | + } | ||
117 | + | ||
118 | + /** | ||
119 | + * Sets the password for openstack. | ||
120 | + * | ||
121 | + * @param password password for openstack | ||
122 | + * @return itself | ||
123 | + */ | ||
124 | + public BasicElementConfig password(String password) { | ||
125 | + return (BasicElementConfig) setOrClear(PASSWORD, password); | ||
126 | + } | ||
47 | } | 127 | } | ... | ... |
... | @@ -17,7 +17,6 @@ package org.onosproject.openstackswitching; | ... | @@ -17,7 +17,6 @@ package org.onosproject.openstackswitching; |
17 | 17 | ||
18 | import com.google.common.collect.ImmutableSet; | 18 | import com.google.common.collect.ImmutableSet; |
19 | import com.google.common.collect.Lists; | 19 | import com.google.common.collect.Lists; |
20 | -import com.google.common.collect.Maps; | ||
21 | import org.apache.felix.scr.annotations.Activate; | 20 | import org.apache.felix.scr.annotations.Activate; |
22 | import org.apache.felix.scr.annotations.Component; | 21 | import org.apache.felix.scr.annotations.Component; |
23 | import org.apache.felix.scr.annotations.Deactivate; | 22 | import org.apache.felix.scr.annotations.Deactivate; |
... | @@ -26,8 +25,6 @@ import org.apache.felix.scr.annotations.ReferenceCardinality; | ... | @@ -26,8 +25,6 @@ import org.apache.felix.scr.annotations.ReferenceCardinality; |
26 | import org.apache.felix.scr.annotations.Service; | 25 | import org.apache.felix.scr.annotations.Service; |
27 | import org.onlab.packet.Ethernet; | 26 | import org.onlab.packet.Ethernet; |
28 | import org.onlab.packet.Ip4Address; | 27 | import org.onlab.packet.Ip4Address; |
29 | -import org.onlab.packet.Ip4Prefix; | ||
30 | -import org.onlab.packet.MacAddress; | ||
31 | import org.onosproject.core.ApplicationId; | 28 | import org.onosproject.core.ApplicationId; |
32 | import org.onosproject.core.CoreService; | 29 | import org.onosproject.core.CoreService; |
33 | import org.onosproject.dhcp.DhcpService; | 30 | import org.onosproject.dhcp.DhcpService; |
... | @@ -41,6 +38,7 @@ import org.onosproject.net.config.NetworkConfigRegistry; | ... | @@ -41,6 +38,7 @@ import org.onosproject.net.config.NetworkConfigRegistry; |
41 | import org.onosproject.net.device.DeviceEvent; | 38 | import org.onosproject.net.device.DeviceEvent; |
42 | import org.onosproject.net.device.DeviceListener; | 39 | import org.onosproject.net.device.DeviceListener; |
43 | import org.onosproject.net.device.DeviceService; | 40 | import org.onosproject.net.device.DeviceService; |
41 | +import org.onosproject.net.driver.DriverService; | ||
44 | import org.onosproject.net.flowobjective.FlowObjectiveService; | 42 | import org.onosproject.net.flowobjective.FlowObjectiveService; |
45 | import org.onosproject.net.packet.InboundPacket; | 43 | import org.onosproject.net.packet.InboundPacket; |
46 | import org.onosproject.net.packet.PacketContext; | 44 | import org.onosproject.net.packet.PacketContext; |
... | @@ -49,7 +47,6 @@ import org.onosproject.net.packet.PacketService; | ... | @@ -49,7 +47,6 @@ import org.onosproject.net.packet.PacketService; |
49 | import org.slf4j.Logger; | 47 | import org.slf4j.Logger; |
50 | import org.slf4j.LoggerFactory; | 48 | import org.slf4j.LoggerFactory; |
51 | import java.util.List; | 49 | import java.util.List; |
52 | -import java.util.Map; | ||
53 | import java.util.Collection; | 50 | import java.util.Collection; |
54 | import java.util.Set; | 51 | import java.util.Set; |
55 | import java.util.concurrent.ExecutorService; | 52 | import java.util.concurrent.ExecutorService; |
... | @@ -82,18 +79,23 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService { | ... | @@ -82,18 +79,23 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService { |
82 | protected FlowObjectiveService flowObjectiveService; | 79 | protected FlowObjectiveService flowObjectiveService; |
83 | 80 | ||
84 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | 81 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
85 | - protected NetworkConfigRegistry cfgService; | 82 | + protected DhcpService dhcpService; |
86 | 83 | ||
87 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | 84 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
88 | - protected DhcpService dhcpService; | 85 | + protected NetworkConfigRegistry cfgService; |
89 | 86 | ||
90 | - public static final int DHCP_PORT = 67; | 87 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
88 | + protected DriverService driverService; | ||
91 | 89 | ||
92 | private ApplicationId appId; | 90 | private ApplicationId appId; |
93 | private boolean doNotPushFlows; | 91 | private boolean doNotPushFlows; |
92 | + private Ip4Address neutronServer; | ||
93 | + private Ip4Address keystoneServer; | ||
94 | + private String userName; | ||
95 | + private String password; | ||
94 | private OpenstackArpHandler arpHandler; | 96 | private OpenstackArpHandler arpHandler; |
97 | + private OpenstackRestHandler restHandler; | ||
95 | 98 | ||
96 | - private OpenstackSwitchingRulePopulator rulePopulator; | ||
97 | private ExecutorService deviceEventExcutorService = Executors.newFixedThreadPool(10); | 99 | private ExecutorService deviceEventExcutorService = Executors.newFixedThreadPool(10); |
98 | 100 | ||
99 | private InternalPacketProcessor internalPacketProcessor = new InternalPacketProcessor(); | 101 | private InternalPacketProcessor internalPacketProcessor = new InternalPacketProcessor(); |
... | @@ -109,38 +111,18 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService { | ... | @@ -109,38 +111,18 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService { |
109 | } | 111 | } |
110 | } | 112 | } |
111 | ); | 113 | ); |
112 | - // Map <port_id, OpenstackPort> | ||
113 | - private Map<String, OpenstackPort> openstackPortMap; | ||
114 | - // Map <network_id, OpenstackNetwork> | ||
115 | - private Map<String, OpenstackNetwork> openstackNetworkMap; | ||
116 | - // Map <subnet_id, OpenstackSubner> | ||
117 | - private Map<String, OpenstackSubnet> openstackSubnetMap; | ||
118 | - // Map <vni, List <Entry <portName, host ip>> | ||
119 | - private Map<String, List<PortInfo>> vniPortMap; | ||
120 | - private Map<Ip4Address, Port> tunnelPortMap; | ||
121 | - | ||
122 | 114 | ||
123 | @Activate | 115 | @Activate |
124 | protected void activate() { | 116 | protected void activate() { |
125 | appId = coreService | 117 | appId = coreService |
126 | .registerApplication("org.onosproject.openstackswitching"); | 118 | .registerApplication("org.onosproject.openstackswitching"); |
119 | + | ||
120 | + factories.forEach(cfgService::registerConfigFactory); | ||
127 | packetService.addProcessor(internalPacketProcessor, PacketProcessor.director(1)); | 121 | packetService.addProcessor(internalPacketProcessor, PacketProcessor.director(1)); |
128 | deviceService.addListener(internalDeviceListener); | 122 | deviceService.addListener(internalDeviceListener); |
129 | cfgService.addListener(internalConfigListener); | 123 | cfgService.addListener(internalConfigListener); |
130 | - factories.forEach(cfgService::registerConfigFactory); | ||
131 | - OpenstackSwitchingConfig cfg = | ||
132 | - cfgService.getConfig(appId, OpenstackSwitchingConfig.class); | ||
133 | - if (cfg != null) { | ||
134 | - doNotPushFlows = cfg.doNotPushFlows(); | ||
135 | - } | ||
136 | - openstackPortMap = Maps.newHashMap(); | ||
137 | - openstackNetworkMap = Maps.newHashMap(); | ||
138 | - openstackSubnetMap = Maps.newHashMap(); | ||
139 | - | ||
140 | - vniPortMap = Maps.newHashMap(); | ||
141 | - tunnelPortMap = Maps.newHashMap(); | ||
142 | 124 | ||
143 | - arpHandler = new OpenstackArpHandler(openstackPortMap, packetService); | 125 | + internalConfigListener.configureNetwork(); |
144 | 126 | ||
145 | log.info("Started"); | 127 | log.info("Started"); |
146 | } | 128 | } |
... | @@ -159,7 +141,6 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService { | ... | @@ -159,7 +141,6 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService { |
159 | @Override | 141 | @Override |
160 | public void createPorts(OpenstackPort openstackPort) { | 142 | public void createPorts(OpenstackPort openstackPort) { |
161 | registerDhcpInfo(openstackPort); | 143 | registerDhcpInfo(openstackPort); |
162 | - openstackPortMap.put(openstackPort.id(), openstackPort); | ||
163 | } | 144 | } |
164 | 145 | ||
165 | @Override | 146 | @Override |
... | @@ -174,19 +155,16 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService { | ... | @@ -174,19 +155,16 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService { |
174 | 155 | ||
175 | @Override | 156 | @Override |
176 | public void createNetwork(OpenstackNetwork openstackNetwork) { | 157 | public void createNetwork(OpenstackNetwork openstackNetwork) { |
177 | - openstackNetworkMap.put(openstackNetwork.id(), openstackNetwork); | ||
178 | } | 158 | } |
179 | 159 | ||
180 | @Override | 160 | @Override |
181 | public void createSubnet(OpenstackSubnet openstackSubnet) { | 161 | public void createSubnet(OpenstackSubnet openstackSubnet) { |
182 | - openstackSubnetMap.put(openstackSubnet.id(), openstackSubnet); | ||
183 | - log.debug("Added Subnet Info {}", openstackNetworkMap.get(openstackSubnet.id())); | ||
184 | } | 162 | } |
185 | 163 | ||
186 | @Override | 164 | @Override |
187 | public Collection<OpenstackPort> ports(String networkId) { | 165 | public Collection<OpenstackPort> ports(String networkId) { |
188 | - | 166 | + Collection<OpenstackPort> ports = restHandler.getPorts(); |
189 | - List<OpenstackPort> portList = openstackPortMap.values().stream() | 167 | + List<OpenstackPort> portList = ports.stream() |
190 | .filter(p -> p.networkId().equals(networkId)) | 168 | .filter(p -> p.networkId().equals(networkId)) |
191 | .collect(Collectors.toList()); | 169 | .collect(Collectors.toList()); |
192 | 170 | ||
... | @@ -194,47 +172,46 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService { | ... | @@ -194,47 +172,46 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService { |
194 | } | 172 | } |
195 | 173 | ||
196 | @Override | 174 | @Override |
197 | - public OpenstackPort port(String portName) { | 175 | + public OpenstackPort port(Port port) { |
198 | - String uuid = portName.substring(3); | 176 | + Collection<OpenstackPort> ports = restHandler.getPorts(); |
199 | - return (OpenstackPort) openstackPortMap.values().stream() | 177 | + String uuid = port.annotations().value("portName").substring(3); |
178 | + return ports.stream() | ||
200 | .filter(p -> p.id().startsWith(uuid)) | 179 | .filter(p -> p.id().startsWith(uuid)) |
201 | - .findFirst().get().clone(); | 180 | + .findFirst().orElse(null); |
202 | } | 181 | } |
203 | 182 | ||
204 | @Override | 183 | @Override |
205 | - public OpenstackNetwork network(String networkId) { | 184 | + public OpenstackPort port(String portId) { |
206 | - OpenstackNetwork on = null; | 185 | + Collection<OpenstackPort> ports = restHandler.getPorts(); |
207 | - try { | 186 | + return ports.stream() |
208 | - on = (OpenstackNetwork) openstackNetworkMap.get(networkId).clone(); | 187 | + .filter(p -> p.id().equals(portId)) |
209 | - } catch (CloneNotSupportedException e) { | 188 | + .findFirst().orElse(null); |
210 | - log.error("Cloning is not supported {}", e); | ||
211 | } | 189 | } |
212 | - return on; | 190 | + |
191 | + @Override | ||
192 | + public OpenstackNetwork network(String networkId) { | ||
193 | + Collection<OpenstackNetwork> networks = restHandler.getNetworks(); | ||
194 | + return networks.stream() | ||
195 | + .filter(n -> n.id().equals(networkId)) | ||
196 | + .findFirst().orElse(null); | ||
213 | } | 197 | } |
214 | 198 | ||
215 | private void processDeviceAdded(Device device) { | 199 | private void processDeviceAdded(Device device) { |
216 | log.debug("device {} is added", device.id()); | 200 | log.debug("device {} is added", device.id()); |
217 | - rulePopulator.populateDefaultRules(device.id()); | ||
218 | } | 201 | } |
219 | 202 | ||
220 | private void processPortAdded(Device device, Port port) { | 203 | private void processPortAdded(Device device, Port port) { |
221 | - // TODO: Simplify the data structure to store the network info | ||
222 | - // TODO: Make it stateless | ||
223 | - // TODO: All the logics need to be processed inside of the rulePopulator class | ||
224 | - synchronized (vniPortMap) { | ||
225 | - log.debug("port {} is updated", port.toString()); | ||
226 | - | ||
227 | - updatePortMaps(device, port); | ||
228 | if (!port.annotations().value("portName").equals("vxlan")) { | 204 | if (!port.annotations().value("portName").equals("vxlan")) { |
229 | - populateFlowRulesForTrafficToSameCnode(device, port); | 205 | + OpenstackSwitchingRulePopulator rulePopulator = |
230 | - populateFlowRulesForTrafficToDifferentCnode(device, port); | 206 | + new OpenstackSwitchingRulePopulator(appId, flowObjectiveService, |
231 | - } | 207 | + deviceService, restHandler, driverService); |
208 | + rulePopulator.populateSwitchingRules(device, port); | ||
232 | } | 209 | } |
233 | } | 210 | } |
234 | 211 | ||
235 | private void processPortRemoved(Device device, Port port) { | 212 | private void processPortRemoved(Device device, Port port) { |
213 | + // TODO: Remove flow rules for the VM removed | ||
236 | log.debug("port {} is removed", port.toString()); | 214 | log.debug("port {} is removed", port.toString()); |
237 | - // TODO: need to update the vniPortMap | ||
238 | } | 215 | } |
239 | 216 | ||
240 | private void registerDhcpInfo(OpenstackPort openstackPort) { | 217 | private void registerDhcpInfo(OpenstackPort openstackPort) { |
... | @@ -247,7 +224,7 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService { | ... | @@ -247,7 +224,7 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService { |
247 | 224 | ||
248 | ip4Address = (Ip4Address) openstackPort.fixedIps().values().toArray()[0]; | 225 | ip4Address = (Ip4Address) openstackPort.fixedIps().values().toArray()[0]; |
249 | 226 | ||
250 | - openstackSubnet = openstackSubnetMap.values().stream() | 227 | + openstackSubnet = restHandler.getSubnets().stream() |
251 | .filter(n -> n.networkId().equals(openstackPort.networkId())) | 228 | .filter(n -> n.networkId().equals(openstackPort.networkId())) |
252 | .findFirst().get(); | 229 | .findFirst().get(); |
253 | 230 | ||
... | @@ -280,180 +257,7 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService { | ... | @@ -280,180 +257,7 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService { |
280 | return bytes; | 257 | return bytes; |
281 | } | 258 | } |
282 | 259 | ||
283 | - /** | ||
284 | - * Populates the flow rules for traffic to VMs in different Cnode using | ||
285 | - * Nicira extention. | ||
286 | - * | ||
287 | - * @param device device to put rules | ||
288 | - * @param port port information of the VM | ||
289 | - */ | ||
290 | - private void populateFlowRulesForTrafficToDifferentCnode(Device device, Port port) { | ||
291 | - String portName = port.annotations().value("portName"); | ||
292 | - String channelId = device.annotations().value("channelId"); | ||
293 | - Ip4Address hostIpAddress = Ip4Address.valueOf(channelId.split(":")[0]); | ||
294 | - Ip4Address fixedIp = getFixedIpAddressForPort(portName); | ||
295 | - // TODO: Avoid duplicate flow rule set up for VMs in other Cnode | ||
296 | - // (possibly avoided by flowrule subsystem?) | ||
297 | - if (tunnelPortMap.get(hostIpAddress) == null) { | ||
298 | - log.debug("There is no tunnel port information"); | ||
299 | - return; | ||
300 | - } | ||
301 | - String vni = getVniForPort(portName); | ||
302 | - MacAddress vmMac = getVmMacAddressForPort(portName); | ||
303 | - if (!vniPortMap.isEmpty() && vniPortMap.get(vni) != null) { | ||
304 | - for (PortInfo portInfo : vniPortMap.get(vni)) { | ||
305 | - if (!portInfo.portName.equals(portName) && | ||
306 | - !portInfo.hostIp.equals(hostIpAddress)) { | ||
307 | - MacAddress vmMacx = getVmMacAddressForPort(portInfo.portName); | ||
308 | - rulePopulator.populateForwardingRuleForOtherCnode(vni, | ||
309 | - device.id(), portInfo.hostIp, portInfo.fixedIp, vmMacx, | ||
310 | - tunnelPortMap.get(hostIpAddress).number(), | ||
311 | - portInfo.deviceId, hostIpAddress, fixedIp, vmMac, | ||
312 | - tunnelPortMap.get(portInfo.hostIp).number()); | ||
313 | - } | ||
314 | - } | ||
315 | - } | ||
316 | - } | ||
317 | 260 | ||
318 | - /** | ||
319 | - * Populates the flow rules for traffic to VMs in the same Cnode as the sender. | ||
320 | - * | ||
321 | - * @param device device to put the rules | ||
322 | - * @param port port info of the VM | ||
323 | - */ | ||
324 | - private void populateFlowRulesForTrafficToSameCnode(Device device, Port port) { | ||
325 | - Ip4Prefix cidr = getCidrForPort(port.annotations().value("portName")); | ||
326 | - Ip4Address vmIp = getFixedIpAddressForPort(port.annotations().value("portName")); | ||
327 | - if (vmIp != null) { | ||
328 | - rulePopulator.populateForwardingRule(vmIp, device.id(), port, cidr); | ||
329 | - } | ||
330 | - } | ||
331 | - | ||
332 | - /** | ||
333 | - * Updates the port maps using the port information. | ||
334 | - * | ||
335 | - * @param device device info | ||
336 | - * @param port port of the VM | ||
337 | - */ | ||
338 | - private void updatePortMaps(Device device, Port port) { | ||
339 | - String portName = port.annotations().value("portName"); | ||
340 | - String channelId = device.annotations().value("channelId"); | ||
341 | - Ip4Address hostIpAddress = Ip4Address.valueOf(channelId.split(":")[0]); | ||
342 | - if (portName.startsWith("vxlan")) { | ||
343 | - tunnelPortMap.put(hostIpAddress, port); | ||
344 | - } else { | ||
345 | - String vni = getVniForPort(portName); | ||
346 | - Ip4Address fixedIp = getFixedIpAddressForPort(portName); | ||
347 | - if (vniPortMap.get(vni) == null) { | ||
348 | - vniPortMap.put(vni, Lists.newArrayList()); | ||
349 | - } | ||
350 | - vniPortMap.get(vni).add(new PortInfo(device.id(), portName, fixedIp, hostIpAddress)); | ||
351 | - } | ||
352 | - } | ||
353 | - | ||
354 | - /** | ||
355 | - * Returns CIDR information from the subnet map for the port. | ||
356 | - * | ||
357 | - * @param portName port name of the port of the VM | ||
358 | - * @return CIDR of the VNI of the VM | ||
359 | - */ | ||
360 | - private Ip4Prefix getCidrForPort(String portName) { | ||
361 | - String networkId = null; | ||
362 | - String uuid = portName.substring(3); | ||
363 | - OpenstackPort port = openstackPortMap.values().stream() | ||
364 | - .filter(p -> p.id().startsWith(uuid)) | ||
365 | - .findFirst().get(); | ||
366 | - if (port == null) { | ||
367 | - log.debug("No port information for port {}", portName); | ||
368 | - return null; | ||
369 | - } | ||
370 | - | ||
371 | - OpenstackSubnet subnet = openstackSubnetMap.values().stream() | ||
372 | - .filter(s -> s.networkId().equals(port.networkId())) | ||
373 | - .findFirst().get(); | ||
374 | - if (subnet == null) { | ||
375 | - log.debug("No subnet information for network {}", port.networkId()); | ||
376 | - return null; | ||
377 | - } | ||
378 | - | ||
379 | - return Ip4Prefix.valueOf(subnet.cidr()); | ||
380 | - } | ||
381 | - | ||
382 | - /** | ||
383 | - * Returns the VNI of the VM of the port. | ||
384 | - * | ||
385 | - * @param portName VM port | ||
386 | - * @return VNI | ||
387 | - */ | ||
388 | - private String getVniForPort(String portName) { | ||
389 | - String networkId = null; | ||
390 | - String uuid = portName.substring(3); | ||
391 | - OpenstackPort port = openstackPortMap.values().stream() | ||
392 | - .filter(p -> p.id().startsWith(uuid)) | ||
393 | - .findFirst().get(); | ||
394 | - if (port == null) { | ||
395 | - log.debug("No port information for port {}", portName); | ||
396 | - return null; | ||
397 | - } | ||
398 | - OpenstackNetwork network = openstackNetworkMap.values().stream() | ||
399 | - .filter(n -> n.id().equals(port.networkId())) | ||
400 | - .findFirst().get(); | ||
401 | - if (network == null) { | ||
402 | - log.debug("No VNI information for network {}", network.id()); | ||
403 | - return null; | ||
404 | - } | ||
405 | - | ||
406 | - return network.segmentId(); | ||
407 | - } | ||
408 | - | ||
409 | - /** | ||
410 | - * Returns the Fixed IP address of the VM. | ||
411 | - * | ||
412 | - * @param portName VM port info | ||
413 | - * @return IP address of the VM | ||
414 | - */ | ||
415 | - private Ip4Address getFixedIpAddressForPort(String portName) { | ||
416 | - | ||
417 | - // FIXME - For now we use the information stored from neutron Rest API call. | ||
418 | - // TODO - Later, the information needs to be extracted from Neutron on-demand. | ||
419 | - String uuid = portName.substring(3); | ||
420 | - OpenstackPort port = openstackPortMap.values().stream() | ||
421 | - .filter(p -> p.id().startsWith(uuid)) | ||
422 | - .findFirst().get(); | ||
423 | - | ||
424 | - if (port == null) { | ||
425 | - log.error("There is no port information for port name {}", portName); | ||
426 | - return null; | ||
427 | - } | ||
428 | - | ||
429 | - if (port.fixedIps().isEmpty()) { | ||
430 | - log.error("There is no fixed IP info in the port information"); | ||
431 | - return null; | ||
432 | - } | ||
433 | - | ||
434 | - return (Ip4Address) port.fixedIps().values().toArray()[0]; | ||
435 | - } | ||
436 | - | ||
437 | - /** | ||
438 | - * Returns the MAC address of the VM of the port. | ||
439 | - * | ||
440 | - * @param portName VM port | ||
441 | - * @return MAC address of the VM | ||
442 | - */ | ||
443 | - private MacAddress getVmMacAddressForPort(String portName) { | ||
444 | - | ||
445 | - String uuid = portName.substring(3); | ||
446 | - OpenstackPort port = openstackPortMap.values().stream() | ||
447 | - .filter(p -> p.id().startsWith(uuid)) | ||
448 | - .findFirst().get(); | ||
449 | - | ||
450 | - if (port == null) { | ||
451 | - log.error("There is no mac information for port name {}", portName); | ||
452 | - return null; | ||
453 | - } | ||
454 | - | ||
455 | - return port.macAddress(); | ||
456 | - } | ||
457 | 261 | ||
458 | private class InternalPacketProcessor implements PacketProcessor { | 262 | private class InternalPacketProcessor implements PacketProcessor { |
459 | 263 | ||
... | @@ -529,19 +333,27 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService { | ... | @@ -529,19 +333,27 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService { |
529 | 333 | ||
530 | private class InternalConfigListener implements NetworkConfigListener { | 334 | private class InternalConfigListener implements NetworkConfigListener { |
531 | 335 | ||
336 | + public void configureNetwork() { | ||
337 | + OpenstackSwitchingConfig cfg = | ||
338 | + cfgService.getConfig(appId, OpenstackSwitchingConfig.class); | ||
339 | + if (cfg == null) { | ||
340 | + log.error("There is no openstack server information in config."); | ||
341 | + return; | ||
342 | + } | ||
343 | + doNotPushFlows = cfg.doNotPushFlows(); | ||
344 | + restHandler = new OpenstackRestHandler(cfg); | ||
345 | + arpHandler = new OpenstackArpHandler(restHandler, packetService); | ||
346 | + } | ||
347 | + | ||
532 | @Override | 348 | @Override |
533 | public void event(NetworkConfigEvent event) { | 349 | public void event(NetworkConfigEvent event) { |
534 | if (((event.type() == NetworkConfigEvent.Type.CONFIG_ADDED || | 350 | if (((event.type() == NetworkConfigEvent.Type.CONFIG_ADDED || |
535 | event.type() == NetworkConfigEvent.Type.CONFIG_UPDATED)) && | 351 | event.type() == NetworkConfigEvent.Type.CONFIG_UPDATED)) && |
536 | event.configClass().equals(OpenstackSwitchingConfig.class)) { | 352 | event.configClass().equals(OpenstackSwitchingConfig.class)) { |
537 | - OpenstackSwitchingConfig cfg = cfgService.getConfig(appId, | 353 | + configureNetwork(); |
538 | - OpenstackSwitchingConfig.class); | ||
539 | - if (cfg != null) { | ||
540 | - doNotPushFlows = cfg.doNotPushFlows(); | ||
541 | - log.info("Switching mode reconfigured"); | ||
542 | - } | ||
543 | } | 354 | } |
544 | } | 355 | } |
356 | + | ||
545 | } | 357 | } |
546 | 358 | ||
547 | private final class PortInfo { | 359 | private final class PortInfo { | ... | ... |
... | @@ -17,25 +17,35 @@ | ... | @@ -17,25 +17,35 @@ |
17 | package org.onosproject.openstackswitching; | 17 | package org.onosproject.openstackswitching; |
18 | 18 | ||
19 | import org.onlab.packet.Ethernet; | 19 | import org.onlab.packet.Ethernet; |
20 | -import org.onlab.packet.IPv4; | ||
21 | import org.onlab.packet.Ip4Address; | 20 | import org.onlab.packet.Ip4Address; |
22 | -import org.onlab.packet.Ip4Prefix; | ||
23 | import org.onlab.packet.MacAddress; | 21 | import org.onlab.packet.MacAddress; |
24 | -import org.onlab.packet.TpPort; | ||
25 | import org.onosproject.core.ApplicationId; | 22 | import org.onosproject.core.ApplicationId; |
23 | +import org.onosproject.net.Device; | ||
26 | import org.onosproject.net.DeviceId; | 24 | import org.onosproject.net.DeviceId; |
27 | import org.onosproject.net.Port; | 25 | import org.onosproject.net.Port; |
28 | import org.onosproject.net.PortNumber; | 26 | import org.onosproject.net.PortNumber; |
27 | +import org.onosproject.net.behaviour.ExtensionTreatmentResolver; | ||
28 | +import org.onosproject.net.device.DeviceService; | ||
29 | +import org.onosproject.net.driver.DefaultDriverData; | ||
30 | +import org.onosproject.net.driver.DefaultDriverHandler; | ||
31 | +import org.onosproject.net.driver.Driver; | ||
32 | +import org.onosproject.net.driver.DriverHandler; | ||
33 | +import org.onosproject.net.driver.DriverService; | ||
29 | import org.onosproject.net.flow.DefaultTrafficSelector; | 34 | import org.onosproject.net.flow.DefaultTrafficSelector; |
30 | import org.onosproject.net.flow.DefaultTrafficTreatment; | 35 | import org.onosproject.net.flow.DefaultTrafficTreatment; |
31 | import org.onosproject.net.flow.TrafficSelector; | 36 | import org.onosproject.net.flow.TrafficSelector; |
32 | import org.onosproject.net.flow.TrafficTreatment; | 37 | import org.onosproject.net.flow.TrafficTreatment; |
38 | +import org.onosproject.net.flow.instructions.ExtensionTreatment; | ||
39 | +import org.onosproject.net.flow.instructions.ExtensionPropertyException; | ||
40 | +import org.onosproject.net.flow.instructions.ExtensionTreatmentType; | ||
33 | import org.onosproject.net.flowobjective.DefaultForwardingObjective; | 41 | import org.onosproject.net.flowobjective.DefaultForwardingObjective; |
34 | import org.onosproject.net.flowobjective.FlowObjectiveService; | 42 | import org.onosproject.net.flowobjective.FlowObjectiveService; |
35 | import org.onosproject.net.flowobjective.ForwardingObjective; | 43 | import org.onosproject.net.flowobjective.ForwardingObjective; |
36 | import org.slf4j.Logger; | 44 | import org.slf4j.Logger; |
37 | import org.slf4j.LoggerFactory; | 45 | import org.slf4j.LoggerFactory; |
38 | 46 | ||
47 | +import java.util.Collection; | ||
48 | + | ||
39 | /** | 49 | /** |
40 | * Populates switching flow rules. | 50 | * Populates switching flow rules. |
41 | */ | 51 | */ |
... | @@ -43,123 +53,168 @@ public class OpenstackSwitchingRulePopulator { | ... | @@ -43,123 +53,168 @@ public class OpenstackSwitchingRulePopulator { |
43 | 53 | ||
44 | private static Logger log = LoggerFactory | 54 | private static Logger log = LoggerFactory |
45 | .getLogger(OpenstackSwitchingRulePopulator.class); | 55 | .getLogger(OpenstackSwitchingRulePopulator.class); |
56 | + private static final int SWITCHING_RULE_PRIORITY = 50000; | ||
46 | 57 | ||
47 | private FlowObjectiveService flowObjectiveService; | 58 | private FlowObjectiveService flowObjectiveService; |
59 | + private DriverService driverService; | ||
60 | + private DeviceService deviceService; | ||
61 | + private OpenstackRestHandler restHandler; | ||
48 | private ApplicationId appId; | 62 | private ApplicationId appId; |
49 | 63 | ||
64 | + private Collection<OpenstackNetwork> openstackNetworkList; | ||
65 | + private Collection<OpenstackPort> openstackPortList; | ||
66 | + | ||
50 | /** | 67 | /** |
51 | * Creates OpenstackSwitchingRulPopulator. | 68 | * Creates OpenstackSwitchingRulPopulator. |
52 | * | 69 | * |
53 | * @param appId application id | 70 | * @param appId application id |
54 | * @param flowObjectiveService FlowObjectiveService reference | 71 | * @param flowObjectiveService FlowObjectiveService reference |
72 | + * @param deviceService DeviceService reference | ||
73 | + * @param driverService DriverService reference | ||
55 | */ | 74 | */ |
56 | public OpenstackSwitchingRulePopulator(ApplicationId appId, | 75 | public OpenstackSwitchingRulePopulator(ApplicationId appId, |
57 | - FlowObjectiveService flowObjectiveService) { | 76 | + FlowObjectiveService flowObjectiveService, |
77 | + DeviceService deviceService, | ||
78 | + OpenstackRestHandler restHandler, | ||
79 | + DriverService driverService) { | ||
58 | this.flowObjectiveService = flowObjectiveService; | 80 | this.flowObjectiveService = flowObjectiveService; |
81 | + this.deviceService = deviceService; | ||
82 | + this.driverService = driverService; | ||
83 | + this.restHandler = restHandler; | ||
59 | this.appId = appId; | 84 | this.appId = appId; |
85 | + | ||
86 | + openstackNetworkList = restHandler.getNetworks(); | ||
87 | + openstackPortList = restHandler.getPorts(); | ||
60 | } | 88 | } |
61 | 89 | ||
62 | /** | 90 | /** |
63 | - * Populates flows rules for forwarding packets to and from VMs. | 91 | + * Populates flow rules for the VM created. |
64 | * | 92 | * |
65 | - * @param ip v4 IP Address | 93 | + * @param device device to populate rules to |
66 | - * @param id device ID | 94 | + * @param port port for the VM created |
67 | - * @param port port | ||
68 | - * @param cidr v4 IP prefix | ||
69 | - * @return true if it succeeds to populate rules, false otherwise. | ||
70 | */ | 95 | */ |
71 | - public boolean populateForwardingRule(Ip4Address ip, DeviceId id, Port port, Ip4Prefix cidr) { | 96 | + public void populateSwitchingRules(Device device, Port port) { |
72 | - | 97 | + populateFlowRulesForTrafficToSameCnode(device, port); |
73 | - | 98 | + populateFlowRulesForTrafficToDifferentCnode(device, port); |
74 | - setFlowRuleForVMsInSameCnode(ip, id, port, cidr); | ||
75 | - | ||
76 | - return true; | ||
77 | } | 99 | } |
78 | 100 | ||
79 | /** | 101 | /** |
80 | - * Populates the common flows rules for all VMs. | 102 | + * Populates the flow rules for traffic to VMs in the same Cnode as the sender. |
81 | * | 103 | * |
82 | - * - Send ARP packets to the controller | 104 | + * @param device device to put the rules |
83 | - * - Send DHCP packets to the controller | 105 | + * @param port port info of the VM |
84 | - * | ||
85 | - * @param id Device ID to populates rules to | ||
86 | */ | 106 | */ |
87 | - public void populateDefaultRules(DeviceId id) { | 107 | + private void populateFlowRulesForTrafficToSameCnode(Device device, Port port) { |
108 | + Ip4Address vmIp = getFixedIpAddressForPort(port.annotations().value("portName")); | ||
109 | + if (vmIp != null) { | ||
110 | + setFlowRuleForVMsInSameCnode(vmIp, device.id(), port); | ||
111 | + } | ||
112 | + } | ||
88 | 113 | ||
89 | - setFlowRuleForArp(id); | 114 | + /** |
115 | + * Populates the flow rules for traffic to VMs in different Cnode using | ||
116 | + * Nicira extention. | ||
117 | + * | ||
118 | + * @param device device to put rules | ||
119 | + * @param port port information of the VM | ||
120 | + */ | ||
121 | + private void populateFlowRulesForTrafficToDifferentCnode(Device device, Port port) { | ||
122 | + String portName = port.annotations().value("portName"); | ||
123 | + String channelId = device.annotations().value("channelId"); | ||
124 | + Ip4Address hostIpAddress = Ip4Address.valueOf(channelId.split(":")[0]); | ||
125 | + Ip4Address fixedIp = getFixedIpAddressForPort(portName); | ||
126 | + MacAddress vmMac = getVmMacAddressForPort(portName); | ||
127 | + String vni = getVniForPort(portName); | ||
128 | + deviceService.getAvailableDevices().forEach(d -> { | ||
129 | + if (!d.equals(device)) { | ||
130 | + deviceService.getPorts(d.id()).forEach(p -> { | ||
131 | + String pName = p.annotations().value("portName"); | ||
132 | + if (!p.equals(port) && vni.equals(getVniForPort(pName))) { | ||
133 | + String cidx = d.annotations().value("channelId"); | ||
134 | + Ip4Address hostIpx = Ip4Address.valueOf(cidx.split(":")[0]); | ||
135 | + MacAddress vmMacx = getVmMacAddressForPort(pName); | ||
136 | + Ip4Address fixedIpx = getFixedIpAddressForPort(pName); | ||
90 | 137 | ||
91 | - log.warn("Default rule has been set"); | 138 | + setVxLanFlowRule(vni, device.id(), hostIpx, fixedIpx, vmMacx); |
139 | + setVxLanFlowRule(vni, d.id(), hostIpAddress, fixedIp, vmMac); | ||
140 | + } | ||
141 | + }); | ||
142 | + } | ||
143 | + }); | ||
92 | } | 144 | } |
93 | 145 | ||
94 | /** | 146 | /** |
95 | - * Populates the forwarding rules for VMs with the same VNI but in other Code. | 147 | + * Returns the VNI of the VM of the port. |
96 | * | 148 | * |
97 | - * @param vni VNI for the networks | 149 | + * @param portName VM port |
98 | - * @param id device ID to populates the flow rules | 150 | + * @return VNI |
99 | - * @param hostIp host IP address of the VM | ||
100 | - * @param vmIp fixed IP address for the VM | ||
101 | - * @param vmMac MAC address for the VM | ||
102 | - * @param tunnelPort tunnel port number for the VM | ||
103 | - * @param idx device ID for OVS of the other VM | ||
104 | - * @param hostIpx host IP address of the other VM | ||
105 | - * @param vmIpx fixed IP address of the other VM | ||
106 | - * @param vmMacx MAC address for the other VM | ||
107 | - * @param tunnelPortx x tunnel port number for other VM | ||
108 | */ | 151 | */ |
109 | - public void populateForwardingRuleForOtherCnode(String vni, DeviceId id, Ip4Address hostIp, | 152 | + private String getVniForPort(String portName) { |
110 | - Ip4Address vmIp, MacAddress vmMac, PortNumber tunnelPort, | 153 | + String uuid = portName.substring(3); |
111 | - DeviceId idx, Ip4Address hostIpx, | 154 | + OpenstackPort port = openstackPortList.stream() |
112 | - Ip4Address vmIpx, MacAddress vmMacx, PortNumber tunnelPortx) { | 155 | + .filter(p -> p.id().startsWith(uuid)) |
113 | - setVxLanFlowRule(vni, id, hostIp, vmIp, vmMac, tunnelPort); | 156 | + .findAny().orElse(null); |
114 | - setVxLanFlowRule(vni, idx, hostIpx, vmIpx, vmMacx, tunnelPortx); | 157 | + if (port == null) { |
158 | + log.warn("No port information for port {}", portName); | ||
159 | + return null; | ||
160 | + } | ||
161 | + | ||
162 | + OpenstackNetwork network = openstackNetworkList.stream() | ||
163 | + .filter(n -> n.id().equals(port.networkId())) | ||
164 | + .findAny().orElse(null); | ||
165 | + if (network == null) { | ||
166 | + log.warn("No VNI information for network {}", network.id()); | ||
167 | + return null; | ||
168 | + } | ||
169 | + | ||
170 | + return network.segmentId(); | ||
115 | } | 171 | } |
116 | 172 | ||
117 | /** | 173 | /** |
118 | - * Populates the flow rules for DHCP packets from VMs. | 174 | + * Returns the Fixed IP address of the VM. |
119 | * | 175 | * |
120 | - * @param id device ID to set the rules | 176 | + * @param portName VM port info |
177 | + * @return IP address of the VM | ||
121 | */ | 178 | */ |
122 | - private void setFlowRuleForDhcp(DeviceId id) { | 179 | + private Ip4Address getFixedIpAddressForPort(String portName) { |
123 | - TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder(); | ||
124 | - TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder(); | ||
125 | 180 | ||
126 | - sBuilder.matchEthType(Ethernet.TYPE_IPV4) | 181 | + String uuid = portName.substring(3); |
127 | - .matchIPProtocol(IPv4.PROTOCOL_UDP) | 182 | + OpenstackPort port = openstackPortList.stream() |
128 | - .matchUdpDst(TpPort.tpPort(OpenstackSwitchingManager.DHCP_PORT)); | 183 | + .filter(p -> p.id().startsWith(uuid)) |
129 | - tBuilder.setOutput(PortNumber.CONTROLLER); | 184 | + .findFirst().orElse(null); |
130 | 185 | ||
131 | - ForwardingObjective fo = DefaultForwardingObjective.builder() | 186 | + if (port == null) { |
132 | - .withSelector(sBuilder.build()) | 187 | + log.error("There is no port information for port name {}", portName); |
133 | - .withTreatment(tBuilder.build()) | 188 | + return null; |
134 | - .withPriority(5000) | 189 | + } |
135 | - .withFlag(ForwardingObjective.Flag.VERSATILE) | ||
136 | - .fromApp(appId) | ||
137 | - .add(); | ||
138 | 190 | ||
139 | - flowObjectiveService.forward(id, fo); | 191 | + if (port.fixedIps().isEmpty()) { |
192 | + log.error("There is no fixed IP info in the port information"); | ||
193 | + return null; | ||
194 | + } | ||
195 | + | ||
196 | + return (Ip4Address) port.fixedIps().values().toArray()[0]; | ||
140 | } | 197 | } |
141 | 198 | ||
142 | /** | 199 | /** |
143 | - * Populates the flow rules for ARP packets from VMs. | 200 | + * Returns the MAC address of the VM of the port. |
144 | * | 201 | * |
145 | - * @param id device ID to put rules. | 202 | + * @param portName VM port |
203 | + * @return MAC address of the VM | ||
146 | */ | 204 | */ |
147 | - private void setFlowRuleForArp(DeviceId id) { | 205 | + private MacAddress getVmMacAddressForPort(String portName) { |
148 | - TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder(); | ||
149 | - TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder(); | ||
150 | 206 | ||
151 | - sBuilder.matchEthType(Ethernet.TYPE_ARP); | 207 | + String uuid = portName.substring(3); |
152 | - tBuilder.setOutput(PortNumber.CONTROLLER); | 208 | + OpenstackPort port = openstackPortList.stream() |
209 | + .filter(p -> p.id().startsWith(uuid)) | ||
210 | + .findFirst().orElse(null); | ||
153 | 211 | ||
154 | - ForwardingObjective fo = DefaultForwardingObjective.builder() | 212 | + if (port == null) { |
155 | - .withSelector(sBuilder.build()) | 213 | + log.error("There is port information for port name {}", portName); |
156 | - .withTreatment(tBuilder.build()) | 214 | + return null; |
157 | - .withPriority(5000) | 215 | + } |
158 | - .withFlag(ForwardingObjective.Flag.VERSATILE) | ||
159 | - .fromApp(appId) | ||
160 | - .add(); | ||
161 | 216 | ||
162 | - flowObjectiveService.forward(id, fo); | 217 | + return port.macAddress(); |
163 | } | 218 | } |
164 | 219 | ||
165 | /** | 220 | /** |
... | @@ -168,22 +223,20 @@ public class OpenstackSwitchingRulePopulator { | ... | @@ -168,22 +223,20 @@ public class OpenstackSwitchingRulePopulator { |
168 | * @param ip4Address VM IP address | 223 | * @param ip4Address VM IP address |
169 | * @param id device ID to put rules | 224 | * @param id device ID to put rules |
170 | * @param port VM port | 225 | * @param port VM port |
171 | - * @param cidr subnet info of the VMs | ||
172 | */ | 226 | */ |
173 | private void setFlowRuleForVMsInSameCnode(Ip4Address ip4Address, DeviceId id, | 227 | private void setFlowRuleForVMsInSameCnode(Ip4Address ip4Address, DeviceId id, |
174 | - Port port, Ip4Prefix cidr) { | 228 | + Port port) { |
175 | TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder(); | 229 | TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder(); |
176 | TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder(); | 230 | TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder(); |
177 | 231 | ||
178 | sBuilder.matchEthType(Ethernet.TYPE_IPV4) | 232 | sBuilder.matchEthType(Ethernet.TYPE_IPV4) |
179 | - .matchIPDst(ip4Address.toIpPrefix()) | 233 | + .matchIPDst(ip4Address.toIpPrefix()); |
180 | - .matchIPSrc(cidr); | ||
181 | tBuilder.setOutput(port.number()); | 234 | tBuilder.setOutput(port.number()); |
182 | 235 | ||
183 | ForwardingObjective fo = DefaultForwardingObjective.builder() | 236 | ForwardingObjective fo = DefaultForwardingObjective.builder() |
184 | .withSelector(sBuilder.build()) | 237 | .withSelector(sBuilder.build()) |
185 | .withTreatment(tBuilder.build()) | 238 | .withTreatment(tBuilder.build()) |
186 | - .withPriority(5000) | 239 | + .withPriority(SWITCHING_RULE_PRIORITY) |
187 | .withFlag(ForwardingObjective.Flag.VERSATILE) | 240 | .withFlag(ForwardingObjective.Flag.VERSATILE) |
188 | .fromApp(appId) | 241 | .fromApp(appId) |
189 | .add(); | 242 | .add(); |
... | @@ -199,28 +252,56 @@ public class OpenstackSwitchingRulePopulator { | ... | @@ -199,28 +252,56 @@ public class OpenstackSwitchingRulePopulator { |
199 | * @param hostIp host IP of the VM | 252 | * @param hostIp host IP of the VM |
200 | * @param vmIp fixed IP of the VM | 253 | * @param vmIp fixed IP of the VM |
201 | * @param vmMac MAC address of the VM | 254 | * @param vmMac MAC address of the VM |
202 | - * @param tunnelPort tunnel port to forward traffic to | ||
203 | */ | 255 | */ |
204 | private void setVxLanFlowRule(String vni, DeviceId id, Ip4Address hostIp, | 256 | private void setVxLanFlowRule(String vni, DeviceId id, Ip4Address hostIp, |
205 | - Ip4Address vmIp, MacAddress vmMac, PortNumber tunnelPort) { | 257 | + Ip4Address vmIp, MacAddress vmMac) { |
206 | TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder(); | 258 | TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder(); |
207 | TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder(); | 259 | TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder(); |
208 | 260 | ||
209 | sBuilder.matchEthType(Ethernet.TYPE_IPV4) | 261 | sBuilder.matchEthType(Ethernet.TYPE_IPV4) |
210 | .matchIPDst(vmIp.toIpPrefix()); | 262 | .matchIPDst(vmIp.toIpPrefix()); |
211 | tBuilder.setTunnelId(Long.parseLong(vni)) | 263 | tBuilder.setTunnelId(Long.parseLong(vni)) |
212 | - //.setTunnelDst() <- for Nicira ext | 264 | + .extension(buildNiciraExtenstion(id, hostIp), id) |
213 | - //.setEthDst(vmMac) | 265 | + .setOutput(getTunnelPort(id)); |
214 | - .setOutput(tunnelPort); | ||
215 | 266 | ||
216 | ForwardingObjective fo = DefaultForwardingObjective.builder() | 267 | ForwardingObjective fo = DefaultForwardingObjective.builder() |
217 | .withSelector(sBuilder.build()) | 268 | .withSelector(sBuilder.build()) |
218 | .withTreatment(tBuilder.build()) | 269 | .withTreatment(tBuilder.build()) |
219 | - .withPriority(5000) | 270 | + .withPriority(SWITCHING_RULE_PRIORITY) |
220 | .withFlag(ForwardingObjective.Flag.VERSATILE) | 271 | .withFlag(ForwardingObjective.Flag.VERSATILE) |
221 | .fromApp(appId) | 272 | .fromApp(appId) |
222 | .add(); | 273 | .add(); |
223 | 274 | ||
224 | flowObjectiveService.forward(id, fo); | 275 | flowObjectiveService.forward(id, fo); |
225 | } | 276 | } |
277 | + | ||
278 | + private ExtensionTreatment buildNiciraExtenstion(DeviceId id, Ip4Address hostIp) { | ||
279 | + Driver driver = driverService.getDriver(id); | ||
280 | + DriverHandler driverHandler = new DefaultDriverHandler(new DefaultDriverData(driver, id)); | ||
281 | + ExtensionTreatmentResolver resolver = driverHandler.behaviour(ExtensionTreatmentResolver.class); | ||
282 | + | ||
283 | + ExtensionTreatment extensionInstruction = | ||
284 | + resolver.getExtensionInstruction( | ||
285 | + ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_TUNNEL_DST.type()); | ||
286 | + | ||
287 | + try { | ||
288 | + extensionInstruction.setPropertyValue("tunnelDst", hostIp); | ||
289 | + } catch (ExtensionPropertyException e) { | ||
290 | + log.error("Error setting Nicira extension setting {}", e); | ||
291 | + } | ||
292 | + | ||
293 | + return extensionInstruction; | ||
294 | + } | ||
295 | + | ||
296 | + private PortNumber getTunnelPort(DeviceId id) { | ||
297 | + Port port = deviceService.getPorts(id).stream() | ||
298 | + .filter(p -> p.annotations().value("portName").equals("vxlan")) | ||
299 | + .findAny().orElse(null); | ||
300 | + | ||
301 | + if (port == null) { | ||
302 | + log.error("No TunnelPort was created."); | ||
303 | + return null; | ||
304 | + } | ||
305 | + return port.number(); | ||
306 | + } | ||
226 | } | 307 | } | ... | ... |
... | @@ -43,6 +43,9 @@ public class OpenstackNetworkCodec extends JsonCodec<OpenstackNetwork> { | ... | @@ -43,6 +43,9 @@ public class OpenstackNetworkCodec extends JsonCodec<OpenstackNetwork> { |
43 | public OpenstackNetwork decode(ObjectNode json, CodecContext context) { | 43 | public OpenstackNetwork decode(ObjectNode json, CodecContext context) { |
44 | 44 | ||
45 | JsonNode networkInfo = json.get(NETWORK); | 45 | JsonNode networkInfo = json.get(NETWORK); |
46 | + if (networkInfo == null) { | ||
47 | + networkInfo = json; | ||
48 | + } | ||
46 | 49 | ||
47 | String name = networkInfo.path(NAME).asText(); | 50 | String name = networkInfo.path(NAME).asText(); |
48 | String tenantId = networkInfo.path(TENANT_ID).asText(); | 51 | String tenantId = networkInfo.path(TENANT_ID).asText(); | ... | ... |
... | @@ -15,48 +15,52 @@ | ... | @@ -15,48 +15,52 @@ |
15 | */ | 15 | */ |
16 | package org.onosproject.openstackswitching.web; | 16 | package org.onosproject.openstackswitching.web; |
17 | 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; | 18 | import org.onosproject.rest.AbstractWebResource; |
23 | import org.slf4j.Logger; | 19 | import org.slf4j.Logger; |
24 | import org.slf4j.LoggerFactory; | 20 | import org.slf4j.LoggerFactory; |
25 | 21 | ||
26 | import javax.ws.rs.Consumes; | 22 | import javax.ws.rs.Consumes; |
23 | +import javax.ws.rs.DELETE; | ||
27 | import javax.ws.rs.POST; | 24 | import javax.ws.rs.POST; |
25 | +import javax.ws.rs.PUT; | ||
28 | import javax.ws.rs.Path; | 26 | import javax.ws.rs.Path; |
29 | import javax.ws.rs.Produces; | 27 | import javax.ws.rs.Produces; |
30 | import javax.ws.rs.core.MediaType; | 28 | import javax.ws.rs.core.MediaType; |
31 | import javax.ws.rs.core.Response; | 29 | import javax.ws.rs.core.Response; |
32 | import java.io.InputStream; | 30 | import java.io.InputStream; |
33 | 31 | ||
32 | +/** | ||
33 | + * Handles REST API call of Neutron ML2 plugin. | ||
34 | + */ | ||
34 | @Path("networks") | 35 | @Path("networks") |
35 | public class OpenstackNetworkWebResource extends AbstractWebResource { | 36 | public class OpenstackNetworkWebResource extends AbstractWebResource { |
36 | 37 | ||
37 | protected static final Logger log = LoggerFactory | 38 | protected static final Logger log = LoggerFactory |
38 | .getLogger(OpenstackNetworkWebResource.class); | 39 | .getLogger(OpenstackNetworkWebResource.class); |
39 | 40 | ||
40 | - private static final OpenstackNetworkCodec NETWORK_CODEC = new OpenstackNetworkCodec(); | ||
41 | - | ||
42 | @POST | 41 | @POST |
43 | @Consumes(MediaType.APPLICATION_JSON) | 42 | @Consumes(MediaType.APPLICATION_JSON) |
44 | @Produces(MediaType.APPLICATION_JSON) | 43 | @Produces(MediaType.APPLICATION_JSON) |
45 | public Response createNetwork(InputStream input) { | 44 | public Response createNetwork(InputStream input) { |
46 | - try { | 45 | + log.debug("REST API networks is called {}", input.toString()); |
47 | - ObjectMapper mapper = new ObjectMapper(); | 46 | + return Response.status(Response.Status.OK).build(); |
48 | - ObjectNode networkNode = (ObjectNode) mapper.readTree(input); | 47 | + } |
49 | - | ||
50 | - OpenstackNetwork openstackNetwork = NETWORK_CODEC.decode(networkNode, this); | ||
51 | 48 | ||
52 | - OpenstackSwitchingService switchingService = get(OpenstackSwitchingService.class); | 49 | + @PUT |
53 | - switchingService.createNetwork(openstackNetwork); | 50 | + @Path("{id}") |
51 | + @Consumes(MediaType.APPLICATION_JSON) | ||
52 | + @Produces(MediaType.APPLICATION_JSON) | ||
53 | + public Response updateNetwork(InputStream input) { | ||
54 | + log.debug("REST API networks is called {}", input.toString()); | ||
54 | return Response.status(Response.Status.OK).build(); | 55 | 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 | } | 56 | } |
57 | + | ||
58 | + @DELETE | ||
59 | + @Path("{id}") | ||
60 | + @Consumes(MediaType.APPLICATION_JSON) | ||
61 | + @Produces(MediaType.APPLICATION_JSON) | ||
62 | + public Response deleteNetwork(InputStream input) { | ||
63 | + log.debug("REST API networks is called {}", input.toString()); | ||
64 | + return Response.status(Response.Status.OK).build(); | ||
61 | } | 65 | } |
62 | } | 66 | } | ... | ... |
... | @@ -58,6 +58,9 @@ public class OpenstackPortCodec extends JsonCodec<OpenstackPort> { | ... | @@ -58,6 +58,9 @@ public class OpenstackPortCodec extends JsonCodec<OpenstackPort> { |
58 | 58 | ||
59 | HashMap<String, Ip4Address> fixedIpMap = new HashMap<>(); | 59 | HashMap<String, Ip4Address> fixedIpMap = new HashMap<>(); |
60 | JsonNode portInfo = json.get(PORT); | 60 | JsonNode portInfo = json.get(PORT); |
61 | + if (portInfo == null) { | ||
62 | + portInfo = json; | ||
63 | + } | ||
61 | 64 | ||
62 | String status = portInfo.path(STATUS).asText(); | 65 | String status = portInfo.path(STATUS).asText(); |
63 | String name = portInfo.path(NAME).asText(); | 66 | String name = portInfo.path(NAME).asText(); | ... | ... |
... | @@ -33,6 +33,9 @@ import javax.ws.rs.core.MediaType; | ... | @@ -33,6 +33,9 @@ import javax.ws.rs.core.MediaType; |
33 | import javax.ws.rs.core.Response; | 33 | import javax.ws.rs.core.Response; |
34 | import java.io.InputStream; | 34 | import java.io.InputStream; |
35 | 35 | ||
36 | +/** | ||
37 | + * Handles Rest API call from Neutron ML2 plugin. | ||
38 | + */ | ||
36 | @Path("ports") | 39 | @Path("ports") |
37 | public class OpenstackPortWebResource extends AbstractWebResource { | 40 | public class OpenstackPortWebResource extends AbstractWebResource { |
38 | 41 | ||
... | @@ -50,13 +53,15 @@ public class OpenstackPortWebResource extends AbstractWebResource { | ... | @@ -50,13 +53,15 @@ public class OpenstackPortWebResource extends AbstractWebResource { |
50 | ObjectNode portNode = (ObjectNode) mapper.readTree(input); | 53 | ObjectNode portNode = (ObjectNode) mapper.readTree(input); |
51 | 54 | ||
52 | OpenstackPort openstackPort = PORT_CODEC.decode(portNode, this); | 55 | OpenstackPort openstackPort = PORT_CODEC.decode(portNode, this); |
53 | - | 56 | + OpenstackSwitchingService switchingService = |
54 | - OpenstackSwitchingService switchingService = get(OpenstackSwitchingService.class); | 57 | + getService(OpenstackSwitchingService.class); |
55 | switchingService.createPorts(openstackPort); | 58 | switchingService.createPorts(openstackPort); |
59 | + | ||
56 | log.debug("REST API ports is called with {}", portNode.toString()); | 60 | log.debug("REST API ports is called with {}", portNode.toString()); |
57 | return Response.status(Response.Status.OK).build(); | 61 | return Response.status(Response.Status.OK).build(); |
62 | + | ||
58 | } catch (Exception e) { | 63 | } catch (Exception e) { |
59 | - log.error("Creates VirtualPort failed because of exception {}", | 64 | + log.error("Creates Port failed because of exception {}", |
60 | e.toString()); | 65 | e.toString()); |
61 | return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(e.toString()) | 66 | return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(e.toString()) |
62 | .build(); | 67 | .build(); |
... | @@ -64,23 +69,12 @@ public class OpenstackPortWebResource extends AbstractWebResource { | ... | @@ -64,23 +69,12 @@ public class OpenstackPortWebResource extends AbstractWebResource { |
64 | } | 69 | } |
65 | 70 | ||
66 | @DELETE | 71 | @DELETE |
72 | + @Path("{id}") | ||
67 | @Consumes(MediaType.APPLICATION_JSON) | 73 | @Consumes(MediaType.APPLICATION_JSON) |
68 | @Produces(MediaType.APPLICATION_JSON) | 74 | @Produces(MediaType.APPLICATION_JSON) |
69 | public Response deletesPorts(InputStream input) { | 75 | public Response deletesPorts(InputStream input) { |
70 | - try { | 76 | + log.debug("REST API ports is called with {}", input.toString()); |
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(); | 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 | } | 78 | } |
85 | 79 | ||
86 | @PUT | 80 | @PUT |
... | @@ -88,19 +82,7 @@ public class OpenstackPortWebResource extends AbstractWebResource { | ... | @@ -88,19 +82,7 @@ public class OpenstackPortWebResource extends AbstractWebResource { |
88 | @Consumes(MediaType.APPLICATION_JSON) | 82 | @Consumes(MediaType.APPLICATION_JSON) |
89 | @Produces(MediaType.APPLICATION_JSON) | 83 | @Produces(MediaType.APPLICATION_JSON) |
90 | public Response updatePorts(InputStream input) { | 84 | public Response updatePorts(InputStream input) { |
91 | - try { | 85 | + log.info("REST API ports is called with {}", input.toString()); |
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(); | 86 | 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 | } | 87 | } |
106 | } | 88 | } | ... | ... |
... | @@ -51,6 +51,9 @@ public class OpenstackSubnetCodec extends JsonCodec<OpenstackSubnet> { | ... | @@ -51,6 +51,9 @@ public class OpenstackSubnetCodec extends JsonCodec<OpenstackSubnet> { |
51 | @Override | 51 | @Override |
52 | public OpenstackSubnet decode(ObjectNode json, CodecContext context) { | 52 | public OpenstackSubnet decode(ObjectNode json, CodecContext context) { |
53 | JsonNode subnetInfo = json.get(SUBNET); | 53 | JsonNode subnetInfo = json.get(SUBNET); |
54 | + if (subnetInfo == null) { | ||
55 | + subnetInfo = json; | ||
56 | + } | ||
54 | 57 | ||
55 | String name = subnetInfo.path(NAME).asText(); | 58 | String name = subnetInfo.path(NAME).asText(); |
56 | boolean enableDhcp = subnetInfo.path(ENABLE_DHCP).asBoolean(); | 59 | boolean enableDhcp = subnetInfo.path(ENABLE_DHCP).asBoolean(); | ... | ... |
... | @@ -15,18 +15,19 @@ | ... | @@ -15,18 +15,19 @@ |
15 | */ | 15 | */ |
16 | package org.onosproject.openstackswitching.web; | 16 | package org.onosproject.openstackswitching.web; |
17 | 17 | ||
18 | - | 18 | +/** |
19 | -import com.fasterxml.jackson.databind.ObjectMapper; | 19 | + * Handles Rest API call from Neutron ML2 plugin. |
20 | -import com.fasterxml.jackson.databind.node.ObjectNode; | 20 | + */ |
21 | -import org.onosproject.openstackswitching.OpenstackSubnet; | ||
22 | -import org.onosproject.openstackswitching.OpenstackSwitchingService; | ||
23 | import org.onosproject.rest.AbstractWebResource; | 21 | import org.onosproject.rest.AbstractWebResource; |
24 | import org.slf4j.Logger; | 22 | import org.slf4j.Logger; |
25 | import org.slf4j.LoggerFactory; | 23 | import org.slf4j.LoggerFactory; |
26 | 24 | ||
27 | import javax.ws.rs.Consumes; | 25 | import javax.ws.rs.Consumes; |
26 | +import javax.ws.rs.DELETE; | ||
28 | import javax.ws.rs.POST; | 27 | import javax.ws.rs.POST; |
28 | +import javax.ws.rs.PUT; | ||
29 | import javax.ws.rs.Path; | 29 | import javax.ws.rs.Path; |
30 | +import javax.ws.rs.PathParam; | ||
30 | import javax.ws.rs.Produces; | 31 | import javax.ws.rs.Produces; |
31 | import javax.ws.rs.core.MediaType; | 32 | import javax.ws.rs.core.MediaType; |
32 | import javax.ws.rs.core.Response; | 33 | import javax.ws.rs.core.Response; |
... | @@ -37,28 +38,32 @@ public class OpenstackSubnetWebResource extends AbstractWebResource { | ... | @@ -37,28 +38,32 @@ public class OpenstackSubnetWebResource extends AbstractWebResource { |
37 | protected static final Logger log = LoggerFactory | 38 | protected static final Logger log = LoggerFactory |
38 | .getLogger(OpenstackSubnetWebResource.class); | 39 | .getLogger(OpenstackSubnetWebResource.class); |
39 | 40 | ||
40 | - private static final OpenstackSubnetCodec SUBNET_CODEC = new OpenstackSubnetCodec(); | ||
41 | - | ||
42 | @POST | 41 | @POST |
43 | @Consumes(MediaType.APPLICATION_JSON) | 42 | @Consumes(MediaType.APPLICATION_JSON) |
44 | @Produces(MediaType.APPLICATION_JSON) | 43 | @Produces(MediaType.APPLICATION_JSON) |
45 | public Response createSubnet(InputStream input) { | 44 | public Response createSubnet(InputStream input) { |
46 | - try { | 45 | + return Response.status(Response.Status.OK).build(); |
47 | - ObjectMapper mapper = new ObjectMapper(); | 46 | + } |
48 | - ObjectNode subnetNode = (ObjectNode) mapper.readTree(input); | ||
49 | 47 | ||
50 | - OpenstackSubnet openstackSubnet = SUBNET_CODEC.decode(subnetNode, this); | ||
51 | 48 | ||
52 | - OpenstackSwitchingService switchingService = get(OpenstackSwitchingService.class); | 49 | + @PUT |
53 | - switchingService.createSubnet(openstackSubnet); | 50 | + @Path("{subnetUUID}") |
54 | - log.debug("REST API subnets is called with {}", subnetNode.toString()); | 51 | + @Produces(MediaType.APPLICATION_JSON) |
52 | + @Consumes(MediaType.APPLICATION_JSON) | ||
53 | + public Response updateSubnet(@PathParam("id") String id, | ||
54 | + final InputStream input) { | ||
55 | return Response.status(Response.Status.OK).build(); | 55 | return Response.status(Response.Status.OK).build(); |
56 | - } catch (Exception e) { | 56 | + |
57 | - log.error("Creates VirtualSubnet failed because of exception {}", | ||
58 | - e.toString()); | ||
59 | - return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(e.toString()) | ||
60 | - .build(); | ||
61 | } | 57 | } |
58 | + | ||
59 | + @DELETE | ||
60 | + @Path("{subnetUUID}") | ||
61 | + @Produces(MediaType.APPLICATION_JSON) | ||
62 | + @Consumes(MediaType.APPLICATION_JSON) | ||
63 | + public Response deleteSubnet(@PathParam("id") String id, | ||
64 | + final InputStream input) { | ||
65 | + return Response.status(Response.Status.OK).build(); | ||
62 | } | 66 | } |
63 | 67 | ||
68 | + | ||
64 | } | 69 | } | ... | ... |
apps/openstackswitching/network-cfg.json
0 → 100644
1 | +{ | ||
2 | + "apps" : { | ||
3 | + "org.onosproject.openstackswitching" : { | ||
4 | + "openstackswitching" : { | ||
5 | + "do_not_push_flows" : "false", | ||
6 | + "neutron_server" : "http://127.0.0.1:9696/v2.0/", | ||
7 | + "keystone_server" : "http://127.0.0.1:5000/v2.0/", | ||
8 | + "user_name" : "admin", | ||
9 | + "password" : "nova" | ||
10 | + } | ||
11 | + }, | ||
12 | + "org.onosproject.dhcp" : { | ||
13 | + "dhcp" : { | ||
14 | + "ip": "10.0.0.1", | ||
15 | + "mac": "1a:2b:3c:4e:5e:6f", | ||
16 | + "subnet": "255.0.0.0", | ||
17 | + "broadcast": "10.255.255.255", | ||
18 | + "router": "10.0.0.1", | ||
19 | + "domain": "10.0.0.1", | ||
20 | + "ttl": "63", | ||
21 | + "lease": "300", | ||
22 | + "renew": "150", | ||
23 | + "rebind": "200", | ||
24 | + "delay": "3", | ||
25 | + "timeout": "150", | ||
26 | + "startip": "10.0.0.110", | ||
27 | + "endip": "10.0.0.130" | ||
28 | + } | ||
29 | + }, | ||
30 | + "org.onosproject.cordvtn" : { | ||
31 | + "cordvtn" : { | ||
32 | + "ovsdbNodes" : [ | ||
33 | + { | ||
34 | + "host" : "compute-01", | ||
35 | + "ip" : "128.199.162.106", | ||
36 | + "port" : "6640", | ||
37 | + "bridgeId" : "of:0000000000000001" | ||
38 | + }, | ||
39 | + { | ||
40 | + "host" : "compute-02", | ||
41 | + "ip" : "103.253.145.133", | ||
42 | + "port" : "6640", | ||
43 | + "bridgeId" : "of:0000000000000002" | ||
44 | + }, | ||
45 | + { | ||
46 | + "host" : "network", | ||
47 | + "ip" : "128.199.125.11", | ||
48 | + "port" : "6640", | ||
49 | + "bridgeId" : "of:0000000000000003" | ||
50 | + } | ||
51 | + ] | ||
52 | + } | ||
53 | + } | ||
54 | + } | ||
55 | +} |
-
Please register or login to post a comment