sanghoshin
Committed by Gerrit Code Review

SONA: Openstackswitching

 - Refactored the app to expose APIs to CordVtn App
 - Added clone method in OpenstackPort and OpenstackNetwork
 - Added NetworkConfig to select the working mode of the app
 - Added a few more APIs for getting network topology information
 - Integrated with the modified DhcpService app
Change-Id: I9e266aff10a00d80074d031276864fff195d2b3f
Showing 23 changed files with 510 additions and 152 deletions
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-openstackswitching</artifactId>
25 + <version>1.4.0-SNAPSHOT</version>
26 + <relativePath>../pom.xml</relativePath>
27 + </parent>
28 +
29 + <artifactId>onos-app-openstackswitching-api</artifactId>
30 + <packaging>bundle</packaging>
31 +
32 + <description>SONA Openstack Switching application API</description>
33 +
34 + <dependencies>
35 + <dependency>
36 + <groupId>org.onosproject</groupId>
37 + <artifactId>onos-api</artifactId>
38 + <version>${project.version}</version>
39 + </dependency>
40 + <dependency>
41 + <groupId>org.osgi</groupId>
42 + <artifactId>org.osgi.compendium</artifactId>
43 + </dependency>
44 + <dependency>
45 + <groupId>org.osgi</groupId>
46 + <artifactId>org.osgi.core</artifactId>
47 + </dependency>
48 + </dependencies>
49 +
50 +</project>
...@@ -77,6 +77,11 @@ public final class OpenstackNetwork { ...@@ -77,6 +77,11 @@ public final class OpenstackNetwork {
77 return this.networkType; 77 return this.networkType;
78 } 78 }
79 79
80 + @Override
81 + protected Object clone() throws CloneNotSupportedException {
82 + return super.clone();
83 + }
84 +
80 public static final class Builder { 85 public static final class Builder {
81 private String name; 86 private String name;
82 private String tenantId; 87 private String tenantId;
......
...@@ -19,6 +19,7 @@ import com.google.common.collect.Lists; ...@@ -19,6 +19,7 @@ import com.google.common.collect.Lists;
19 import org.onlab.packet.Ip4Address; 19 import org.onlab.packet.Ip4Address;
20 import org.onlab.packet.MacAddress; 20 import org.onlab.packet.MacAddress;
21 21
22 +import java.util.Collections;
22 import java.util.HashMap; 23 import java.util.HashMap;
23 import java.util.List; 24 import java.util.List;
24 25
...@@ -179,6 +180,16 @@ public final class OpenstackPort { ...@@ -179,6 +180,16 @@ public final class OpenstackPort {
179 // 180 //
180 //} 181 //}
181 182
183 + @Override
184 + public Object clone() {
185 + OpenstackPort op = new OpenstackPort(this.status, this.name, this.adminStateUp,
186 + this.networkId, this.tenantId, this.deviceOwner, this.macAddress,
187 + (HashMap) this.fixedIps.clone(), this.id,
188 + Collections.unmodifiableList(this.securityGroups), this.deviceId);
189 +
190 + return op;
191 + }
192 +
182 /** 193 /**
183 * OpenstackPort Builder class. 194 * OpenstackPort Builder class.
184 */ 195 */
......
...@@ -15,6 +15,10 @@ ...@@ -15,6 +15,10 @@
15 */ 15 */
16 package org.onosproject.openstackswitching; 16 package org.onosproject.openstackswitching;
17 17
18 +import org.onlab.packet.Ip4Address;
19 +
20 +import java.util.List;
21 +
18 import static com.google.common.base.Preconditions.checkNotNull; 22 import static com.google.common.base.Preconditions.checkNotNull;
19 23
20 /** 24 /**
...@@ -26,13 +30,13 @@ public final class OpenstackSubnet { ...@@ -26,13 +30,13 @@ public final class OpenstackSubnet {
26 private boolean enableHhcp; 30 private boolean enableHhcp;
27 private String networkId; 31 private String networkId;
28 private String tenantId; 32 private String tenantId;
29 - private String dnsNameservers; 33 + private List<Ip4Address> dnsNameservers;
30 private String gatewayIp; 34 private String gatewayIp;
31 private String cidr; 35 private String cidr;
32 private String id; 36 private String id;
33 37
34 private OpenstackSubnet(String name, boolean enableHhcp, String networkId, 38 private OpenstackSubnet(String name, boolean enableHhcp, String networkId,
35 - String tenantId, String dnsNameservers, String gatewayIp, 39 + String tenantId, List<Ip4Address> dnsNameservers, String gatewayIp,
36 String cidr, String id) { 40 String cidr, String id) {
37 this.name = name; 41 this.name = name;
38 this.enableHhcp = enableHhcp; 42 this.enableHhcp = enableHhcp;
...@@ -69,7 +73,7 @@ public final class OpenstackSubnet { ...@@ -69,7 +73,7 @@ public final class OpenstackSubnet {
69 return tenantId; 73 return tenantId;
70 } 74 }
71 75
72 - public String dnsNameservers() { 76 + public List<Ip4Address> dnsNameservers() {
73 return dnsNameservers; 77 return dnsNameservers;
74 } 78 }
75 79
...@@ -85,8 +89,6 @@ public final class OpenstackSubnet { ...@@ -85,8 +89,6 @@ public final class OpenstackSubnet {
85 return id; 89 return id;
86 } 90 }
87 91
88 - // TODO : Implement the following functions when necessary
89 -
90 /** 92 /**
91 * OpenstackSubnet Builder class. 93 * OpenstackSubnet Builder class.
92 * 94 *
...@@ -96,7 +98,7 @@ public final class OpenstackSubnet { ...@@ -96,7 +98,7 @@ public final class OpenstackSubnet {
96 private boolean enableDhcp; 98 private boolean enableDhcp;
97 private String networkId; 99 private String networkId;
98 private String tenantId; 100 private String tenantId;
99 - private String dnsNameservers; 101 + private List<Ip4Address> dnsNameservers;
100 private String gatewayIp; 102 private String gatewayIp;
101 private String cidr; 103 private String cidr;
102 private String id; 104 private String id;
...@@ -127,7 +129,7 @@ public final class OpenstackSubnet { ...@@ -127,7 +129,7 @@ public final class OpenstackSubnet {
127 return this; 129 return this;
128 } 130 }
129 131
130 - public Builder setDnsNameservers(String dnsNameservers) { 132 + public Builder setDnsNameservers(List<Ip4Address> dnsNameservers) {
131 this.dnsNameservers = dnsNameservers; 133 this.dnsNameservers = dnsNameservers;
132 134
133 return this; 135 return this;
......
...@@ -15,8 +15,10 @@ ...@@ -15,8 +15,10 @@
15 */ 15 */
16 package org.onosproject.openstackswitching; 16 package org.onosproject.openstackswitching;
17 17
18 +import java.util.Collection;
19 +
18 /** 20 /**
19 - * It handles port management REST API from Openstack for VMs. 21 + * Handles port management REST API from Openstack for VMs.
20 */ 22 */
21 public interface OpenstackSwitchingService { 23 public interface OpenstackSwitchingService {
22 24
...@@ -40,16 +42,41 @@ public interface OpenstackSwitchingService { ...@@ -40,16 +42,41 @@ public interface OpenstackSwitchingService {
40 void updatePorts(); 42 void updatePorts();
41 43
42 /** 44 /**
43 - * Store the network information created by openstack. 45 + * Stores the network information created by openstack.
44 * 46 *
45 * @param openstackNetwork network information 47 * @param openstackNetwork network information
46 */ 48 */
47 void createNetwork(OpenstackNetwork openstackNetwork); 49 void createNetwork(OpenstackNetwork openstackNetwork);
48 50
49 /** 51 /**
50 - * Store the subnet information created by openstack. 52 + * Stores the subnet information created by openstack.
51 * 53 *
52 * @param openstackSubnet subnet information 54 * @param openstackSubnet subnet information
53 */ 55 */
54 void createSubnet(OpenstackSubnet openstackSubnet); 56 void createSubnet(OpenstackSubnet openstackSubnet);
57 +
58 + /**
59 + * Returns port information list for the network ID given.
60 + *
61 + * @param networkId Network ID of the ports
62 + * @return port information list
63 + */
64 + Collection<OpenstackPort> ports(String networkId);
65 +
66 + /**
67 + * Returns port information for the port ID given.
68 + *
69 + * @param portId Port ID
70 + * @return port information
71 + */
72 + OpenstackPort port(String portId);
73 +
74 + /**
75 + * Returns network information list for the network ID given.
76 + *
77 + * @param networkId Network ID
78 + * @return network information list
79 + */
80 + OpenstackNetwork network(String networkId);
81 +
55 } 82 }
......
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 +<app name="org.onosproject.openstackswitching" origin="ON.Lab" version="${project.version}"
18 + featuresRepo="mvn:${project.groupId}/${project.artifactId}/${project.version}/xml/features"
19 + features="${project.artifactId}">
20 + <description>${project.description}</description>
21 + <artifact>mvn:${project.groupId}/onos-app-openstackswitching/${project.version}</artifact>
22 + <artifact>mvn:${project.groupId}/onos-app-dhcp-api/${project.version}</artifact>
23 + <artifact>mvn:${project.groupId}/onos-app-dhcp/${project.version}</artifact>
24 +</app>
1 +<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
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 +<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>
19 + <feature name="onos-app-openstackswitching" version="${project.version}"
20 + description="${project.description}">
21 + <feature>onos-api</feature>
22 + <bundle>mvn:${project.groupId}/onos-app-openstackswitching/${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>
25 + </feature>
26 +</features>
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-openstackswitching</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-app-openstackswitching-api</artifactId>
51 + <version>${project.version}</version>
52 + </dependency>
53 + <dependency>
54 + <groupId>org.onosproject</groupId>
55 + <artifactId>onos-rest</artifactId>
56 + <version>${project.version}</version>
57 + </dependency>
58 + <dependency>
59 + <groupId>org.onosproject</groupId>
60 + <artifactId>onlab-rest</artifactId>
61 + <version>${project.version}</version>
62 + </dependency>
63 + <dependency>
64 + <groupId>javax.ws.rs</groupId>
65 + <artifactId>jsr311-api</artifactId>
66 + <version>1.1.1</version>
67 + </dependency>
68 + <dependency>
69 + <groupId>com.sun.jersey</groupId>
70 + <artifactId>jersey-servlet</artifactId>
71 + </dependency>
72 + <dependency>
73 + <groupId>com.fasterxml.jackson.core</groupId>
74 + <artifactId>jackson-databind</artifactId>
75 + </dependency>
76 + <dependency>
77 + <groupId>com.fasterxml.jackson.core</groupId>
78 + <artifactId>jackson-annotations</artifactId>
79 + </dependency>
80 + <dependency>
81 + <groupId>org.osgi</groupId>
82 + <artifactId>org.osgi.compendium</artifactId>
83 + </dependency>
84 + <dependency>
85 + <groupId>org.osgi</groupId>
86 + <artifactId>org.osgi.core</artifactId>
87 + </dependency>
88 + <dependency>
89 + <groupId>org.onosproject</groupId>
90 + <artifactId>onos-app-dhcp-api</artifactId>
91 + <version>${project.version}</version>
92 + </dependency>
93 + </dependencies>
94 +
95 + <build>
96 + <plugins>
97 + <plugin>
98 + <groupId>org.apache.felix</groupId>
99 + <artifactId>maven-bundle-plugin</artifactId>
100 + <extensions>true</extensions>
101 + <configuration>
102 + <instructions>
103 + <_wab>src/main/webapp/</_wab>
104 + <Bundle-SymbolicName>
105 + ${project.groupId}.${project.artifactId}
106 + </Bundle-SymbolicName>
107 + <Import-Package>
108 + org.slf4j,
109 + org.osgi.framework,
110 + javax.ws.rs,
111 + javax.ws.rs.core,
112 + com.sun.jersey.api.core,
113 + com.sun.jersey.spi.container.servlet,
114 + com.sun.jersey.server.impl.container.servlet,
115 + com.fasterxml.jackson.databind,
116 + com.fasterxml.jackson.databind.node,
117 + com.fasterxml.jackson.core,
118 + org.apache.karaf.shell.commands,
119 + com.google.common.*,
120 + org.onlab.packet.*,
121 + org.onosproject.*
122 + </Import-Package>
123 + <Web-ContextPath>${web.context}</Web-ContextPath>
124 + </instructions>
125 + </configuration>
126 + </plugin>
127 + </plugins>
128 + </build>
129 +
130 +
131 +</project>
...@@ -31,7 +31,7 @@ import java.nio.ByteBuffer; ...@@ -31,7 +31,7 @@ import java.nio.ByteBuffer;
31 import java.util.Map; 31 import java.util.Map;
32 32
33 /** 33 /**
34 - * It handles ARP packet from VMs. 34 + * Handles ARP packet from VMs.
35 */ 35 */
36 public class OpenstackArpHandler { 36 public class OpenstackArpHandler {
37 37
......
1 +/*
2 + * Copyright 2014 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.core.ApplicationId;
19 +import org.onosproject.net.config.Config;
20 +import org.onosproject.net.config.basics.BasicElementConfig;
21 +
22 +/**
23 + * Handles configuration for OpenstackSwitching app.
24 + */
25 +public class OpenstackSwitchingConfig extends Config<ApplicationId> {
26 + public static final String DONOTPUSH = "do_not_push_flows";
27 +
28 + /**
29 + * Returns the flag whether the app pushes flows or not.
30 + *
31 + * @return the flag or false if not set
32 + */
33 + public boolean doNotPushFlows() {
34 + String flag = get(DONOTPUSH, "false");
35 + return Boolean.valueOf(flag);
36 + }
37 +
38 + /**
39 + * Sets the flag whether the app pushes flows or not.
40 + *
41 + * @param flag the flag whether the app pushes flows or not
42 + * @return self
43 + */
44 + public BasicElementConfig doNotPushFlows(boolean flag) {
45 + return (BasicElementConfig) setOrClear(DONOTPUSH, flag);
46 + }
47 +}
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
15 */ 15 */
16 package org.onosproject.openstackswitching; 16 package org.onosproject.openstackswitching;
17 17
18 +import com.google.common.collect.ImmutableSet;
18 import com.google.common.collect.Lists; 19 import com.google.common.collect.Lists;
19 import com.google.common.collect.Maps; 20 import com.google.common.collect.Maps;
20 import org.apache.felix.scr.annotations.Activate; 21 import org.apache.felix.scr.annotations.Activate;
...@@ -33,6 +34,10 @@ import org.onosproject.dhcp.DhcpService; ...@@ -33,6 +34,10 @@ import org.onosproject.dhcp.DhcpService;
33 import org.onosproject.net.Device; 34 import org.onosproject.net.Device;
34 import org.onosproject.net.DeviceId; 35 import org.onosproject.net.DeviceId;
35 import org.onosproject.net.Port; 36 import org.onosproject.net.Port;
37 +import org.onosproject.net.config.ConfigFactory;
38 +import org.onosproject.net.config.NetworkConfigEvent;
39 +import org.onosproject.net.config.NetworkConfigListener;
40 +import org.onosproject.net.config.NetworkConfigRegistry;
36 import org.onosproject.net.device.DeviceEvent; 41 import org.onosproject.net.device.DeviceEvent;
37 import org.onosproject.net.device.DeviceListener; 42 import org.onosproject.net.device.DeviceListener;
38 import org.onosproject.net.device.DeviceService; 43 import org.onosproject.net.device.DeviceService;
...@@ -43,17 +48,21 @@ import org.onosproject.net.packet.PacketProcessor; ...@@ -43,17 +48,21 @@ import org.onosproject.net.packet.PacketProcessor;
43 import org.onosproject.net.packet.PacketService; 48 import org.onosproject.net.packet.PacketService;
44 import org.slf4j.Logger; 49 import org.slf4j.Logger;
45 import org.slf4j.LoggerFactory; 50 import org.slf4j.LoggerFactory;
46 -
47 import java.util.List; 51 import java.util.List;
48 import java.util.Map; 52 import java.util.Map;
53 +import java.util.Collection;
54 +import java.util.Set;
49 import java.util.concurrent.ExecutorService; 55 import java.util.concurrent.ExecutorService;
50 import java.util.concurrent.Executors; 56 import java.util.concurrent.Executors;
57 +import java.util.stream.Collectors;
58 +
59 +import static org.onosproject.net.config.basics.SubjectFactories.APP_SUBJECT_FACTORY;
51 60
52 @SuppressWarnings("ALL") 61 @SuppressWarnings("ALL")
53 @Service 62 @Service
54 @Component(immediate = true) 63 @Component(immediate = true)
55 /** 64 /**
56 - * It populates forwarding rules for VMs created by Openstack. 65 + * Populates forwarding rules for VMs created by Openstack.
57 */ 66 */
58 public class OpenstackSwitchingManager implements OpenstackSwitchingService { 67 public class OpenstackSwitchingManager implements OpenstackSwitchingService {
59 68
...@@ -73,11 +82,15 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService { ...@@ -73,11 +82,15 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService {
73 protected FlowObjectiveService flowObjectiveService; 82 protected FlowObjectiveService flowObjectiveService;
74 83
75 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 84 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
85 + protected NetworkConfigRegistry cfgService;
86 +
87 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
76 protected DhcpService dhcpService; 88 protected DhcpService dhcpService;
77 89
78 public static final int DHCP_PORT = 67; 90 public static final int DHCP_PORT = 67;
79 91
80 private ApplicationId appId; 92 private ApplicationId appId;
93 + private boolean doNotPushFlows;
81 private OpenstackArpHandler arpHandler; 94 private OpenstackArpHandler arpHandler;
82 95
83 private OpenstackSwitchingRulePopulator rulePopulator; 96 private OpenstackSwitchingRulePopulator rulePopulator;
...@@ -85,7 +98,17 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService { ...@@ -85,7 +98,17 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService {
85 98
86 private InternalPacketProcessor internalPacketProcessor = new InternalPacketProcessor(); 99 private InternalPacketProcessor internalPacketProcessor = new InternalPacketProcessor();
87 private InternalDeviceListener internalDeviceListener = new InternalDeviceListener(); 100 private InternalDeviceListener internalDeviceListener = new InternalDeviceListener();
88 - 101 + private InternalConfigListener internalConfigListener = new InternalConfigListener();
102 + private final Set<ConfigFactory> factories = ImmutableSet.of(
103 + new ConfigFactory<ApplicationId, OpenstackSwitchingConfig>(APP_SUBJECT_FACTORY,
104 + OpenstackSwitchingConfig.class,
105 + "openstackswitching") {
106 + @Override
107 + public OpenstackSwitchingConfig createConfig() {
108 + return new OpenstackSwitchingConfig();
109 + }
110 + }
111 + );
89 // Map <port_id, OpenstackPort> 112 // Map <port_id, OpenstackPort>
90 private Map<String, OpenstackPort> openstackPortMap; 113 private Map<String, OpenstackPort> openstackPortMap;
91 // Map <network_id, OpenstackNetwork> 114 // Map <network_id, OpenstackNetwork>
...@@ -101,17 +124,24 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService { ...@@ -101,17 +124,24 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService {
101 protected void activate() { 124 protected void activate() {
102 appId = coreService 125 appId = coreService
103 .registerApplication("org.onosproject.openstackswitching"); 126 .registerApplication("org.onosproject.openstackswitching");
104 - rulePopulator = new OpenstackSwitchingRulePopulator(appId, flowObjectiveService);
105 packetService.addProcessor(internalPacketProcessor, PacketProcessor.director(1)); 127 packetService.addProcessor(internalPacketProcessor, PacketProcessor.director(1));
106 deviceService.addListener(internalDeviceListener); 128 deviceService.addListener(internalDeviceListener);
107 - 129 + 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 + }
108 openstackPortMap = Maps.newHashMap(); 136 openstackPortMap = Maps.newHashMap();
109 openstackNetworkMap = Maps.newHashMap(); 137 openstackNetworkMap = Maps.newHashMap();
110 openstackSubnetMap = Maps.newHashMap(); 138 openstackSubnetMap = Maps.newHashMap();
111 139
112 vniPortMap = Maps.newHashMap(); 140 vniPortMap = Maps.newHashMap();
113 tunnelPortMap = Maps.newHashMap(); 141 tunnelPortMap = Maps.newHashMap();
142 +
114 arpHandler = new OpenstackArpHandler(openstackPortMap, packetService); 143 arpHandler = new OpenstackArpHandler(openstackPortMap, packetService);
144 +
115 log.info("Started"); 145 log.info("Started");
116 } 146 }
117 147
...@@ -119,6 +149,7 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService { ...@@ -119,6 +149,7 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService {
119 protected void deactivate() { 149 protected void deactivate() {
120 packetService.removeProcessor(internalPacketProcessor); 150 packetService.removeProcessor(internalPacketProcessor);
121 deviceService.removeListener(internalDeviceListener); 151 deviceService.removeListener(internalDeviceListener);
152 + cfgService.removeListener(internalConfigListener);
122 153
123 deviceEventExcutorService.shutdown(); 154 deviceEventExcutorService.shutdown();
124 155
...@@ -127,43 +158,10 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService { ...@@ -127,43 +158,10 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService {
127 158
128 @Override 159 @Override
129 public void createPorts(OpenstackPort openstackPort) { 160 public void createPorts(OpenstackPort openstackPort) {
130 - //For DHCP purpose 161 + registerDhcpInfo(openstackPort);
131 - //registerDhcpInfo(openstackPort);
132 openstackPortMap.put(openstackPort.id(), openstackPort); 162 openstackPortMap.put(openstackPort.id(), openstackPort);
133 } 163 }
134 164
135 - /*
136 - private void registerDhcpInfo(OpenstackPort openstackPort) {
137 - Ip4Address ip4Address;
138 - Ip4Address subnetMask;
139 - Ip4Address dhcpServer;
140 - Ip4Address gatewayIPAddress;
141 - Ip4Address domainServer;
142 - OpenstackSubnet openstackSubnet;
143 -
144 - ip4Address = (Ip4Address) openstackPort.fixedIps().values().toArray()[0];
145 -
146 - openstackSubnet = openstackSubnetMap.values().stream()
147 - .filter(n -> n.networkId().equals(openstackPort.networkId()))
148 - .findFirst().get();
149 -
150 - int prefix;
151 - String[] parts = openstackSubnet.cidr().split("/");
152 - prefix = Integer.parseInt(parts[1]);
153 - int mask = 0xffffffff << (32 - prefix);
154 - byte[] bytes = new byte[]{(byte) (mask >>> 24),
155 - (byte) (mask >> 16 & 0xff), (byte) (mask >> 8 & 0xff), (byte) (mask & 0xff)};
156 -
157 - subnetMask = Ip4Address.valueOf(bytes);
158 - gatewayIPAddress = Ip4Address.valueOf(openstackSubnet.gatewayIp());
159 - dhcpServer = gatewayIPAddress;
160 - domainServer = Ip4Address.valueOf("8.8.8.8");
161 -
162 - dhcpService.setStaticMappingOpenstack(openstackPort.macAddress(),
163 - ip4Address, subnetMask, dhcpServer, gatewayIPAddress, domainServer);
164 - }
165 - */
166 -
167 @Override 165 @Override
168 public void deletePorts() { 166 public void deletePorts() {
169 167
...@@ -179,13 +177,41 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService { ...@@ -179,13 +177,41 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService {
179 openstackNetworkMap.put(openstackNetwork.id(), openstackNetwork); 177 openstackNetworkMap.put(openstackNetwork.id(), openstackNetwork);
180 } 178 }
181 179
182 -
183 @Override 180 @Override
184 public void createSubnet(OpenstackSubnet openstackSubnet) { 181 public void createSubnet(OpenstackSubnet openstackSubnet) {
185 openstackSubnetMap.put(openstackSubnet.id(), openstackSubnet); 182 openstackSubnetMap.put(openstackSubnet.id(), openstackSubnet);
186 log.debug("Added Subnet Info {}", openstackNetworkMap.get(openstackSubnet.id())); 183 log.debug("Added Subnet Info {}", openstackNetworkMap.get(openstackSubnet.id()));
187 } 184 }
188 185
186 + @Override
187 + public Collection<OpenstackPort> ports(String networkId) {
188 +
189 + List<OpenstackPort> portList = openstackPortMap.values().stream()
190 + .filter(p -> p.networkId().equals(networkId))
191 + .collect(Collectors.toList());
192 +
193 + return portList;
194 + }
195 +
196 + @Override
197 + public OpenstackPort port(String portName) {
198 + String uuid = portName.substring(3);
199 + return (OpenstackPort) openstackPortMap.values().stream()
200 + .filter(p -> p.id().startsWith(uuid))
201 + .findFirst().get().clone();
202 + }
203 +
204 + @Override
205 + public OpenstackNetwork network(String networkId) {
206 + OpenstackNetwork on = null;
207 + try {
208 + on = (OpenstackNetwork) openstackNetworkMap.get(networkId).clone();
209 + } catch (CloneNotSupportedException e) {
210 + log.error("Cloning is not supported {}", e);
211 + }
212 + return on;
213 + }
214 +
189 private void processDeviceAdded(Device device) { 215 private void processDeviceAdded(Device device) {
190 log.debug("device {} is added", device.id()); 216 log.debug("device {} is added", device.id());
191 rulePopulator.populateDefaultRules(device.id()); 217 rulePopulator.populateDefaultRules(device.id());
...@@ -211,6 +237,49 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService { ...@@ -211,6 +237,49 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService {
211 // TODO: need to update the vniPortMap 237 // TODO: need to update the vniPortMap
212 } 238 }
213 239
240 + private void registerDhcpInfo(OpenstackPort openstackPort) {
241 + Ip4Address ip4Address;
242 + Ip4Address subnetMask;
243 + Ip4Address dhcpServer;
244 + Ip4Address gatewayIPAddress;
245 + Ip4Address domainServer;
246 + OpenstackSubnet openstackSubnet;
247 +
248 + ip4Address = (Ip4Address) openstackPort.fixedIps().values().toArray()[0];
249 +
250 + openstackSubnet = openstackSubnetMap.values().stream()
251 + .filter(n -> n.networkId().equals(openstackPort.networkId()))
252 + .findFirst().get();
253 +
254 + subnetMask = Ip4Address.valueOf(buildSubnetMask(openstackSubnet.cidr()));
255 + gatewayIPAddress = Ip4Address.valueOf(openstackSubnet.gatewayIp());
256 + dhcpServer = gatewayIPAddress;
257 + // TODO: supports multiple DNS servers
258 + if (openstackSubnet.dnsNameservers().isEmpty()) {
259 + domainServer = Ip4Address.valueOf("8.8.8.8");
260 + } else {
261 + domainServer = openstackSubnet.dnsNameservers().get(0);
262 + }
263 + List<Ip4Address> options = Lists.newArrayList();
264 + options.add(subnetMask);
265 + options.add(dhcpServer);
266 + options.add(gatewayIPAddress);
267 + options.add(domainServer);
268 +
269 + dhcpService.setStaticMapping(openstackPort.macAddress(), ip4Address, true, options);
270 + }
271 +
272 + private byte[] buildSubnetMask(String cidr) {
273 + int prefix;
274 + String[] parts = cidr.split("/");
275 + prefix = Integer.parseInt(parts[1]);
276 + int mask = 0xffffffff << (32 - prefix);
277 + byte[] bytes = new byte[]{(byte) (mask >>> 24),
278 + (byte) (mask >> 16 & 0xff), (byte) (mask >> 8 & 0xff), (byte) (mask & 0xff)};
279 +
280 + return bytes;
281 + }
282 +
214 /** 283 /**
215 * Populates the flow rules for traffic to VMs in different Cnode using 284 * Populates the flow rules for traffic to VMs in different Cnode using
216 * Nicira extention. 285 * Nicira extention.
...@@ -407,8 +476,8 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService { ...@@ -407,8 +476,8 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService {
407 private class InternalDeviceListener implements DeviceListener { 476 private class InternalDeviceListener implements DeviceListener {
408 477
409 @Override 478 @Override
410 - public void event(DeviceEvent event) { 479 + public void event(DeviceEvent deviceEvent) {
411 - deviceEventExcutorService.execute(new InternalEventHandler(event)); 480 + deviceEventExcutorService.execute(new InternalEventHandler(deviceEvent));
412 } 481 }
413 } 482 }
414 483
...@@ -422,6 +491,11 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService { ...@@ -422,6 +491,11 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService {
422 491
423 @Override 492 @Override
424 public void run() { 493 public void run() {
494 +
495 + if (doNotPushFlows) {
496 + return;
497 + }
498 +
425 switch (deviceEvent.type()) { 499 switch (deviceEvent.type()) {
426 case DEVICE_ADDED: 500 case DEVICE_ADDED:
427 processDeviceAdded((Device) deviceEvent.subject()); 501 processDeviceAdded((Device) deviceEvent.subject());
...@@ -453,6 +527,23 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService { ...@@ -453,6 +527,23 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService {
453 } 527 }
454 } 528 }
455 529
530 + private class InternalConfigListener implements NetworkConfigListener {
531 +
532 + @Override
533 + public void event(NetworkConfigEvent event) {
534 + if (((event.type() == NetworkConfigEvent.Type.CONFIG_ADDED ||
535 + event.type() == NetworkConfigEvent.Type.CONFIG_UPDATED)) &&
536 + event.configClass().equals(OpenstackSwitchingConfig.class)) {
537 + OpenstackSwitchingConfig cfg = cfgService.getConfig(appId,
538 + OpenstackSwitchingConfig.class);
539 + if (cfg != null) {
540 + doNotPushFlows = cfg.doNotPushFlows();
541 + log.info("Switching mode reconfigured");
542 + }
543 + }
544 + }
545 + }
546 +
456 private final class PortInfo { 547 private final class PortInfo {
457 DeviceId deviceId; 548 DeviceId deviceId;
458 String portName; 549 String portName;
......
...@@ -37,8 +37,7 @@ import org.slf4j.Logger; ...@@ -37,8 +37,7 @@ import org.slf4j.Logger;
37 import org.slf4j.LoggerFactory; 37 import org.slf4j.LoggerFactory;
38 38
39 /** 39 /**
40 - * It populates switching flow rules. 40 + * Populates switching flow rules.
41 - *
42 */ 41 */
43 public class OpenstackSwitchingRulePopulator { 42 public class OpenstackSwitchingRulePopulator {
44 43
......
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 +/**
18 + * OpenStack switch interface.
19 + */
20 +package org.onosproject.openstackswitching;
...@@ -29,7 +29,7 @@ import org.slf4j.LoggerFactory; ...@@ -29,7 +29,7 @@ import org.slf4j.LoggerFactory;
29 import java.util.HashMap; 29 import java.util.HashMap;
30 30
31 /** 31 /**
32 - * It encodes and decodes the OpenstackPort. 32 + * Encodes and decodes the OpenstackPort.
33 */ 33 */
34 public class OpenstackPortCodec extends JsonCodec<OpenstackPort> { 34 public class OpenstackPortCodec extends JsonCodec<OpenstackPort> {
35 35
......
...@@ -53,7 +53,7 @@ public class OpenstackPortWebResource extends AbstractWebResource { ...@@ -53,7 +53,7 @@ public class OpenstackPortWebResource extends AbstractWebResource {
53 53
54 OpenstackSwitchingService switchingService = get(OpenstackSwitchingService.class); 54 OpenstackSwitchingService switchingService = get(OpenstackSwitchingService.class);
55 switchingService.createPorts(openstackPort); 55 switchingService.createPorts(openstackPort);
56 - log.info("REST API ports is called with {}", portNode.toString()); 56 + log.debug("REST API ports is called with {}", portNode.toString());
57 return Response.status(Response.Status.OK).build(); 57 return Response.status(Response.Status.OK).build();
58 } catch (Exception e) { 58 } catch (Exception e) {
59 log.error("Creates VirtualPort failed because of exception {}", 59 log.error("Creates VirtualPort failed because of exception {}",
......
...@@ -18,17 +18,21 @@ package org.onosproject.openstackswitching.web; ...@@ -18,17 +18,21 @@ package org.onosproject.openstackswitching.web;
18 import com.fasterxml.jackson.databind.JsonNode; 18 import com.fasterxml.jackson.databind.JsonNode;
19 19
20 20
21 +import com.fasterxml.jackson.databind.node.ArrayNode;
21 import com.fasterxml.jackson.databind.node.ObjectNode; 22 import com.fasterxml.jackson.databind.node.ObjectNode;
23 +import com.google.common.collect.Lists;
24 +import org.onlab.packet.Ip4Address;
22 import org.onosproject.codec.CodecContext; 25 import org.onosproject.codec.CodecContext;
23 import org.onosproject.codec.JsonCodec; 26 import org.onosproject.codec.JsonCodec;
24 import org.onosproject.openstackswitching.OpenstackSubnet; 27 import org.onosproject.openstackswitching.OpenstackSubnet;
25 import org.slf4j.Logger; 28 import org.slf4j.Logger;
26 import org.slf4j.LoggerFactory; 29 import org.slf4j.LoggerFactory;
27 30
31 +import java.util.List;
32 +
28 /** 33 /**
29 - * It encodes and decodes the OpenstackSubnet. 34 + * Encodes and decodes the OpenstackSubnet.
30 */ 35 */
31 -
32 public class OpenstackSubnetCodec extends JsonCodec<OpenstackSubnet> { 36 public class OpenstackSubnetCodec extends JsonCodec<OpenstackSubnet> {
33 private static Logger log = LoggerFactory 37 private static Logger log = LoggerFactory
34 .getLogger(OpenstackSubnetCodec.class); 38 .getLogger(OpenstackSubnetCodec.class);
...@@ -52,7 +56,11 @@ public class OpenstackSubnetCodec extends JsonCodec<OpenstackSubnet> { ...@@ -52,7 +56,11 @@ public class OpenstackSubnetCodec extends JsonCodec<OpenstackSubnet> {
52 boolean enableDhcp = subnetInfo.path(ENABLE_DHCP).asBoolean(); 56 boolean enableDhcp = subnetInfo.path(ENABLE_DHCP).asBoolean();
53 String networkId = subnetInfo.path(NETWORK_ID).asText(); 57 String networkId = subnetInfo.path(NETWORK_ID).asText();
54 String tenantId = subnetInfo.path(TENANT_ID).asText(); 58 String tenantId = subnetInfo.path(TENANT_ID).asText();
55 - String dnsNameservsers = subnetInfo.path(DNS_NAMESERVERS).asText(); 59 + ArrayNode dnsNameservsers = (ArrayNode) subnetInfo.path(DNS_NAMESERVERS);
60 + List<Ip4Address> dnsList = Lists.newArrayList();
61 + if (dnsNameservsers != null && !dnsNameservsers.isMissingNode()) {
62 + dnsNameservsers.forEach(dns -> dnsList.add(Ip4Address.valueOf(dns.asText())));
63 + }
56 String gatewayIp = subnetInfo.path(GATEWAY_IP).asText(); 64 String gatewayIp = subnetInfo.path(GATEWAY_IP).asText();
57 String cidr = subnetInfo.path(CIDR).asText(); 65 String cidr = subnetInfo.path(CIDR).asText();
58 String id = subnetInfo.path(ID).asText(); 66 String id = subnetInfo.path(ID).asText();
...@@ -62,7 +70,7 @@ public class OpenstackSubnetCodec extends JsonCodec<OpenstackSubnet> { ...@@ -62,7 +70,7 @@ public class OpenstackSubnetCodec extends JsonCodec<OpenstackSubnet> {
62 .setEnableDhcp(enableDhcp) 70 .setEnableDhcp(enableDhcp)
63 .setNetworkId(networkId) 71 .setNetworkId(networkId)
64 .setTenantId(tenantId) 72 .setTenantId(tenantId)
65 - .setDnsNameservers(dnsNameservsers) 73 + .setDnsNameservers(dnsList)
66 .setGatewayIp(gatewayIp) 74 .setGatewayIp(gatewayIp)
67 .setCidr(cidr) 75 .setCidr(cidr)
68 .setId(id) 76 .setId(id)
......
...@@ -51,7 +51,7 @@ public class OpenstackSubnetWebResource extends AbstractWebResource { ...@@ -51,7 +51,7 @@ public class OpenstackSubnetWebResource extends AbstractWebResource {
51 51
52 OpenstackSwitchingService switchingService = get(OpenstackSwitchingService.class); 52 OpenstackSwitchingService switchingService = get(OpenstackSwitchingService.class);
53 switchingService.createSubnet(openstackSubnet); 53 switchingService.createSubnet(openstackSubnet);
54 - log.info("REST API subnets is called with {}", subnetNode.toString()); 54 + log.debug("REST API subnets is called with {}", subnetNode.toString());
55 return Response.status(Response.Status.OK).build(); 55 return Response.status(Response.Status.OK).build();
56 } catch (Exception e) { 56 } catch (Exception e) {
57 log.error("Creates VirtualSubnet failed because of exception {}", 57 log.error("Creates VirtualSubnet failed because of exception {}",
......
...@@ -26,101 +26,18 @@ ...@@ -26,101 +26,18 @@
26 <relativePath>../pom.xml</relativePath> 26 <relativePath>../pom.xml</relativePath>
27 </parent> 27 </parent>
28 28
29 - <artifactId>onos-app-openstackswitching</artifactId> 29 + <artifactId>onos-openstackswitching</artifactId>
30 - <packaging>bundle</packaging> 30 + <packaging>pom</packaging>
31 31
32 - <description>SONA Openstack Switching applications</description> 32 + <description>SONA Openstack Switching application</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 33
34 + <modules>
35 + <module>api</module>
36 + <module>app</module>
37 + </modules>
46 38
47 <dependencies> 39 <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 - <dependency>
84 - <groupId>org.onosproject</groupId>
85 - <artifactId>onos-app-dhcp-api</artifactId>
86 - <version>${project.version}</version>
87 - </dependency>
88 </dependencies> 40 </dependencies>
89 41
90 - <build>
91 - <plugins>
92 - <plugin>
93 - <groupId>org.apache.felix</groupId>
94 - <artifactId>maven-bundle-plugin</artifactId>
95 - <extensions>true</extensions>
96 - <configuration>
97 - <instructions>
98 - <_wab>src/main/webapp/</_wab>
99 - <Bundle-SymbolicName>
100 - ${project.groupId}.${project.artifactId}
101 - </Bundle-SymbolicName>
102 - <Import-Package>
103 - org.slf4j,
104 - org.osgi.framework,
105 - javax.ws.rs,
106 - javax.ws.rs.core,
107 - com.sun.jersey.api.core,
108 - com.sun.jersey.spi.container.servlet,
109 - com.sun.jersey.server.impl.container.servlet,
110 - com.fasterxml.jackson.databind,
111 - com.fasterxml.jackson.databind.node,
112 - com.fasterxml.jackson.core,
113 - org.apache.karaf.shell.commands,
114 - com.google.common.*,
115 - org.onlab.packet.*,
116 - org.onosproject.*
117 - </Import-Package>
118 - <Web-ContextPath>${web.context}</Web-ContextPath>
119 - </instructions>
120 - </configuration>
121 - </plugin>
122 - </plugins>
123 - </build>
124 -
125 42
126 </project> 43 </project>
......