Committed by
Gerrit Code Review
ONOS-2184 - Initial implementation of Virtual network Intent service.
Change-Id: I03103b4eca797cd32480fbd0e3b4cf0385b50ef2
Showing
24 changed files
with
2078 additions
and
55 deletions
... | @@ -2,6 +2,7 @@ COMPILE_DEPS = [ | ... | @@ -2,6 +2,7 @@ COMPILE_DEPS = [ |
2 | '//lib:CORE_DEPS', | 2 | '//lib:CORE_DEPS', |
3 | '//lib:org.apache.karaf.shell.console', | 3 | '//lib:org.apache.karaf.shell.console', |
4 | '//incubator/api:onos-incubator-api', | 4 | '//incubator/api:onos-incubator-api', |
5 | + '//incubator/net:onos-incubator-net', | ||
5 | '//utils/rest:onlab-rest', | 6 | '//utils/rest:onlab-rest', |
6 | '//core/common:onos-core-common', | 7 | '//core/common:onos-core-common', |
7 | ] | 8 | ] | ... | ... |
1 | +/* | ||
2 | + * Copyright 2016-present Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | + | ||
17 | +package org.onosproject.cli.net.vnet; | ||
18 | + | ||
19 | +import org.apache.karaf.shell.commands.Argument; | ||
20 | +import org.apache.karaf.shell.commands.Command; | ||
21 | +import org.onosproject.cli.net.ConnectivityIntentCommand; | ||
22 | +import org.onosproject.incubator.net.virtual.NetworkId; | ||
23 | +import org.onosproject.incubator.net.virtual.VirtualNetworkIntent; | ||
24 | +import org.onosproject.incubator.net.virtual.VirtualNetworkService; | ||
25 | +import org.onosproject.net.ConnectPoint; | ||
26 | +import org.onosproject.net.flow.TrafficSelector; | ||
27 | +import org.onosproject.net.flow.TrafficTreatment; | ||
28 | +import org.onosproject.net.intent.Constraint; | ||
29 | +import org.onosproject.net.intent.Intent; | ||
30 | +import org.onosproject.net.intent.IntentService; | ||
31 | + | ||
32 | +import java.util.List; | ||
33 | + | ||
34 | +/** | ||
35 | + * Installs virtual network intents. | ||
36 | + */ | ||
37 | +@Command(scope = "onos", name = "add-vnet-intent", | ||
38 | + description = "Installs virtual network connectivity intent") | ||
39 | +public class VirtualNetworkIntentCreateCommand extends ConnectivityIntentCommand { | ||
40 | + | ||
41 | + @Argument(index = 0, name = "networkId", description = "Network ID", | ||
42 | + required = true, multiValued = false) | ||
43 | + Long networkId = null; | ||
44 | + | ||
45 | + @Argument(index = 1, name = "ingressDevice", | ||
46 | + description = "Ingress Device/Port Description", | ||
47 | + required = true, multiValued = false) | ||
48 | + String ingressDeviceString = null; | ||
49 | + | ||
50 | + @Argument(index = 2, name = "egressDevice", | ||
51 | + description = "Egress Device/Port Description", | ||
52 | + required = true, multiValued = false) | ||
53 | + String egressDeviceString = null; | ||
54 | + | ||
55 | + @Override | ||
56 | + protected void execute() { | ||
57 | + VirtualNetworkService service = get(VirtualNetworkService.class); | ||
58 | + IntentService virtualNetworkIntentService = service.get(NetworkId.networkId(networkId), IntentService.class); | ||
59 | + | ||
60 | + ConnectPoint ingress = ConnectPoint.deviceConnectPoint(ingressDeviceString); | ||
61 | + ConnectPoint egress = ConnectPoint.deviceConnectPoint(egressDeviceString); | ||
62 | + | ||
63 | + TrafficSelector selector = buildTrafficSelector(); | ||
64 | + TrafficTreatment treatment = buildTrafficTreatment(); | ||
65 | + | ||
66 | + List<Constraint> constraints = buildConstraints(); | ||
67 | + | ||
68 | + Intent intent = VirtualNetworkIntent.builder() | ||
69 | + .networkId(NetworkId.networkId(networkId)) | ||
70 | + .appId(appId()) | ||
71 | + .key(key()) | ||
72 | + .selector(selector) | ||
73 | + .treatment(treatment) | ||
74 | + .ingressPoint(ingress) | ||
75 | + .egressPoint(egress) | ||
76 | + .constraints(constraints) | ||
77 | + .priority(priority()) | ||
78 | + .build(); | ||
79 | + virtualNetworkIntentService.submit(intent); | ||
80 | + print("Virtual intent submitted:\n%s", intent.toString()); | ||
81 | + } | ||
82 | +} |
1 | +/* | ||
2 | + * Copyright 2016-present Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | + | ||
17 | +package org.onosproject.cli.net.vnet; | ||
18 | + | ||
19 | +import org.apache.karaf.shell.commands.Argument; | ||
20 | +import org.apache.karaf.shell.commands.Command; | ||
21 | +import org.apache.karaf.shell.commands.Option; | ||
22 | +import org.onosproject.cli.AbstractShellCommand; | ||
23 | +import org.onosproject.core.ApplicationId; | ||
24 | +import org.onosproject.core.CoreService; | ||
25 | +import org.onosproject.incubator.net.virtual.NetworkId; | ||
26 | +import org.onosproject.incubator.net.virtual.VirtualNetworkService; | ||
27 | +import org.onosproject.net.intent.Intent; | ||
28 | +import org.onosproject.net.intent.IntentEvent; | ||
29 | +import org.onosproject.net.intent.IntentListener; | ||
30 | +import org.onosproject.net.intent.IntentService; | ||
31 | +import org.onosproject.net.intent.IntentState; | ||
32 | +import org.onosproject.net.intent.Key; | ||
33 | + | ||
34 | +import java.math.BigInteger; | ||
35 | +import java.util.EnumSet; | ||
36 | +import java.util.Objects; | ||
37 | +import java.util.concurrent.CountDownLatch; | ||
38 | +import java.util.concurrent.TimeUnit; | ||
39 | + | ||
40 | +import static com.google.common.base.Strings.isNullOrEmpty; | ||
41 | +import static org.onosproject.net.intent.IntentState.FAILED; | ||
42 | +import static org.onosproject.net.intent.IntentState.WITHDRAWN; | ||
43 | + | ||
44 | +/** | ||
45 | + * Removes a virtual network intent. | ||
46 | + */ | ||
47 | +@Command(scope = "onos", name = "remove-vnet-intent", | ||
48 | + description = "Removes the virtual network intent") | ||
49 | +public class VirtualNetworkIntentRemoveCommand extends AbstractShellCommand { | ||
50 | + | ||
51 | + @Argument(index = 0, name = "networkId", description = "Network ID", | ||
52 | + required = true, multiValued = false) | ||
53 | + Long networkId = null; | ||
54 | + | ||
55 | + @Argument(index = 1, name = "app", | ||
56 | + description = "Application ID", | ||
57 | + required = false, multiValued = false) | ||
58 | + String applicationIdString = null; | ||
59 | + | ||
60 | + @Argument(index = 2, name = "key", | ||
61 | + description = "Intent Key", | ||
62 | + required = false, multiValued = false) | ||
63 | + String keyString = null; | ||
64 | + | ||
65 | + @Option(name = "-p", aliases = "--purge", | ||
66 | + description = "Purge the intent from the store after removal", | ||
67 | + required = false, multiValued = false) | ||
68 | + private boolean purgeAfterRemove = false; | ||
69 | + | ||
70 | + @Option(name = "-s", aliases = "--sync", | ||
71 | + description = "Waits for the removal before returning", | ||
72 | + required = false, multiValued = false) | ||
73 | + private boolean sync = false; | ||
74 | + | ||
75 | + private static final EnumSet<IntentState> CAN_PURGE = EnumSet.of(WITHDRAWN, FAILED); | ||
76 | + | ||
77 | + @Override | ||
78 | + protected void execute() { | ||
79 | + VirtualNetworkService service = get(VirtualNetworkService.class); | ||
80 | + IntentService intentService = service.get(NetworkId.networkId(networkId), IntentService.class); | ||
81 | + CoreService coreService = get(CoreService.class); | ||
82 | + | ||
83 | + if (purgeAfterRemove || sync) { | ||
84 | + print("Using \"sync\" to remove/purge intents - this may take a while..."); | ||
85 | + print("Check \"summary\" to see remove/purge progress."); | ||
86 | + } | ||
87 | + | ||
88 | + ApplicationId appId = appId(); | ||
89 | + if (!isNullOrEmpty(applicationIdString)) { | ||
90 | + appId = coreService.getAppId(applicationIdString); | ||
91 | + if (appId == null) { | ||
92 | + print("Cannot find application Id %s", applicationIdString); | ||
93 | + return; | ||
94 | + } | ||
95 | + } | ||
96 | + | ||
97 | + if (isNullOrEmpty(keyString)) { | ||
98 | + for (Intent intent : intentService.getIntents()) { | ||
99 | + if (intent.appId().equals(appId)) { | ||
100 | + removeIntent(intentService, intent); | ||
101 | + } | ||
102 | + } | ||
103 | + | ||
104 | + } else { | ||
105 | + final Key key; | ||
106 | + if (keyString.startsWith("0x")) { | ||
107 | + // The intent uses a LongKey | ||
108 | + keyString = keyString.replaceFirst("0x", ""); | ||
109 | + key = Key.of(new BigInteger(keyString, 16).longValue(), appId); | ||
110 | + } else { | ||
111 | + // The intent uses a StringKey | ||
112 | + key = Key.of(keyString, appId); | ||
113 | + } | ||
114 | + | ||
115 | + Intent intent = intentService.getIntent(key); | ||
116 | + if (intent != null) { | ||
117 | + removeIntent(intentService, intent); | ||
118 | + } else { | ||
119 | + print("Intent not found!"); | ||
120 | + } | ||
121 | + } | ||
122 | + } | ||
123 | + | ||
124 | + /** | ||
125 | + * Removes the intent using the specified intentService. | ||
126 | + * | ||
127 | + * @param intentService intent service | ||
128 | + * @param intent intent | ||
129 | + */ | ||
130 | + private void removeIntent(IntentService intentService, Intent intent) { | ||
131 | + IntentListener listener = null; | ||
132 | + Key key = intent.key(); | ||
133 | + final CountDownLatch withdrawLatch, purgeLatch; | ||
134 | + if (purgeAfterRemove || sync) { | ||
135 | + // set up latch and listener to track uninstall progress | ||
136 | + withdrawLatch = new CountDownLatch(1); | ||
137 | + purgeLatch = purgeAfterRemove ? new CountDownLatch(1) : null; | ||
138 | + listener = (IntentEvent event) -> { | ||
139 | + if (Objects.equals(event.subject().key(), key)) { | ||
140 | + if (event.type() == IntentEvent.Type.WITHDRAWN || | ||
141 | + event.type() == IntentEvent.Type.FAILED) { | ||
142 | + withdrawLatch.countDown(); | ||
143 | + } else if (purgeAfterRemove && | ||
144 | + event.type() == IntentEvent.Type.PURGED) { | ||
145 | + purgeLatch.countDown(); | ||
146 | + } | ||
147 | + } | ||
148 | + }; | ||
149 | + intentService.addListener(listener); | ||
150 | + } else { | ||
151 | + purgeLatch = null; | ||
152 | + withdrawLatch = null; | ||
153 | + } | ||
154 | + | ||
155 | + // request the withdraw | ||
156 | + intentService.withdraw(intent); | ||
157 | + | ||
158 | + if (purgeAfterRemove || sync) { | ||
159 | + try { // wait for withdraw event | ||
160 | + withdrawLatch.await(5, TimeUnit.SECONDS); | ||
161 | + } catch (InterruptedException e) { | ||
162 | + print("Timed out waiting for intent {} withdraw", key); | ||
163 | + } | ||
164 | + if (purgeAfterRemove && CAN_PURGE.contains(intentService.getIntentState(key))) { | ||
165 | + intentService.purge(intent); | ||
166 | + if (sync) { // wait for purge event | ||
167 | + /* TODO | ||
168 | + Technically, the event comes before map.remove() is called. | ||
169 | + If we depend on sync and purge working together, we will | ||
170 | + need to address this. | ||
171 | + */ | ||
172 | + try { | ||
173 | + purgeLatch.await(5, TimeUnit.SECONDS); | ||
174 | + } catch (InterruptedException e) { | ||
175 | + print("Timed out waiting for intent {} purge", key); | ||
176 | + } | ||
177 | + } | ||
178 | + } | ||
179 | + } | ||
180 | + | ||
181 | + if (listener != null) { | ||
182 | + // clean up the listener | ||
183 | + intentService.removeListener(listener); | ||
184 | + } | ||
185 | + } | ||
186 | +} |
... | @@ -683,6 +683,12 @@ | ... | @@ -683,6 +683,12 @@ |
683 | <command> | 683 | <command> |
684 | <action class="org.onosproject.cli.net.vnet.VirtualHostRemoveCommand"/> | 684 | <action class="org.onosproject.cli.net.vnet.VirtualHostRemoveCommand"/> |
685 | </command> | 685 | </command> |
686 | + <command> | ||
687 | + <action class="org.onosproject.cli.net.vnet.VirtualNetworkIntentCreateCommand"/> | ||
688 | + </command> | ||
689 | + <command> | ||
690 | + <action class="org.onosproject.cli.net.vnet.VirtualNetworkIntentRemoveCommand"/> | ||
691 | + </command> | ||
686 | </command-bundle> | 692 | </command-bundle> |
687 | 693 | ||
688 | <bean id="reviewAppNameCompleter" class="org.onosproject.cli.security.ReviewApplicationNameCompleter"/> | 694 | <bean id="reviewAppNameCompleter" class="org.onosproject.cli.security.ReviewApplicationNameCompleter"/> | ... | ... |
... | @@ -155,7 +155,6 @@ public class FakeIntentManager implements TestableIntentService { | ... | @@ -155,7 +155,6 @@ public class FakeIntentManager implements TestableIntentService { |
155 | 155 | ||
156 | @Override | 156 | @Override |
157 | public void withdraw(Intent intent) { | 157 | public void withdraw(Intent intent) { |
158 | - intents.remove(intent.key()); | ||
159 | executeWithdraw(intent); | 158 | executeWithdraw(intent); |
160 | } | 159 | } |
161 | 160 | ||
... | @@ -167,6 +166,7 @@ public class FakeIntentManager implements TestableIntentService { | ... | @@ -167,6 +166,7 @@ public class FakeIntentManager implements TestableIntentService { |
167 | intents.remove(intent.key()); | 166 | intents.remove(intent.key()); |
168 | installables.remove(intent.key()); | 167 | installables.remove(intent.key()); |
169 | intentStates.remove(intent.key()); | 168 | intentStates.remove(intent.key()); |
169 | + dispatch(new IntentEvent(IntentEvent.Type.PURGED, intent)); | ||
170 | } | 170 | } |
171 | } | 171 | } |
172 | 172 | ... | ... |
1 | COMPILE_DEPS = [ | 1 | COMPILE_DEPS = [ |
2 | '//lib:CORE_DEPS', | 2 | '//lib:CORE_DEPS', |
3 | '//incubator/api:onos-incubator-api', | 3 | '//incubator/api:onos-incubator-api', |
4 | + '//utils/rest:onlab-rest', | ||
5 | + '//incubator/net:onos-incubator-net', | ||
6 | + '//incubator/store:onos-incubator-store', | ||
4 | ] | 7 | ] |
5 | 8 | ||
6 | TEST_DEPS = [ | 9 | TEST_DEPS = [ |
10 | + '//lib:TEST_REST', | ||
7 | '//lib:TEST_ADAPTERS', | 11 | '//lib:TEST_ADAPTERS', |
8 | '//core/common:onos-core-common', | 12 | '//core/common:onos-core-common', |
9 | '//core/store/dist:onos-core-dist', | 13 | '//core/store/dist:onos-core-dist', | ... | ... |
... | @@ -93,6 +93,14 @@ | ... | @@ -93,6 +93,14 @@ |
93 | 93 | ||
94 | <dependency> | 94 | <dependency> |
95 | <groupId>org.onosproject</groupId> | 95 | <groupId>org.onosproject</groupId> |
96 | + <artifactId>onlab-osgi</artifactId> | ||
97 | + <version>${project.version}</version> | ||
98 | + <classifier>tests</classifier> | ||
99 | + <scope>test</scope> | ||
100 | + </dependency> | ||
101 | + | ||
102 | + <dependency> | ||
103 | + <groupId>org.onosproject</groupId> | ||
96 | <artifactId>onos-incubator-api</artifactId> | 104 | <artifactId>onos-incubator-api</artifactId> |
97 | </dependency> | 105 | </dependency> |
98 | 106 | ||
... | @@ -110,6 +118,17 @@ | ... | @@ -110,6 +118,17 @@ |
110 | <groupId>org.apache.felix</groupId> | 118 | <groupId>org.apache.felix</groupId> |
111 | <artifactId>org.apache.felix.scr</artifactId> | 119 | <artifactId>org.apache.felix.scr</artifactId> |
112 | </dependency> | 120 | </dependency> |
121 | + <dependency> | ||
122 | + <groupId>org.onosproject</groupId> | ||
123 | + <artifactId>onos-incubator-store</artifactId> | ||
124 | + <version>${project.version}</version> | ||
125 | + <scope>test</scope> | ||
126 | + </dependency> | ||
127 | + <dependency> | ||
128 | + <groupId>org.onosproject</groupId> | ||
129 | + <artifactId>onos-incubator-net</artifactId> | ||
130 | + <version>${project.version}</version> | ||
131 | + </dependency> | ||
113 | </dependencies> | 132 | </dependencies> |
114 | 133 | ||
115 | </project> | 134 | </project> | ... | ... |
core/net/src/main/java/org/onosproject/net/intent/impl/compiler/VirtualNetworkIntentCompiler.java
0 → 100644
1 | +/* | ||
2 | + * Copyright 2016-present Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | + | ||
17 | +package org.onosproject.net.intent.impl.compiler; | ||
18 | + | ||
19 | +import org.apache.felix.scr.annotations.Activate; | ||
20 | +import org.apache.felix.scr.annotations.Component; | ||
21 | +import org.apache.felix.scr.annotations.Deactivate; | ||
22 | +import org.apache.felix.scr.annotations.Reference; | ||
23 | +import org.apache.felix.scr.annotations.ReferenceCardinality; | ||
24 | +import org.onlab.osgi.DefaultServiceDirectory; | ||
25 | +import org.onlab.osgi.ServiceDirectory; | ||
26 | +import org.onosproject.core.ApplicationId; | ||
27 | +import org.onosproject.incubator.net.tunnel.TunnelId; | ||
28 | +import org.onosproject.incubator.net.virtual.NetworkId; | ||
29 | +import org.onosproject.incubator.net.virtual.VirtualNetworkIntent; | ||
30 | +import org.onosproject.incubator.net.virtual.VirtualNetworkService; | ||
31 | +import org.onosproject.incubator.net.virtual.VirtualNetworkStore; | ||
32 | +import org.onosproject.incubator.net.virtual.VirtualPort; | ||
33 | +import org.onosproject.net.ConnectPoint; | ||
34 | +import org.onosproject.net.EncapsulationType; | ||
35 | +import org.onosproject.net.Link; | ||
36 | +import org.onosproject.net.Path; | ||
37 | +import org.onosproject.net.intent.Constraint; | ||
38 | +import org.onosproject.net.intent.Intent; | ||
39 | +import org.onosproject.net.intent.IntentService; | ||
40 | +import org.onosproject.net.intent.Key; | ||
41 | +import org.onosproject.net.intent.PointToPointIntent; | ||
42 | +import org.onosproject.net.intent.constraint.EncapsulationConstraint; | ||
43 | +import org.onosproject.net.intent.impl.IntentCompilationException; | ||
44 | +import org.onosproject.net.topology.TopologyService; | ||
45 | +import org.slf4j.Logger; | ||
46 | + | ||
47 | +import java.util.ArrayList; | ||
48 | +import java.util.List; | ||
49 | +import java.util.Optional; | ||
50 | +import java.util.Set; | ||
51 | + | ||
52 | +import static org.slf4j.LoggerFactory.getLogger; | ||
53 | + | ||
54 | +/** | ||
55 | + * An intent compiler for {@link org.onosproject.incubator.net.virtual.VirtualNetworkIntent}. | ||
56 | + */ | ||
57 | +@Component(immediate = true) | ||
58 | +public class VirtualNetworkIntentCompiler | ||
59 | + extends ConnectivityIntentCompiler<VirtualNetworkIntent> { | ||
60 | + | ||
61 | + private final Logger log = getLogger(getClass()); | ||
62 | + | ||
63 | + private static final String NETWORK_ID = "networkId="; | ||
64 | + protected static final String KEY_FORMAT = "{" + NETWORK_ID + "%s, src=%s, dst=%s}"; | ||
65 | + | ||
66 | + protected ServiceDirectory serviceDirectory = new DefaultServiceDirectory(); | ||
67 | + | ||
68 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
69 | + protected VirtualNetworkService manager; | ||
70 | + | ||
71 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
72 | + protected IntentService intentService; | ||
73 | + | ||
74 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
75 | + protected VirtualNetworkStore store; | ||
76 | + | ||
77 | + | ||
78 | + @Activate | ||
79 | + public void activate() { | ||
80 | + intentManager.registerCompiler(VirtualNetworkIntent.class, this); | ||
81 | + } | ||
82 | + | ||
83 | + @Deactivate | ||
84 | + public void deactivate() { | ||
85 | + intentManager.unregisterCompiler(VirtualNetworkIntent.class); | ||
86 | + } | ||
87 | + | ||
88 | + @Override | ||
89 | + public List<Intent> compile(VirtualNetworkIntent intent, List<Intent> installable) { | ||
90 | + | ||
91 | + log.debug("Compiling intent: " + intent); | ||
92 | + List<Intent> intents = new ArrayList<>(); | ||
93 | + Optional<Path> path = getPaths(intent).stream() | ||
94 | + .findFirst(); | ||
95 | + if (path != null && path.isPresent()) { | ||
96 | + path.get().links().forEach(link -> { | ||
97 | + Intent physicalIntent = createPtPtIntent(intent, link); | ||
98 | + intents.add(physicalIntent); | ||
99 | + | ||
100 | + // store the virtual intent to physical intent tunnelId mapping | ||
101 | + store.addTunnelId(intent, TunnelId.valueOf(physicalIntent.key().toString())); | ||
102 | + }); | ||
103 | + } else { | ||
104 | + throw new IntentCompilationException("Unable to find a path for intent " + intent); | ||
105 | + } | ||
106 | + | ||
107 | + return intents; | ||
108 | + } | ||
109 | + | ||
110 | + /** | ||
111 | + * Returns the paths for the virtual network intent. | ||
112 | + * | ||
113 | + * @param intent virtual network intent | ||
114 | + * @return set of paths | ||
115 | + */ | ||
116 | + private Set<Path> getPaths(VirtualNetworkIntent intent) { | ||
117 | + | ||
118 | + TopologyService topologyService = manager.get(intent.networkId(), TopologyService.class); | ||
119 | + if (topologyService == null) { | ||
120 | + throw new IntentCompilationException("topologyService is null"); | ||
121 | + } | ||
122 | + return topologyService.getPaths(topologyService.currentTopology(), | ||
123 | + intent.ingressPoint().deviceId(), intent.egressPoint().deviceId()); | ||
124 | + } | ||
125 | + | ||
126 | + /** | ||
127 | + * Encodes the key using the network identifier, application identifer, source and destination | ||
128 | + * connect points. | ||
129 | + * | ||
130 | + * @param networkId virtual network identifier | ||
131 | + * @param applicationId application identifier | ||
132 | + * @param src source connect point | ||
133 | + * @param dst destination connect point | ||
134 | + * @return encoded key | ||
135 | + */ | ||
136 | + private static Key encodeKey(NetworkId networkId, ApplicationId applicationId, ConnectPoint src, ConnectPoint dst) { | ||
137 | + String key = String.format(KEY_FORMAT, networkId, src, dst); | ||
138 | + return Key.of(key, applicationId); | ||
139 | + } | ||
140 | + | ||
141 | + /** | ||
142 | + * Creates a point-to-point intent from the virtual network intent and virtual link. | ||
143 | + * | ||
144 | + * @param intent virtual network intent | ||
145 | + * @param link virtual link | ||
146 | + * @return point to point intent | ||
147 | + */ | ||
148 | + private Intent createPtPtIntent(VirtualNetworkIntent intent, Link link) { | ||
149 | + ConnectPoint ingressPoint = mapVirtualToPhysicalPort(intent.networkId(), link.src()); | ||
150 | + ConnectPoint egressPoint = mapVirtualToPhysicalPort(intent.networkId(), link.dst()); | ||
151 | + Key intentKey = encodeKey(intent.networkId(), intent.appId(), ingressPoint, egressPoint); | ||
152 | + | ||
153 | + List<Constraint> constraints = new ArrayList<>(); | ||
154 | + constraints.add(new EncapsulationConstraint(EncapsulationType.VLAN)); | ||
155 | + | ||
156 | + // TODO Currently there can only be one intent between the ingress and egress across | ||
157 | + // all virtual networks. We may want to support multiple intents between the same src/dst pairs. | ||
158 | + PointToPointIntent physicalIntent = PointToPointIntent.builder() | ||
159 | + .key(intentKey) | ||
160 | + .appId(intent.appId()) | ||
161 | + .ingressPoint(ingressPoint) | ||
162 | + .egressPoint(egressPoint) | ||
163 | + .constraints(constraints) | ||
164 | + .build(); | ||
165 | + log.debug("Submitting physical intent: " + physicalIntent); | ||
166 | + intentService.submit(physicalIntent); | ||
167 | + | ||
168 | + return physicalIntent; | ||
169 | + } | ||
170 | + | ||
171 | + /** | ||
172 | + * Maps the virtual connect point to a physical connect point. | ||
173 | + * | ||
174 | + * @param networkId virtual network identifier | ||
175 | + * @param virtualCp virtual connect point | ||
176 | + * @return physical connect point | ||
177 | + */ | ||
178 | + private ConnectPoint mapVirtualToPhysicalPort(NetworkId networkId, ConnectPoint virtualCp) { | ||
179 | + Set<VirtualPort> ports = manager.getVirtualPorts(networkId, virtualCp.deviceId()); | ||
180 | + for (VirtualPort port : ports) { | ||
181 | + if (port.element().id().equals(virtualCp.elementId()) && | ||
182 | + port.number().equals(virtualCp.port())) { | ||
183 | + return new ConnectPoint(port.realizedBy().element().id(), port.realizedBy().number()); | ||
184 | + } | ||
185 | + } | ||
186 | + return null; | ||
187 | + } | ||
188 | +} | ||
189 | + |
1 | +/* | ||
2 | + * Copyright 2016-present Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | + | ||
17 | +package org.onosproject.net.intent.impl.compiler; | ||
18 | + | ||
19 | +import org.junit.After; | ||
20 | +import org.junit.Before; | ||
21 | +import org.junit.Test; | ||
22 | +import org.onlab.osgi.ServiceDirectory; | ||
23 | +import org.onlab.osgi.TestServiceDirectory; | ||
24 | +import org.onlab.rest.BaseResource; | ||
25 | +import org.onosproject.TestApplicationId; | ||
26 | +import org.onosproject.common.event.impl.TestEventDispatcher; | ||
27 | +import org.onosproject.core.ApplicationId; | ||
28 | +import org.onosproject.core.CoreService; | ||
29 | +import org.onosproject.core.CoreServiceAdapter; | ||
30 | +import org.onosproject.core.IdGenerator; | ||
31 | +import org.onosproject.incubator.net.virtual.TenantId; | ||
32 | +import org.onosproject.incubator.net.virtual.VirtualDevice; | ||
33 | +import org.onosproject.incubator.net.virtual.VirtualLink; | ||
34 | +import org.onosproject.incubator.net.virtual.VirtualNetwork; | ||
35 | +import org.onosproject.incubator.net.virtual.VirtualNetworkIntent; | ||
36 | +import org.onosproject.incubator.net.virtual.VirtualNetworkService; | ||
37 | +import org.onosproject.incubator.net.virtual.VirtualNetworkStore; | ||
38 | +import org.onosproject.incubator.net.virtual.impl.VirtualNetworkManager; | ||
39 | +import org.onosproject.incubator.store.virtual.impl.DistributedVirtualNetworkStore; | ||
40 | +import org.onosproject.net.ConnectPoint; | ||
41 | +import org.onosproject.net.DefaultPort; | ||
42 | +import org.onosproject.net.EncapsulationType; | ||
43 | +import org.onosproject.net.Link; | ||
44 | +import org.onosproject.net.NetTestTools; | ||
45 | +import org.onosproject.net.Port; | ||
46 | +import org.onosproject.net.PortNumber; | ||
47 | +import org.onosproject.net.TestDeviceParams; | ||
48 | +import org.onosproject.net.intent.Constraint; | ||
49 | +import org.onosproject.net.intent.FakeIntentManager; | ||
50 | +import org.onosproject.net.intent.Intent; | ||
51 | +import org.onosproject.net.intent.IntentExtensionService; | ||
52 | +import org.onosproject.net.intent.IntentService; | ||
53 | +import org.onosproject.net.intent.Key; | ||
54 | +import org.onosproject.net.intent.MockIdGenerator; | ||
55 | +import org.onosproject.net.intent.TestableIntentService; | ||
56 | +import org.onosproject.net.intent.constraint.EncapsulationConstraint; | ||
57 | +import org.onosproject.store.service.TestStorageService; | ||
58 | + | ||
59 | +import java.util.ArrayList; | ||
60 | +import java.util.Collections; | ||
61 | +import java.util.List; | ||
62 | +import java.util.concurrent.atomic.AtomicLong; | ||
63 | + | ||
64 | +import static org.junit.Assert.assertEquals; | ||
65 | +import static org.onlab.junit.TestUtils.TestUtilsException; | ||
66 | +import static org.onlab.junit.TestUtils.setField; | ||
67 | + | ||
68 | +/** | ||
69 | + * Junit tests for virtual network intent compiler. | ||
70 | + */ | ||
71 | +public class VirtualNetworkIntentCompilerTest extends TestDeviceParams { | ||
72 | + | ||
73 | + private CoreService coreService; | ||
74 | + private TestableIntentService intentService = new FakeIntentManager(); | ||
75 | + private IntentExtensionService intentExtensionService; | ||
76 | + private final IdGenerator idGenerator = new MockIdGenerator(); | ||
77 | + private VirtualNetworkIntentCompiler compiler; | ||
78 | + private VirtualNetworkManager manager; | ||
79 | + private DistributedVirtualNetworkStore virtualNetworkManagerStore; | ||
80 | + private ServiceDirectory testDirectory; | ||
81 | + | ||
82 | + private final String tenantIdValue1 = "TENANT_ID1"; | ||
83 | + private static final ApplicationId APP_ID = | ||
84 | + new TestApplicationId("test"); | ||
85 | + | ||
86 | + private ConnectPoint cp1; | ||
87 | + private ConnectPoint cp2; | ||
88 | + private ConnectPoint cp3; | ||
89 | + private ConnectPoint cp4; | ||
90 | + private ConnectPoint cp5; | ||
91 | + private ConnectPoint cp6; | ||
92 | + private VirtualLink link1; | ||
93 | + private VirtualLink link2; | ||
94 | + private VirtualLink link3; | ||
95 | + private VirtualLink link4; | ||
96 | + private VirtualLink link5; | ||
97 | + private VirtualLink link6; | ||
98 | + | ||
99 | + @Before | ||
100 | + public void setUp() throws TestUtilsException { | ||
101 | + virtualNetworkManagerStore = new DistributedVirtualNetworkStore(); | ||
102 | + | ||
103 | + coreService = new TestCoreService(); | ||
104 | + | ||
105 | + Intent.unbindIdGenerator(idGenerator); | ||
106 | + Intent.bindIdGenerator(idGenerator); | ||
107 | + | ||
108 | + virtualNetworkManagerStore.setCoreService(coreService); | ||
109 | + setField(coreService, "coreService", new TestCoreService()); | ||
110 | + setField(virtualNetworkManagerStore, "storageService", new TestStorageService()); | ||
111 | + virtualNetworkManagerStore.activate(); | ||
112 | + | ||
113 | + manager = new VirtualNetworkManager(); | ||
114 | + manager.setStore(virtualNetworkManagerStore); | ||
115 | + manager.setIntentService(intentService); | ||
116 | + NetTestTools.injectEventDispatcher(manager, new TestEventDispatcher()); | ||
117 | + manager.activate(); | ||
118 | + | ||
119 | + // Register a compiler and an installer both setup for success. | ||
120 | + intentExtensionService = intentService; | ||
121 | + | ||
122 | + testDirectory = new TestServiceDirectory() | ||
123 | + .add(VirtualNetworkService.class, manager) | ||
124 | + .add(VirtualNetworkStore.class, virtualNetworkManagerStore) | ||
125 | + .add(IntentService.class, intentService); | ||
126 | + BaseResource.setServiceDirectory(testDirectory); | ||
127 | + | ||
128 | + compiler = new VirtualNetworkIntentCompiler(); | ||
129 | + compiler.manager = manager; | ||
130 | + compiler.intentService = intentService; | ||
131 | + compiler.store = virtualNetworkManagerStore; | ||
132 | + compiler.intentManager = intentExtensionService; | ||
133 | + compiler.serviceDirectory = testDirectory; | ||
134 | + } | ||
135 | + | ||
136 | + @After | ||
137 | + public void tearDown() { | ||
138 | + Intent.unbindIdGenerator(idGenerator); | ||
139 | + manager.deactivate(); | ||
140 | + } | ||
141 | + | ||
142 | + /** | ||
143 | + * Method to create the virtual network for further testing. | ||
144 | + * | ||
145 | + * @return virtual network | ||
146 | + */ | ||
147 | + private VirtualNetwork setupVirtualNetworkTopology() { | ||
148 | + manager.registerTenantId(TenantId.tenantId(tenantIdValue1)); | ||
149 | + VirtualNetwork virtualNetwork = manager.createVirtualNetwork(TenantId.tenantId(tenantIdValue1)); | ||
150 | + VirtualDevice virtualDevice1 = | ||
151 | + manager.createVirtualDevice(virtualNetwork.id(), DID1); | ||
152 | + VirtualDevice virtualDevice2 = | ||
153 | + manager.createVirtualDevice(virtualNetwork.id(), DID2); | ||
154 | + VirtualDevice virtualDevice3 = | ||
155 | + manager.createVirtualDevice(virtualNetwork.id(), DID3); | ||
156 | + VirtualDevice virtualDevice4 = | ||
157 | + manager.createVirtualDevice(virtualNetwork.id(), DID4); | ||
158 | + | ||
159 | + Port port1 = new DefaultPort(virtualDevice1, PortNumber.portNumber(1), true); | ||
160 | + manager.createVirtualPort(virtualNetwork.id(), virtualDevice1.id(), port1.number(), port1); | ||
161 | + cp1 = new ConnectPoint(virtualDevice1.id(), port1.number()); | ||
162 | + | ||
163 | + Port port2 = new DefaultPort(virtualDevice1, PortNumber.portNumber(2), true); | ||
164 | + manager.createVirtualPort(virtualNetwork.id(), virtualDevice1.id(), port2.number(), port2); | ||
165 | + cp2 = new ConnectPoint(virtualDevice1.id(), port2.number()); | ||
166 | + | ||
167 | + Port port3 = new DefaultPort(virtualDevice2, PortNumber.portNumber(3), true); | ||
168 | + manager.createVirtualPort(virtualNetwork.id(), virtualDevice2.id(), port3.number(), port3); | ||
169 | + cp3 = new ConnectPoint(virtualDevice2.id(), port3.number()); | ||
170 | + | ||
171 | + Port port4 = new DefaultPort(virtualDevice2, PortNumber.portNumber(4), true); | ||
172 | + manager.createVirtualPort(virtualNetwork.id(), virtualDevice2.id(), port4.number(), port4); | ||
173 | + cp4 = new ConnectPoint(virtualDevice2.id(), port4.number()); | ||
174 | + | ||
175 | + Port port5 = new DefaultPort(virtualDevice3, PortNumber.portNumber(5), true); | ||
176 | + manager.createVirtualPort(virtualNetwork.id(), virtualDevice3.id(), port5.number(), port5); | ||
177 | + cp5 = new ConnectPoint(virtualDevice3.id(), port5.number()); | ||
178 | + | ||
179 | + Port port6 = new DefaultPort(virtualDevice3, PortNumber.portNumber(6), true); | ||
180 | + manager.createVirtualPort(virtualNetwork.id(), virtualDevice3.id(), port6.number(), port6); | ||
181 | + cp6 = new ConnectPoint(virtualDevice3.id(), port6.number()); | ||
182 | + | ||
183 | + link1 = manager.createVirtualLink(virtualNetwork.id(), cp1, cp3); | ||
184 | + virtualNetworkManagerStore.updateLink(link1, link1.tunnelId(), Link.State.ACTIVE); | ||
185 | + link2 = manager.createVirtualLink(virtualNetwork.id(), cp3, cp1); | ||
186 | + virtualNetworkManagerStore.updateLink(link2, link2.tunnelId(), Link.State.ACTIVE); | ||
187 | + link3 = manager.createVirtualLink(virtualNetwork.id(), cp4, cp5); | ||
188 | + virtualNetworkManagerStore.updateLink(link3, link3.tunnelId(), Link.State.ACTIVE); | ||
189 | + link4 = manager.createVirtualLink(virtualNetwork.id(), cp5, cp4); | ||
190 | + virtualNetworkManagerStore.updateLink(link4, link4.tunnelId(), Link.State.ACTIVE); | ||
191 | + | ||
192 | + return virtualNetwork; | ||
193 | + } | ||
194 | + | ||
195 | + @Test | ||
196 | + public void testCompiler() { | ||
197 | + compiler.activate(); | ||
198 | + VirtualNetwork virtualNetwork = setupVirtualNetworkTopology(); | ||
199 | + | ||
200 | + Key intentKey = Key.of("test", APP_ID); | ||
201 | + | ||
202 | + List<Constraint> constraints = new ArrayList<>(); | ||
203 | + constraints.add(new EncapsulationConstraint(EncapsulationType.VLAN)); | ||
204 | + | ||
205 | + VirtualNetworkIntent virtualIntent = VirtualNetworkIntent.builder() | ||
206 | + .networkId(virtualNetwork.id()) | ||
207 | + .key(intentKey) | ||
208 | + .appId(APP_ID) | ||
209 | + .ingressPoint(cp1) | ||
210 | + .egressPoint(cp5) | ||
211 | + .constraints(constraints) | ||
212 | + .build(); | ||
213 | + | ||
214 | + List<Intent> compiled = compiler.compile(virtualIntent, Collections.emptyList()); | ||
215 | + assertEquals("The virtual intents size is not as expected.", 2, compiled.size()); | ||
216 | + | ||
217 | + compiler.deactivate(); | ||
218 | + } | ||
219 | + | ||
220 | + | ||
221 | + /** | ||
222 | + * Core service test class. | ||
223 | + */ | ||
224 | + private class TestCoreService extends CoreServiceAdapter { | ||
225 | + | ||
226 | + @Override | ||
227 | + public IdGenerator getIdGenerator(String topic) { | ||
228 | + return new IdGenerator() { | ||
229 | + private AtomicLong counter = new AtomicLong(0); | ||
230 | + | ||
231 | + @Override | ||
232 | + public long getNewId() { | ||
233 | + return counter.getAndIncrement(); | ||
234 | + } | ||
235 | + }; | ||
236 | + } | ||
237 | + } | ||
238 | + | ||
239 | +} |
... | @@ -9,6 +9,7 @@ COMPILE_DEPS = [ | ... | @@ -9,6 +9,7 @@ COMPILE_DEPS = [ |
9 | '//lib:netty-handler', | 9 | '//lib:netty-handler', |
10 | '//lib:netty-transport-native-epoll', | 10 | '//lib:netty-transport-native-epoll', |
11 | '//lib:commons-math3', | 11 | '//lib:commons-math3', |
12 | + '//incubator/api:onos-incubator-api', | ||
12 | ] | 13 | ] |
13 | 14 | ||
14 | TEST_DEPS = [ | 15 | TEST_DEPS = [ | ... | ... |
... | @@ -27,6 +27,8 @@ import org.onlab.util.KryoNamespace; | ... | @@ -27,6 +27,8 @@ import org.onlab.util.KryoNamespace; |
27 | import org.onosproject.cluster.ClusterService; | 27 | import org.onosproject.cluster.ClusterService; |
28 | import org.onosproject.cluster.ControllerNode; | 28 | import org.onosproject.cluster.ControllerNode; |
29 | import org.onosproject.cluster.NodeId; | 29 | import org.onosproject.cluster.NodeId; |
30 | +import org.onosproject.incubator.net.virtual.NetworkId; | ||
31 | +import org.onosproject.incubator.net.virtual.VirtualNetworkIntent; | ||
30 | import org.onosproject.net.intent.Intent; | 32 | import org.onosproject.net.intent.Intent; |
31 | import org.onosproject.net.intent.IntentData; | 33 | import org.onosproject.net.intent.IntentData; |
32 | import org.onosproject.net.intent.IntentEvent; | 34 | import org.onosproject.net.intent.IntentEvent; |
... | @@ -97,6 +99,8 @@ public class GossipIntentStore | ... | @@ -97,6 +99,8 @@ public class GossipIntentStore |
97 | KryoNamespace.Builder intentSerializer = KryoNamespace.newBuilder() | 99 | KryoNamespace.Builder intentSerializer = KryoNamespace.newBuilder() |
98 | .register(KryoNamespaces.API) | 100 | .register(KryoNamespaces.API) |
99 | .register(IntentData.class) | 101 | .register(IntentData.class) |
102 | + .register(VirtualNetworkIntent.class) | ||
103 | + .register(NetworkId.class) | ||
100 | .register(MultiValuedTimestamp.class); | 104 | .register(MultiValuedTimestamp.class); |
101 | 105 | ||
102 | currentMap = storageService.<Key, IntentData>eventuallyConsistentMapBuilder() | 106 | currentMap = storageService.<Key, IntentData>eventuallyConsistentMapBuilder() | ... | ... |
incubator/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualNetworkIntent.java
0 → 100644
1 | +/* | ||
2 | + * Copyright 2016-present Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | + | ||
17 | +package org.onosproject.incubator.net.virtual; | ||
18 | + | ||
19 | +import com.google.common.annotations.Beta; | ||
20 | +import com.google.common.base.MoreObjects; | ||
21 | +import org.onosproject.core.ApplicationId; | ||
22 | +import org.onosproject.net.ConnectPoint; | ||
23 | +import org.onosproject.net.flow.TrafficSelector; | ||
24 | +import org.onosproject.net.flow.TrafficTreatment; | ||
25 | +import org.onosproject.net.intent.ConnectivityIntent; | ||
26 | +import org.onosproject.net.intent.Constraint; | ||
27 | +import org.onosproject.net.intent.Key; | ||
28 | + | ||
29 | +import java.util.Collections; | ||
30 | +import java.util.List; | ||
31 | + | ||
32 | +import static com.google.common.base.Preconditions.checkArgument; | ||
33 | +import static com.google.common.base.Preconditions.checkNotNull; | ||
34 | + | ||
35 | +/** | ||
36 | + * Abstraction of VirtualNetworkIntent connectivity. | ||
37 | + */ | ||
38 | +@Beta | ||
39 | +public final class VirtualNetworkIntent extends ConnectivityIntent { | ||
40 | + | ||
41 | + private final NetworkId networkId; | ||
42 | + private final ConnectPoint ingressPoint; | ||
43 | + private final ConnectPoint egressPoint; | ||
44 | + | ||
45 | + private static final String NETWORK_ID_NULL = "Network ID cannot be null"; | ||
46 | + | ||
47 | + /** | ||
48 | + * Returns a new point to point intent builder. The application id, | ||
49 | + * ingress point and egress point are required fields. If they are | ||
50 | + * not set by calls to the appropriate methods, an exception will | ||
51 | + * be thrown. | ||
52 | + * | ||
53 | + * @return point to point builder | ||
54 | + */ | ||
55 | + public static VirtualNetworkIntent.Builder builder() { | ||
56 | + return new VirtualNetworkIntent.Builder(); | ||
57 | + } | ||
58 | + | ||
59 | + /** | ||
60 | + * Builder of a point to point intent. | ||
61 | + */ | ||
62 | + public static final class Builder extends ConnectivityIntent.Builder { | ||
63 | + NetworkId networkId; | ||
64 | + ConnectPoint ingressPoint; | ||
65 | + ConnectPoint egressPoint; | ||
66 | + | ||
67 | + /** | ||
68 | + * Builder constructor. | ||
69 | + */ | ||
70 | + private Builder() { | ||
71 | + // Hide constructor | ||
72 | + } | ||
73 | + | ||
74 | + @Override | ||
75 | + public VirtualNetworkIntent.Builder appId(ApplicationId appId) { | ||
76 | + return (VirtualNetworkIntent.Builder) super.appId(appId); | ||
77 | + } | ||
78 | + | ||
79 | + @Override | ||
80 | + public VirtualNetworkIntent.Builder key(Key key) { | ||
81 | + return (VirtualNetworkIntent.Builder) super.key(key); | ||
82 | + } | ||
83 | + | ||
84 | + @Override | ||
85 | + public VirtualNetworkIntent.Builder selector(TrafficSelector selector) { | ||
86 | + return (VirtualNetworkIntent.Builder) super.selector(selector); | ||
87 | + } | ||
88 | + | ||
89 | + @Override | ||
90 | + public VirtualNetworkIntent.Builder treatment(TrafficTreatment treatment) { | ||
91 | + return (VirtualNetworkIntent.Builder) super.treatment(treatment); | ||
92 | + } | ||
93 | + | ||
94 | + @Override | ||
95 | + public VirtualNetworkIntent.Builder constraints(List<Constraint> constraints) { | ||
96 | + return (VirtualNetworkIntent.Builder) super.constraints(constraints); | ||
97 | + } | ||
98 | + | ||
99 | + @Override | ||
100 | + public VirtualNetworkIntent.Builder priority(int priority) { | ||
101 | + return (VirtualNetworkIntent.Builder) super.priority(priority); | ||
102 | + } | ||
103 | + | ||
104 | + /** | ||
105 | + * Sets the virtual network of the virtual network intent. | ||
106 | + * | ||
107 | + * @param networkId virtual network identifier | ||
108 | + * @return this builder | ||
109 | + */ | ||
110 | + public VirtualNetworkIntent.Builder networkId(NetworkId networkId) { | ||
111 | + this.networkId = networkId; | ||
112 | + return this; | ||
113 | + } | ||
114 | + | ||
115 | + /** | ||
116 | + * Sets the ingress point of the virtual network intent that will be built. | ||
117 | + * | ||
118 | + * @param ingressPoint ingress connect point | ||
119 | + * @return this builder | ||
120 | + */ | ||
121 | + public VirtualNetworkIntent.Builder ingressPoint(ConnectPoint ingressPoint) { | ||
122 | + this.ingressPoint = ingressPoint; | ||
123 | + return this; | ||
124 | + } | ||
125 | + | ||
126 | + /** | ||
127 | + * Sets the egress point of the virtual network intent that will be built. | ||
128 | + * | ||
129 | + * @param egressPoint egress connect point | ||
130 | + * @return this builder | ||
131 | + */ | ||
132 | + public VirtualNetworkIntent.Builder egressPoint(ConnectPoint egressPoint) { | ||
133 | + this.egressPoint = egressPoint; | ||
134 | + return this; | ||
135 | + } | ||
136 | + | ||
137 | + /** | ||
138 | + * Builds a virtual network intent from the accumulated parameters. | ||
139 | + * | ||
140 | + * @return virtual network intent | ||
141 | + */ | ||
142 | + public VirtualNetworkIntent build() { | ||
143 | + | ||
144 | + return new VirtualNetworkIntent( | ||
145 | + networkId, | ||
146 | + appId, | ||
147 | + key, | ||
148 | + selector, | ||
149 | + treatment, | ||
150 | + ingressPoint, | ||
151 | + egressPoint, | ||
152 | + constraints, | ||
153 | + priority | ||
154 | + ); | ||
155 | + } | ||
156 | + } | ||
157 | + | ||
158 | + | ||
159 | + /** | ||
160 | + * Creates a new point-to-point intent with the supplied ingress/egress | ||
161 | + * ports and constraints. | ||
162 | + * | ||
163 | + * @param networkId virtual network identifier | ||
164 | + * @param appId application identifier | ||
165 | + * @param key key of the intent | ||
166 | + * @param selector traffic selector | ||
167 | + * @param treatment treatment | ||
168 | + * @param ingressPoint ingress port | ||
169 | + * @param egressPoint egress port | ||
170 | + * @param constraints optional list of constraints | ||
171 | + * @param priority priority to use for flows generated by this intent | ||
172 | + * @throws NullPointerException if {@code ingressPoint} or | ||
173 | + * {@code egressPoints} or {@code appId} is null. | ||
174 | + */ | ||
175 | + private VirtualNetworkIntent(NetworkId networkId, | ||
176 | + ApplicationId appId, | ||
177 | + Key key, | ||
178 | + TrafficSelector selector, | ||
179 | + TrafficTreatment treatment, | ||
180 | + ConnectPoint ingressPoint, | ||
181 | + ConnectPoint egressPoint, | ||
182 | + List<Constraint> constraints, | ||
183 | + int priority) { | ||
184 | + super(appId, key, Collections.emptyList(), selector, treatment, constraints, | ||
185 | + priority); | ||
186 | + | ||
187 | + checkNotNull(networkId, NETWORK_ID_NULL); | ||
188 | + checkArgument(!ingressPoint.equals(egressPoint), | ||
189 | + "ingress and egress should be different (ingress: %s, egress: %s)", ingressPoint, egressPoint); | ||
190 | + | ||
191 | + this.networkId = networkId; | ||
192 | + this.ingressPoint = checkNotNull(ingressPoint); | ||
193 | + this.egressPoint = checkNotNull(egressPoint); | ||
194 | + } | ||
195 | + | ||
196 | + /** | ||
197 | + * Constructor for serializer. | ||
198 | + */ | ||
199 | + protected VirtualNetworkIntent() { | ||
200 | + super(); | ||
201 | + this.networkId = null; | ||
202 | + this.ingressPoint = null; | ||
203 | + this.egressPoint = null; | ||
204 | + } | ||
205 | + | ||
206 | + /** | ||
207 | + * Returns the virtual network identifier. | ||
208 | + * | ||
209 | + * @return network identifier | ||
210 | + */ | ||
211 | + public NetworkId networkId() { | ||
212 | + return networkId; | ||
213 | + } | ||
214 | + | ||
215 | + /** | ||
216 | + * Returns the port on which the ingress traffic should be connected to | ||
217 | + * the egress. | ||
218 | + * | ||
219 | + * @return ingress port | ||
220 | + */ | ||
221 | + public ConnectPoint ingressPoint() { | ||
222 | + return ingressPoint; | ||
223 | + } | ||
224 | + | ||
225 | + /** | ||
226 | + * Returns the port on which the traffic should egress. | ||
227 | + * | ||
228 | + * @return egress port | ||
229 | + */ | ||
230 | + public ConnectPoint egressPoint() { | ||
231 | + return egressPoint; | ||
232 | + } | ||
233 | + | ||
234 | + @Override | ||
235 | + public String toString() { | ||
236 | + return MoreObjects.toStringHelper(getClass()) | ||
237 | + .add("networkId", networkId) | ||
238 | + .add("id", id()) | ||
239 | + .add("key", key()) | ||
240 | + .add("appId", appId()) | ||
241 | + .add("priority", priority()) | ||
242 | + .add("resources", resources()) | ||
243 | + .add("selector", selector()) | ||
244 | + .add("treatment", treatment()) | ||
245 | + .add("ingress", ingressPoint) | ||
246 | + .add("egress", egressPoint) | ||
247 | + .add("constraints", constraints()) | ||
248 | + .toString(); | ||
249 | + } | ||
250 | + | ||
251 | +} |
... | @@ -26,6 +26,10 @@ import org.onosproject.net.HostLocation; | ... | @@ -26,6 +26,10 @@ import org.onosproject.net.HostLocation; |
26 | import org.onosproject.net.Link; | 26 | import org.onosproject.net.Link; |
27 | import org.onosproject.net.Port; | 27 | import org.onosproject.net.Port; |
28 | import org.onosproject.net.PortNumber; | 28 | import org.onosproject.net.PortNumber; |
29 | +import org.onosproject.net.intent.Intent; | ||
30 | +import org.onosproject.net.intent.IntentData; | ||
31 | +import org.onosproject.net.intent.IntentState; | ||
32 | +import org.onosproject.net.intent.Key; | ||
29 | import org.onosproject.store.Store; | 33 | import org.onosproject.store.Store; |
30 | 34 | ||
31 | import java.util.Set; | 35 | import java.util.Set; |
... | @@ -223,4 +227,73 @@ public interface VirtualNetworkStore | ... | @@ -223,4 +227,73 @@ public interface VirtualNetworkStore |
223 | */ | 227 | */ |
224 | Set<VirtualPort> getPorts(NetworkId networkId, DeviceId deviceId); | 228 | Set<VirtualPort> getPorts(NetworkId networkId, DeviceId deviceId); |
225 | 229 | ||
230 | + /** | ||
231 | + * Add or update the intent to the store. | ||
232 | + * | ||
233 | + * @param intent virtual intent | ||
234 | + * @param state intent state | ||
235 | + */ | ||
236 | + void addOrUpdateIntent(Intent intent, IntentState state); | ||
237 | + | ||
238 | + /** | ||
239 | + * Remove the virtual intent from the store. | ||
240 | + * | ||
241 | + * @param intentKey intent key | ||
242 | + * @return intent data | ||
243 | + */ | ||
244 | + IntentData removeIntent(Key intentKey); | ||
245 | + | ||
246 | + /** | ||
247 | + * Adds the intent to tunnel identifier mapping to the store. | ||
248 | + * | ||
249 | + * @param intent intent | ||
250 | + * @param tunnelId tunnel identifier | ||
251 | + */ | ||
252 | + void addTunnelId(Intent intent, TunnelId tunnelId); | ||
253 | + | ||
254 | + /** | ||
255 | + * Return the set of tunnel identifiers store against the intent. | ||
256 | + * | ||
257 | + * @param intent intent | ||
258 | + * @return set of tunnel identifiers | ||
259 | + */ | ||
260 | + Set<TunnelId> getTunnelIds(Intent intent); | ||
261 | + | ||
262 | + /** | ||
263 | + * Removes the intent to tunnel identifier mapping from the store. | ||
264 | + * | ||
265 | + * @param intent intent | ||
266 | + * @param tunnelId tunnel identifier | ||
267 | + */ | ||
268 | + void removeTunnelId(Intent intent, TunnelId tunnelId); | ||
269 | + | ||
270 | + /** | ||
271 | + * Return all intents. | ||
272 | + * | ||
273 | + * @return set of intents | ||
274 | + */ | ||
275 | + Set<Intent> getIntents(); | ||
276 | + | ||
277 | + /** | ||
278 | + * Return the intent for the specified intent key. | ||
279 | + * | ||
280 | + * @param key intent key | ||
281 | + * @return intent | ||
282 | + */ | ||
283 | + Intent getIntent(Key key); | ||
284 | + | ||
285 | + /** | ||
286 | + * Return the set of intent data. | ||
287 | + * | ||
288 | + * @return set of intent data | ||
289 | + */ | ||
290 | + Set<IntentData> getIntentData(); | ||
291 | + | ||
292 | + /** | ||
293 | + * Return the intent data matching the intent key. | ||
294 | + * | ||
295 | + * @param key intent key | ||
296 | + * @return intent data | ||
297 | + */ | ||
298 | + IntentData getIntentData(Key key); | ||
226 | } | 299 | } | ... | ... |
... | @@ -2,13 +2,15 @@ COMPILE_DEPS = [ | ... | @@ -2,13 +2,15 @@ COMPILE_DEPS = [ |
2 | '//lib:CORE_DEPS', | 2 | '//lib:CORE_DEPS', |
3 | '//core/common:onos-core-common', | 3 | '//core/common:onos-core-common', |
4 | '//incubator/api:onos-incubator-api', | 4 | '//incubator/api:onos-incubator-api', |
5 | + '//incubator/store:onos-incubator-store', | ||
6 | + '//utils/rest:onlab-rest', | ||
5 | ] | 7 | ] |
6 | 8 | ||
7 | TEST_DEPS = [ | 9 | TEST_DEPS = [ |
10 | + '//lib:TEST_REST', | ||
8 | '//lib:TEST_ADAPTERS', | 11 | '//lib:TEST_ADAPTERS', |
9 | '//core/api:onos-api-tests', | 12 | '//core/api:onos-api-tests', |
10 | '//core/common:onos-core-common-tests', | 13 | '//core/common:onos-core-common-tests', |
11 | - '//incubator/store:onos-incubator-store', | ||
12 | '//core/store/serializers:onos-core-serializers', | 14 | '//core/store/serializers:onos-core-serializers', |
13 | '//lib:concurrent-trees', | 15 | '//lib:concurrent-trees', |
14 | ] | 16 | ] | ... | ... |
... | @@ -95,6 +95,14 @@ | ... | @@ -95,6 +95,14 @@ |
95 | <groupId>org.apache.felix</groupId> | 95 | <groupId>org.apache.felix</groupId> |
96 | <artifactId>org.apache.felix.scr.annotations</artifactId> | 96 | <artifactId>org.apache.felix.scr.annotations</artifactId> |
97 | </dependency> | 97 | </dependency> |
98 | + | ||
99 | + <dependency> | ||
100 | + <groupId>org.onosproject</groupId> | ||
101 | + <artifactId>onlab-osgi</artifactId> | ||
102 | + <version>${project.version}</version> | ||
103 | + <classifier>tests</classifier> | ||
104 | + <scope>test</scope> | ||
105 | + </dependency> | ||
98 | </dependencies> | 106 | </dependencies> |
99 | 107 | ||
100 | <build> | 108 | <build> | ... | ... |
1 | +/* | ||
2 | + * Copyright 2016-present Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | + | ||
17 | +package org.onosproject.incubator.net.virtual.impl; | ||
18 | + | ||
19 | +import com.google.common.collect.Iterators; | ||
20 | +import org.onlab.osgi.ServiceDirectory; | ||
21 | +import org.onosproject.event.AbstractListenerManager; | ||
22 | +import org.onosproject.incubator.net.virtual.VirtualNetwork; | ||
23 | +import org.onosproject.incubator.net.virtual.VirtualNetworkIntent; | ||
24 | +import org.onosproject.incubator.net.virtual.VirtualNetworkService; | ||
25 | +import org.onosproject.incubator.net.virtual.VirtualNetworkStore; | ||
26 | +import org.onosproject.incubator.net.virtual.VirtualPort; | ||
27 | +import org.onosproject.net.ConnectPoint; | ||
28 | +import org.onosproject.net.DeviceId; | ||
29 | +import org.onosproject.net.Port; | ||
30 | +import org.onosproject.net.PortNumber; | ||
31 | +import org.onosproject.net.intent.Intent; | ||
32 | +import org.onosproject.net.intent.IntentData; | ||
33 | +import org.onosproject.net.intent.IntentEvent; | ||
34 | +import org.onosproject.net.intent.IntentListener; | ||
35 | +import org.onosproject.net.intent.IntentPartitionService; | ||
36 | +import org.onosproject.net.intent.IntentService; | ||
37 | +import org.onosproject.net.intent.IntentState; | ||
38 | +import org.onosproject.net.intent.Key; | ||
39 | +import org.slf4j.Logger; | ||
40 | +import org.slf4j.LoggerFactory; | ||
41 | + | ||
42 | +import java.util.ArrayList; | ||
43 | +import java.util.List; | ||
44 | +import java.util.Optional; | ||
45 | + | ||
46 | +import static com.google.common.base.Preconditions.*; | ||
47 | + | ||
48 | +/** | ||
49 | + * intent service implementation built on the virtual network service. | ||
50 | + */ | ||
51 | +public class VirtualNetworkIntentService extends AbstractListenerManager<IntentEvent, IntentListener> | ||
52 | + implements IntentService, VnetService { | ||
53 | + | ||
54 | + private final Logger log = LoggerFactory.getLogger(getClass()); | ||
55 | + | ||
56 | + private static final String NETWORK_NULL = "Network cannot be null"; | ||
57 | + private static final String NETWORK_ID_NULL = "Network ID cannot be null"; | ||
58 | + private static final String DEVICE_NULL = "Device cannot be null"; | ||
59 | + private static final String INTENT_NULL = "Intent cannot be null"; | ||
60 | + private static final String KEY_NULL = "Key cannot be null"; | ||
61 | + private static final String APP_ID_NULL = "Intent app identifier cannot be null"; | ||
62 | + private static final String INTENT_KEY_NULL = "Intent key cannot be null"; | ||
63 | + private static final String CP_NULL = "Connect Point cannot be null"; | ||
64 | + | ||
65 | + protected IntentService intentService; | ||
66 | + protected VirtualNetworkStore store; | ||
67 | + protected IntentPartitionService partitionService; | ||
68 | + | ||
69 | + private final VirtualNetwork network; | ||
70 | + private final VirtualNetworkService manager; | ||
71 | + | ||
72 | + /** | ||
73 | + * Creates a new VirtualNetworkIntentService object. | ||
74 | + * | ||
75 | + * @param virtualNetworkManager virtual network manager service | ||
76 | + * @param network virtual network | ||
77 | + * @param serviceDirectory service directory | ||
78 | + */ | ||
79 | + public VirtualNetworkIntentService(VirtualNetworkService virtualNetworkManager, VirtualNetwork network, | ||
80 | + ServiceDirectory serviceDirectory) { | ||
81 | + checkNotNull(network, NETWORK_NULL); | ||
82 | + this.network = network; | ||
83 | + this.manager = virtualNetworkManager; | ||
84 | + this.store = serviceDirectory.get(VirtualNetworkStore.class); | ||
85 | + this.intentService = serviceDirectory.get(IntentService.class); | ||
86 | + this.partitionService = serviceDirectory.get(IntentPartitionService.class); | ||
87 | + } | ||
88 | + | ||
89 | + @Override | ||
90 | + public void submit(Intent intent) { | ||
91 | + checkNotNull(intent, INTENT_NULL); | ||
92 | + checkState(intent instanceof VirtualNetworkIntent, "Only VirtualNetworkIntent is supported."); | ||
93 | + checkArgument(validateIntent((VirtualNetworkIntent) intent), "Invalid Intent"); | ||
94 | + | ||
95 | + intentService.submit(intent); | ||
96 | + } | ||
97 | + | ||
98 | + /** | ||
99 | + * Returns true if the virtual network intent is valid. | ||
100 | + * | ||
101 | + * @param intent virtual network intent | ||
102 | + * @return true if intent is valid | ||
103 | + */ | ||
104 | + private boolean validateIntent(VirtualNetworkIntent intent) { | ||
105 | + checkNotNull(intent, INTENT_NULL); | ||
106 | + checkNotNull(intent.networkId(), NETWORK_ID_NULL); | ||
107 | + checkNotNull(intent.appId(), APP_ID_NULL); | ||
108 | + checkNotNull(intent.key(), INTENT_KEY_NULL); | ||
109 | + ConnectPoint ingressPoint = intent.ingressPoint(); | ||
110 | + ConnectPoint egressPoint = intent.egressPoint(); | ||
111 | + | ||
112 | + return (validateConnectPoint(ingressPoint) && validateConnectPoint(egressPoint)); | ||
113 | + } | ||
114 | + | ||
115 | + /** | ||
116 | + * Returns true if the connect point is valid. | ||
117 | + * | ||
118 | + * @param connectPoint connect point | ||
119 | + * @return true if connect point is valid | ||
120 | + */ | ||
121 | + private boolean validateConnectPoint(ConnectPoint connectPoint) { | ||
122 | + checkNotNull(connectPoint, CP_NULL); | ||
123 | + Port port = getPort(connectPoint.deviceId(), connectPoint.port()); | ||
124 | + return port == null ? false : true; | ||
125 | + } | ||
126 | + | ||
127 | + /** | ||
128 | + * Returns the virtual port for the given device identifier and port number. | ||
129 | + * | ||
130 | + * @param deviceId virtual device identifier | ||
131 | + * @param portNumber virtual port number | ||
132 | + * @return virtual port | ||
133 | + */ | ||
134 | + private Port getPort(DeviceId deviceId, PortNumber portNumber) { | ||
135 | + checkNotNull(deviceId, DEVICE_NULL); | ||
136 | + | ||
137 | + Optional<VirtualPort> foundPort = manager.getVirtualPorts(this.network.id(), deviceId) | ||
138 | + .stream() | ||
139 | + .filter(port -> port.number().equals(portNumber)) | ||
140 | + .findFirst(); | ||
141 | + if (foundPort.isPresent()) { | ||
142 | + return foundPort.get(); | ||
143 | + } | ||
144 | + return null; | ||
145 | + } | ||
146 | + | ||
147 | + @Override | ||
148 | + public void withdraw(Intent intent) { | ||
149 | + checkNotNull(intent, INTENT_NULL); | ||
150 | + // Withdraws the physical intents created due to the virtual intents. | ||
151 | + store.getTunnelIds(intent) | ||
152 | + .forEach(tunnelId -> { | ||
153 | + Key intentKey = Key.of(tunnelId.id(), intent.appId()); | ||
154 | + Intent physicalIntent = intentService.getIntent(intentKey); | ||
155 | + checkNotNull(physicalIntent, INTENT_NULL); | ||
156 | + | ||
157 | + // Withdraw the physical intent(s) | ||
158 | + log.info("Withdrawing pt-pt intent: " + physicalIntent); | ||
159 | + intentService.withdraw(physicalIntent); | ||
160 | + }); | ||
161 | + // Now withdraw the virtual intent | ||
162 | + log.info("Withdrawing virtual intent: " + intent); | ||
163 | + intentService.withdraw(intent); | ||
164 | + } | ||
165 | + | ||
166 | + @Override | ||
167 | + public void purge(Intent intent) { | ||
168 | + checkNotNull(intent, INTENT_NULL); | ||
169 | + // Purges the physical intents created for each tunnelId. | ||
170 | + store.getTunnelIds(intent) | ||
171 | + .forEach(tunnelId -> { | ||
172 | + Key intentKey = Key.of(tunnelId.id(), intent.appId()); | ||
173 | + Intent physicalIntent = intentService.getIntent(intentKey); | ||
174 | + checkNotNull(physicalIntent, INTENT_NULL); | ||
175 | + | ||
176 | + // Purge the physical intent(s) | ||
177 | + intentService.purge(physicalIntent); | ||
178 | + store.removeTunnelId(intent, tunnelId); | ||
179 | + }); | ||
180 | + // Now purge the virtual intent | ||
181 | + intentService.purge(intent); | ||
182 | + } | ||
183 | + | ||
184 | + @Override | ||
185 | + public Intent getIntent(Key key) { | ||
186 | + checkNotNull(key, KEY_NULL); | ||
187 | + return store.getIntent(key); | ||
188 | + } | ||
189 | + | ||
190 | + @Override | ||
191 | + public Iterable<Intent> getIntents() { | ||
192 | + return store.getIntents(); | ||
193 | + } | ||
194 | + | ||
195 | + @Override | ||
196 | + public Iterable<IntentData> getIntentData() { | ||
197 | + return store.getIntentData(); | ||
198 | + } | ||
199 | + | ||
200 | + @Override | ||
201 | + public long getIntentCount() { | ||
202 | + return Iterators.size(getIntents().iterator()); | ||
203 | + } | ||
204 | + | ||
205 | + @Override | ||
206 | + public IntentState getIntentState(Key intentKey) { | ||
207 | + checkNotNull(intentKey, KEY_NULL); | ||
208 | + return store.getIntentData(intentKey).state(); | ||
209 | + } | ||
210 | + | ||
211 | + @Override | ||
212 | + public List<Intent> getInstallableIntents(Key intentKey) { | ||
213 | + List<Intent> intents = new ArrayList<>(); | ||
214 | + getIntentData().forEach(intentData -> { | ||
215 | + if (intentData.intent().key().equals(intentKey)) { | ||
216 | + intents.addAll(intentData.installables()); | ||
217 | + } | ||
218 | + }); | ||
219 | + return intents; | ||
220 | + } | ||
221 | + | ||
222 | + @Override | ||
223 | + public boolean isLocal(Key intentKey) { | ||
224 | + checkNotNull(intentKey, INTENT_KEY_NULL); | ||
225 | + Intent intent = getIntent(intentKey); | ||
226 | + checkNotNull(intent, INTENT_NULL); | ||
227 | + return partitionService.isMine(intentKey); | ||
228 | + } | ||
229 | + | ||
230 | + @Override | ||
231 | + public Iterable<Intent> getPending() { | ||
232 | + return null; | ||
233 | + } | ||
234 | + | ||
235 | + | ||
236 | + @Override | ||
237 | + public VirtualNetwork network() { | ||
238 | + return network; | ||
239 | + } | ||
240 | +} |
... | @@ -22,6 +22,7 @@ import org.apache.felix.scr.annotations.Deactivate; | ... | @@ -22,6 +22,7 @@ import org.apache.felix.scr.annotations.Deactivate; |
22 | import org.apache.felix.scr.annotations.Reference; | 22 | import org.apache.felix.scr.annotations.Reference; |
23 | import org.apache.felix.scr.annotations.ReferenceCardinality; | 23 | import org.apache.felix.scr.annotations.ReferenceCardinality; |
24 | import org.apache.felix.scr.annotations.Service; | 24 | import org.apache.felix.scr.annotations.Service; |
25 | +import org.onlab.osgi.DefaultServiceDirectory; | ||
25 | import org.onlab.packet.IpAddress; | 26 | import org.onlab.packet.IpAddress; |
26 | import org.onlab.packet.MacAddress; | 27 | import org.onlab.packet.MacAddress; |
27 | import org.onlab.packet.VlanId; | 28 | import org.onlab.packet.VlanId; |
... | @@ -34,9 +35,9 @@ import org.onosproject.incubator.net.virtual.VirtualLink; | ... | @@ -34,9 +35,9 @@ import org.onosproject.incubator.net.virtual.VirtualLink; |
34 | import org.onosproject.incubator.net.virtual.VirtualNetwork; | 35 | import org.onosproject.incubator.net.virtual.VirtualNetwork; |
35 | import org.onosproject.incubator.net.virtual.VirtualNetworkAdminService; | 36 | import org.onosproject.incubator.net.virtual.VirtualNetworkAdminService; |
36 | import org.onosproject.incubator.net.virtual.VirtualNetworkEvent; | 37 | import org.onosproject.incubator.net.virtual.VirtualNetworkEvent; |
38 | +import org.onosproject.incubator.net.virtual.VirtualNetworkIntent; | ||
37 | import org.onosproject.incubator.net.virtual.VirtualNetworkListener; | 39 | import org.onosproject.incubator.net.virtual.VirtualNetworkListener; |
38 | import org.onosproject.incubator.net.virtual.VirtualNetworkProvider; | 40 | import org.onosproject.incubator.net.virtual.VirtualNetworkProvider; |
39 | -import org.onosproject.incubator.net.virtual.VirtualNetworkProviderRegistry; | ||
40 | import org.onosproject.incubator.net.virtual.VirtualNetworkProviderService; | 41 | import org.onosproject.incubator.net.virtual.VirtualNetworkProviderService; |
41 | import org.onosproject.incubator.net.virtual.VirtualNetworkService; | 42 | import org.onosproject.incubator.net.virtual.VirtualNetworkService; |
42 | import org.onosproject.incubator.net.virtual.VirtualNetworkStore; | 43 | import org.onosproject.incubator.net.virtual.VirtualNetworkStore; |
... | @@ -50,6 +51,10 @@ import org.onosproject.net.Link; | ... | @@ -50,6 +51,10 @@ import org.onosproject.net.Link; |
50 | import org.onosproject.net.Port; | 51 | import org.onosproject.net.Port; |
51 | import org.onosproject.net.PortNumber; | 52 | import org.onosproject.net.PortNumber; |
52 | import org.onosproject.net.device.DeviceService; | 53 | import org.onosproject.net.device.DeviceService; |
54 | +import org.onosproject.net.intent.IntentEvent; | ||
55 | +import org.onosproject.net.intent.IntentListener; | ||
56 | +import org.onosproject.net.intent.IntentService; | ||
57 | +import org.onosproject.net.intent.IntentState; | ||
53 | import org.onosproject.net.link.LinkService; | 58 | import org.onosproject.net.link.LinkService; |
54 | import org.onosproject.net.provider.AbstractListenerProviderRegistry; | 59 | import org.onosproject.net.provider.AbstractListenerProviderRegistry; |
55 | import org.onosproject.net.provider.AbstractProviderService; | 60 | import org.onosproject.net.provider.AbstractProviderService; |
... | @@ -70,7 +75,7 @@ import static com.google.common.base.Preconditions.checkNotNull; | ... | @@ -70,7 +75,7 @@ import static com.google.common.base.Preconditions.checkNotNull; |
70 | public class VirtualNetworkManager | 75 | public class VirtualNetworkManager |
71 | extends AbstractListenerProviderRegistry<VirtualNetworkEvent, VirtualNetworkListener, | 76 | extends AbstractListenerProviderRegistry<VirtualNetworkEvent, VirtualNetworkListener, |
72 | VirtualNetworkProvider, VirtualNetworkProviderService> | 77 | VirtualNetworkProvider, VirtualNetworkProviderService> |
73 | - implements VirtualNetworkService, VirtualNetworkAdminService, VirtualNetworkProviderRegistry { | 78 | + implements VirtualNetworkService, VirtualNetworkAdminService { |
74 | 79 | ||
75 | private final Logger log = LoggerFactory.getLogger(getClass()); | 80 | private final Logger log = LoggerFactory.getLogger(getClass()); |
76 | 81 | ||
... | @@ -78,28 +83,51 @@ public class VirtualNetworkManager | ... | @@ -78,28 +83,51 @@ public class VirtualNetworkManager |
78 | private static final String NETWORK_NULL = "Network ID cannot be null"; | 83 | private static final String NETWORK_NULL = "Network ID cannot be null"; |
79 | private static final String DEVICE_NULL = "Device ID cannot be null"; | 84 | private static final String DEVICE_NULL = "Device ID cannot be null"; |
80 | private static final String LINK_POINT_NULL = "Link end-point cannot be null"; | 85 | private static final String LINK_POINT_NULL = "Link end-point cannot be null"; |
81 | - private static final String VIRTUAL_LINK_NULL = "Virtual Link cannot be null"; | ||
82 | 86 | ||
83 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | 87 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
84 | protected VirtualNetworkStore store; | 88 | protected VirtualNetworkStore store; |
85 | 89 | ||
90 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
91 | + protected IntentService intentService; | ||
92 | + | ||
93 | + private final InternalVirtualIntentListener intentListener = new InternalVirtualIntentListener(); | ||
94 | + | ||
86 | private VirtualNetworkStoreDelegate delegate = this::post; | 95 | private VirtualNetworkStoreDelegate delegate = this::post; |
87 | 96 | ||
88 | // TODO: figure out how to coordinate "implementation" of a virtual network in a cluster | 97 | // TODO: figure out how to coordinate "implementation" of a virtual network in a cluster |
89 | 98 | ||
99 | + /** | ||
100 | + * Only used for Junit test methods outside of this package. | ||
101 | + * | ||
102 | + * @param store virtual network store | ||
103 | + */ | ||
104 | + public void setStore(VirtualNetworkStore store) { | ||
105 | + this.store = store; | ||
106 | + } | ||
107 | + | ||
108 | + /** | ||
109 | + * Only used for Junit test methods outside of this package. | ||
110 | + * | ||
111 | + * @param intentService intent service | ||
112 | + */ | ||
113 | + | ||
114 | + public void setIntentService(IntentService intentService) { | ||
115 | + this.intentService = intentService; | ||
116 | + } | ||
117 | + | ||
90 | @Activate | 118 | @Activate |
91 | - protected void activate() { | 119 | + public void activate() { |
92 | store.setDelegate(delegate); | 120 | store.setDelegate(delegate); |
93 | eventDispatcher.addSink(VirtualNetworkEvent.class, listenerRegistry); | 121 | eventDispatcher.addSink(VirtualNetworkEvent.class, listenerRegistry); |
94 | - | 122 | + intentService.addListener(intentListener); |
95 | log.info("Started"); | 123 | log.info("Started"); |
96 | } | 124 | } |
97 | 125 | ||
98 | @Deactivate | 126 | @Deactivate |
99 | - protected void deactivate() { | 127 | + public void deactivate() { |
100 | store.unsetDelegate(delegate); | 128 | store.unsetDelegate(delegate); |
101 | eventDispatcher.removeSink(VirtualNetworkEvent.class); | 129 | eventDispatcher.removeSink(VirtualNetworkEvent.class); |
102 | - | 130 | + intentService.removeListener(intentListener); |
103 | log.info("Stopped"); | 131 | log.info("Stopped"); |
104 | } | 132 | } |
105 | 133 | ||
... | @@ -167,48 +195,18 @@ public class VirtualNetworkManager | ... | @@ -167,48 +195,18 @@ public class VirtualNetworkManager |
167 | checkNotNull(networkId, NETWORK_NULL); | 195 | checkNotNull(networkId, NETWORK_NULL); |
168 | checkNotNull(src, LINK_POINT_NULL); | 196 | checkNotNull(src, LINK_POINT_NULL); |
169 | checkNotNull(dst, LINK_POINT_NULL); | 197 | checkNotNull(dst, LINK_POINT_NULL); |
170 | - VirtualLink virtualLink = store.addLink(networkId, src, dst, Link.State.INACTIVE, null); | 198 | + return store.addLink(networkId, src, dst, Link.State.ACTIVE, null); |
171 | - checkNotNull(virtualLink, VIRTUAL_LINK_NULL); | ||
172 | - | ||
173 | - if (virtualLink.providerId() != null) { | ||
174 | - VirtualNetworkProvider provider = getProvider(virtualLink.providerId()); | ||
175 | - if (provider != null) { | ||
176 | - TunnelId tunnelId = provider.createTunnel(networkId, mapVirtualToPhysicalPort(networkId, src), | ||
177 | - mapVirtualToPhysicalPort(networkId, dst)); | ||
178 | - store.updateLink(virtualLink, tunnelId, Link.State.INACTIVE); | ||
179 | - } | ||
180 | - } | ||
181 | - return virtualLink; | ||
182 | - } | ||
183 | - | ||
184 | - /** | ||
185 | - * Maps the virtual connect point to a physical connect point. | ||
186 | - * | ||
187 | - * @param networkId network identifier | ||
188 | - * @param virtualCp virtual connect point | ||
189 | - * @return physical connect point | ||
190 | - */ | ||
191 | - private ConnectPoint mapVirtualToPhysicalPort(NetworkId networkId, | ||
192 | - ConnectPoint virtualCp) { | ||
193 | - Set<VirtualPort> ports = store.getPorts(networkId, virtualCp.deviceId()); | ||
194 | - for (VirtualPort port : ports) { | ||
195 | - if (port.element().id().equals(virtualCp.elementId()) && | ||
196 | - port.number().equals(virtualCp.port())) { | ||
197 | - return new ConnectPoint(port.realizedBy().element().id(), port.realizedBy().number()); | ||
198 | - } | ||
199 | - } | ||
200 | - return null; | ||
201 | } | 199 | } |
202 | 200 | ||
203 | /** | 201 | /** |
204 | * Maps the physical connect point to a virtual connect point. | 202 | * Maps the physical connect point to a virtual connect point. |
205 | * | 203 | * |
206 | - * @param networkId network identifier | 204 | + * @param networkId network identifier |
207 | * @param physicalCp physical connect point | 205 | * @param physicalCp physical connect point |
208 | * @return virtual connect point | 206 | * @return virtual connect point |
209 | */ | 207 | */ |
210 | private ConnectPoint mapPhysicalToVirtualToPort(NetworkId networkId, | 208 | private ConnectPoint mapPhysicalToVirtualToPort(NetworkId networkId, |
211 | - ConnectPoint physicalCp) { | 209 | + ConnectPoint physicalCp) { |
212 | Set<VirtualPort> ports = store.getPorts(networkId, null); | 210 | Set<VirtualPort> ports = store.getPorts(networkId, null); |
213 | for (VirtualPort port : ports) { | 211 | for (VirtualPort port : ports) { |
214 | if (port.realizedBy().element().id().equals(physicalCp.elementId()) && | 212 | if (port.realizedBy().element().id().equals(physicalCp.elementId()) && |
... | @@ -224,14 +222,7 @@ public class VirtualNetworkManager | ... | @@ -224,14 +222,7 @@ public class VirtualNetworkManager |
224 | checkNotNull(networkId, NETWORK_NULL); | 222 | checkNotNull(networkId, NETWORK_NULL); |
225 | checkNotNull(src, LINK_POINT_NULL); | 223 | checkNotNull(src, LINK_POINT_NULL); |
226 | checkNotNull(dst, LINK_POINT_NULL); | 224 | checkNotNull(dst, LINK_POINT_NULL); |
227 | - VirtualLink virtualLink = store.removeLink(networkId, src, dst); | 225 | + store.removeLink(networkId, src, dst); |
228 | - | ||
229 | - if (virtualLink != null && virtualLink.providerId() != null) { | ||
230 | - VirtualNetworkProvider provider = getProvider(virtualLink.providerId()); | ||
231 | - if (provider != null) { | ||
232 | - provider.destroyTunnel(networkId, virtualLink.tunnelId()); | ||
233 | - } | ||
234 | - } | ||
235 | } | 226 | } |
236 | 227 | ||
237 | @Override | 228 | @Override |
... | @@ -257,6 +248,12 @@ public class VirtualNetworkManager | ... | @@ -257,6 +248,12 @@ public class VirtualNetworkManager |
257 | return store.getNetworks(tenantId); | 248 | return store.getNetworks(tenantId); |
258 | } | 249 | } |
259 | 250 | ||
251 | + /** | ||
252 | + * Returns the virtual network matching the network identifier. | ||
253 | + * | ||
254 | + * @param networkId network identifier | ||
255 | + * @return virtual network | ||
256 | + */ | ||
260 | private VirtualNetwork getVirtualNetwork(NetworkId networkId) { | 257 | private VirtualNetwork getVirtualNetwork(NetworkId networkId) { |
261 | checkNotNull(networkId, NETWORK_NULL); | 258 | checkNotNull(networkId, NETWORK_NULL); |
262 | return store.getNetwork(networkId); | 259 | return store.getNetwork(networkId); |
... | @@ -299,17 +296,38 @@ public class VirtualNetworkManager | ... | @@ -299,17 +296,38 @@ public class VirtualNetworkManager |
299 | return (T) service; | 296 | return (T) service; |
300 | } | 297 | } |
301 | 298 | ||
299 | + /** | ||
300 | + * Returns the Vnet service matching the service key. | ||
301 | + * | ||
302 | + * @param serviceKey service key | ||
303 | + * @return vnet service | ||
304 | + */ | ||
302 | private VnetService lookup(ServiceKey serviceKey) { | 305 | private VnetService lookup(ServiceKey serviceKey) { |
303 | return networkServices.get(serviceKey); | 306 | return networkServices.get(serviceKey); |
304 | } | 307 | } |
305 | 308 | ||
309 | + /** | ||
310 | + * Creates a new service key using the specified network identifier and service class. | ||
311 | + * | ||
312 | + * @param networkId network identifier | ||
313 | + * @param serviceClass service class | ||
314 | + * @param <T> type of service | ||
315 | + * @return service key | ||
316 | + */ | ||
306 | private <T> ServiceKey networkServiceKey(NetworkId networkId, Class<T> serviceClass) { | 317 | private <T> ServiceKey networkServiceKey(NetworkId networkId, Class<T> serviceClass) { |
307 | return new ServiceKey(networkId, serviceClass); | 318 | return new ServiceKey(networkId, serviceClass); |
308 | } | 319 | } |
309 | 320 | ||
310 | 321 | ||
322 | + /** | ||
323 | + * Create a new vnet service instance. | ||
324 | + * | ||
325 | + * @param serviceKey service key | ||
326 | + * @return vnet service | ||
327 | + */ | ||
311 | private VnetService create(ServiceKey serviceKey) { | 328 | private VnetService create(ServiceKey serviceKey) { |
312 | VirtualNetwork network = getVirtualNetwork(serviceKey.networkId()); | 329 | VirtualNetwork network = getVirtualNetwork(serviceKey.networkId()); |
330 | + checkNotNull(network, NETWORK_NULL); | ||
313 | VnetService service; | 331 | VnetService service; |
314 | if (serviceKey.serviceClass.equals(DeviceService.class)) { | 332 | if (serviceKey.serviceClass.equals(DeviceService.class)) { |
315 | service = new VirtualNetworkDeviceService(this, network); | 333 | service = new VirtualNetworkDeviceService(this, network); |
... | @@ -317,6 +335,8 @@ public class VirtualNetworkManager | ... | @@ -317,6 +335,8 @@ public class VirtualNetworkManager |
317 | service = new VirtualNetworkLinkService(this, network); | 335 | service = new VirtualNetworkLinkService(this, network); |
318 | } else if (serviceKey.serviceClass.equals(TopologyService.class)) { | 336 | } else if (serviceKey.serviceClass.equals(TopologyService.class)) { |
319 | service = new VirtualNetworkTopologyService(this, network); | 337 | service = new VirtualNetworkTopologyService(this, network); |
338 | + } else if (serviceKey.serviceClass.equals(IntentService.class)) { | ||
339 | + service = new VirtualNetworkIntentService(this, network, new DefaultServiceDirectory()); | ||
320 | } else { | 340 | } else { |
321 | return null; | 341 | return null; |
322 | } | 342 | } |
... | @@ -324,25 +344,94 @@ public class VirtualNetworkManager | ... | @@ -324,25 +344,94 @@ public class VirtualNetworkManager |
324 | return service; | 344 | return service; |
325 | } | 345 | } |
326 | 346 | ||
347 | + /** | ||
348 | + * Service key class. | ||
349 | + */ | ||
327 | private class ServiceKey { | 350 | private class ServiceKey { |
328 | final NetworkId networkId; | 351 | final NetworkId networkId; |
329 | final Class serviceClass; | 352 | final Class serviceClass; |
330 | 353 | ||
354 | + /** | ||
355 | + * Constructor for service key. | ||
356 | + * | ||
357 | + * @param networkId network identifier | ||
358 | + * @param serviceClass service class | ||
359 | + */ | ||
331 | public ServiceKey(NetworkId networkId, Class serviceClass) { | 360 | public ServiceKey(NetworkId networkId, Class serviceClass) { |
332 | checkNotNull(networkId, NETWORK_NULL); | 361 | checkNotNull(networkId, NETWORK_NULL); |
333 | this.networkId = networkId; | 362 | this.networkId = networkId; |
334 | this.serviceClass = serviceClass; | 363 | this.serviceClass = serviceClass; |
335 | } | 364 | } |
336 | 365 | ||
366 | + /** | ||
367 | + * Returns the network identifier. | ||
368 | + * | ||
369 | + * @return network identifier | ||
370 | + */ | ||
337 | public NetworkId networkId() { | 371 | public NetworkId networkId() { |
338 | return networkId; | 372 | return networkId; |
339 | } | 373 | } |
340 | 374 | ||
375 | + /** | ||
376 | + * Returns the service class. | ||
377 | + * | ||
378 | + * @return service class | ||
379 | + */ | ||
341 | public Class serviceClass() { | 380 | public Class serviceClass() { |
342 | return serviceClass; | 381 | return serviceClass; |
343 | } | 382 | } |
344 | } | 383 | } |
345 | 384 | ||
385 | + /** | ||
386 | + * Internal intent event listener. | ||
387 | + */ | ||
388 | + private class InternalVirtualIntentListener implements IntentListener { | ||
389 | + @Override | ||
390 | + public void event(IntentEvent event) { | ||
391 | + | ||
392 | + // Ignore intent events that are not relevant. | ||
393 | + if (!isRelevant(event)) { | ||
394 | + return; | ||
395 | + } | ||
396 | + | ||
397 | + VirtualNetworkIntent intent = (VirtualNetworkIntent) event.subject(); | ||
398 | + | ||
399 | + switch (event.type()) { | ||
400 | + case INSTALL_REQ: | ||
401 | + store.addOrUpdateIntent(intent, IntentState.INSTALL_REQ); | ||
402 | + break; | ||
403 | + case INSTALLED: | ||
404 | + store.addOrUpdateIntent(intent, IntentState.INSTALLED); | ||
405 | + break; | ||
406 | + case WITHDRAW_REQ: | ||
407 | + store.addOrUpdateIntent(intent, IntentState.WITHDRAW_REQ); | ||
408 | + break; | ||
409 | + case WITHDRAWN: | ||
410 | + store.addOrUpdateIntent(intent, IntentState.WITHDRAWN); | ||
411 | + break; | ||
412 | + case FAILED: | ||
413 | + store.addOrUpdateIntent(intent, IntentState.FAILED); | ||
414 | + break; | ||
415 | + case CORRUPT: | ||
416 | + store.addOrUpdateIntent(intent, IntentState.CORRUPT); | ||
417 | + break; | ||
418 | + case PURGED: | ||
419 | + store.removeIntent(intent.key()); | ||
420 | + default: | ||
421 | + break; | ||
422 | + } | ||
423 | + } | ||
424 | + | ||
425 | + @Override | ||
426 | + public boolean isRelevant(IntentEvent event) { | ||
427 | + if (event.subject() instanceof VirtualNetworkIntent) { | ||
428 | + return true; | ||
429 | + } | ||
430 | + return false; | ||
431 | + } | ||
432 | + } | ||
433 | + | ||
434 | + | ||
346 | @Override | 435 | @Override |
347 | protected VirtualNetworkProviderService createProviderService(VirtualNetworkProvider provider) { | 436 | protected VirtualNetworkProviderService createProviderService(VirtualNetworkProvider provider) { |
348 | return new InternalVirtualNetworkProviderService(provider); | 437 | return new InternalVirtualNetworkProviderService(provider); | ... | ... |
... | @@ -38,6 +38,8 @@ import org.onosproject.net.Port; | ... | @@ -38,6 +38,8 @@ import org.onosproject.net.Port; |
38 | import org.onosproject.net.PortNumber; | 38 | import org.onosproject.net.PortNumber; |
39 | import org.onosproject.net.TestDeviceParams; | 39 | import org.onosproject.net.TestDeviceParams; |
40 | import org.onosproject.net.device.DeviceService; | 40 | import org.onosproject.net.device.DeviceService; |
41 | +import org.onosproject.net.intent.FakeIntentManager; | ||
42 | +import org.onosproject.net.intent.TestableIntentService; | ||
41 | import org.onosproject.store.service.TestStorageService; | 43 | import org.onosproject.store.service.TestStorageService; |
42 | 44 | ||
43 | import java.util.Iterator; | 45 | import java.util.Iterator; |
... | @@ -54,6 +56,7 @@ public class VirtualNetworkDeviceServiceTest extends TestDeviceParams { | ... | @@ -54,6 +56,7 @@ public class VirtualNetworkDeviceServiceTest extends TestDeviceParams { |
54 | private VirtualNetworkManager manager; | 56 | private VirtualNetworkManager manager; |
55 | private DistributedVirtualNetworkStore virtualNetworkManagerStore; | 57 | private DistributedVirtualNetworkStore virtualNetworkManagerStore; |
56 | private CoreService coreService; | 58 | private CoreService coreService; |
59 | + private TestableIntentService intentService = new FakeIntentManager(); | ||
57 | 60 | ||
58 | @Before | 61 | @Before |
59 | public void setUp() throws Exception { | 62 | public void setUp() throws Exception { |
... | @@ -67,6 +70,7 @@ public class VirtualNetworkDeviceServiceTest extends TestDeviceParams { | ... | @@ -67,6 +70,7 @@ public class VirtualNetworkDeviceServiceTest extends TestDeviceParams { |
67 | 70 | ||
68 | manager = new VirtualNetworkManager(); | 71 | manager = new VirtualNetworkManager(); |
69 | manager.store = virtualNetworkManagerStore; | 72 | manager.store = virtualNetworkManagerStore; |
73 | + manager.intentService = intentService; | ||
70 | NetTestTools.injectEventDispatcher(manager, new TestEventDispatcher()); | 74 | NetTestTools.injectEventDispatcher(manager, new TestEventDispatcher()); |
71 | manager.activate(); | 75 | manager.activate(); |
72 | } | 76 | } | ... | ... |
1 | +/* | ||
2 | + * Copyright 2016-present Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | + | ||
17 | +package org.onosproject.incubator.net.virtual.impl; | ||
18 | + | ||
19 | +import com.google.common.collect.Iterators; | ||
20 | +import com.google.common.collect.Lists; | ||
21 | +import org.junit.After; | ||
22 | +import org.junit.Before; | ||
23 | +import org.junit.Test; | ||
24 | +import org.onlab.junit.TestUtils; | ||
25 | +import org.onlab.osgi.ServiceDirectory; | ||
26 | +import org.onlab.osgi.TestServiceDirectory; | ||
27 | +import org.onlab.rest.BaseResource; | ||
28 | +import org.onosproject.TestApplicationId; | ||
29 | +import org.onosproject.common.event.impl.TestEventDispatcher; | ||
30 | +import org.onosproject.core.ApplicationId; | ||
31 | +import org.onosproject.core.CoreService; | ||
32 | +import org.onosproject.core.CoreServiceAdapter; | ||
33 | +import org.onosproject.core.IdGenerator; | ||
34 | +import org.onosproject.incubator.net.virtual.TenantId; | ||
35 | +import org.onosproject.incubator.net.virtual.VirtualDevice; | ||
36 | +import org.onosproject.incubator.net.virtual.VirtualLink; | ||
37 | +import org.onosproject.incubator.net.virtual.VirtualNetwork; | ||
38 | +import org.onosproject.incubator.net.virtual.VirtualNetworkIntent; | ||
39 | +import org.onosproject.incubator.net.virtual.VirtualNetworkStore; | ||
40 | +import org.onosproject.incubator.store.virtual.impl.DistributedVirtualNetworkStore; | ||
41 | +import org.onosproject.net.ConnectPoint; | ||
42 | +import org.onosproject.net.DefaultPort; | ||
43 | +import org.onosproject.net.EncapsulationType; | ||
44 | +import org.onosproject.net.Link; | ||
45 | +import org.onosproject.net.NetTestTools; | ||
46 | +import org.onosproject.net.Port; | ||
47 | +import org.onosproject.net.PortNumber; | ||
48 | +import org.onosproject.net.TestDeviceParams; | ||
49 | +import org.onosproject.net.intent.Constraint; | ||
50 | +import org.onosproject.net.intent.FakeIntentManager; | ||
51 | +import org.onosproject.net.intent.FlowRuleIntent; | ||
52 | +import org.onosproject.net.intent.Intent; | ||
53 | +import org.onosproject.net.intent.IntentCompiler; | ||
54 | +import org.onosproject.net.intent.IntentEvent; | ||
55 | +import org.onosproject.net.intent.IntentExtensionService; | ||
56 | +import org.onosproject.net.intent.IntentListener; | ||
57 | +import org.onosproject.net.intent.IntentPartitionService; | ||
58 | +import org.onosproject.net.intent.IntentPartitionServiceAdapter; | ||
59 | +import org.onosproject.net.intent.IntentService; | ||
60 | +import org.onosproject.net.intent.IntentState; | ||
61 | +import org.onosproject.net.intent.IntentTestsMocks; | ||
62 | +import org.onosproject.net.intent.Key; | ||
63 | +import org.onosproject.net.intent.MockIdGenerator; | ||
64 | +import org.onosproject.net.intent.TestableIntentService; | ||
65 | +import org.onosproject.net.intent.constraint.EncapsulationConstraint; | ||
66 | +import org.onosproject.store.service.TestStorageService; | ||
67 | + | ||
68 | +import java.util.ArrayList; | ||
69 | +import java.util.Collections; | ||
70 | +import java.util.List; | ||
71 | +import java.util.concurrent.Semaphore; | ||
72 | +import java.util.concurrent.TimeUnit; | ||
73 | +import java.util.concurrent.atomic.AtomicLong; | ||
74 | + | ||
75 | +import static org.junit.Assert.*; | ||
76 | + | ||
77 | +/** | ||
78 | + * Junit tests for VirtualNetworkIntentService. | ||
79 | + */ | ||
80 | +public class VirtualNetworkIntentServiceTest extends TestDeviceParams { | ||
81 | + | ||
82 | + private final String tenantIdValue1 = "TENANT_ID1"; | ||
83 | + private static final ApplicationId APP_ID = | ||
84 | + new TestApplicationId(PtToPtIntentVirtualNetworkProvider.PTPT_INTENT_APPID); | ||
85 | + | ||
86 | + private ConnectPoint cp1; | ||
87 | + private ConnectPoint cp2; | ||
88 | + private ConnectPoint cp3; | ||
89 | + private ConnectPoint cp4; | ||
90 | + private ConnectPoint cp5; | ||
91 | + private ConnectPoint cp6; | ||
92 | + private VirtualLink link1; | ||
93 | + private VirtualLink link2; | ||
94 | + private VirtualLink link3; | ||
95 | + private VirtualLink link4; | ||
96 | + private VirtualLink link5; | ||
97 | + private VirtualLink link6; | ||
98 | + | ||
99 | + private VirtualNetworkManager manager; | ||
100 | + private static DistributedVirtualNetworkStore virtualNetworkManagerStore; | ||
101 | + private CoreService coreService; | ||
102 | + private TestableIntentService intentService = new FakeIntentManager(); | ||
103 | + private VirtualNetworkIntentService vnetIntentService; | ||
104 | + private TestIntentCompiler compiler = new TestIntentCompiler(); | ||
105 | + private IntentExtensionService intentExtensionService; | ||
106 | + private IntentPartitionService intentPartitionService; | ||
107 | + private ServiceDirectory testDirectory; | ||
108 | + private TestListener listener = new TestListener(); | ||
109 | + private IdGenerator idGenerator = new MockIdGenerator(); | ||
110 | + private static final int MAX_WAIT_TIME = 5; | ||
111 | + private static final int MAX_PERMITS = 1; | ||
112 | + private static Semaphore created; | ||
113 | + private static Semaphore withdrawn; | ||
114 | + private static Semaphore purged; | ||
115 | + | ||
116 | + @Before | ||
117 | + public void setUp() throws Exception { | ||
118 | + virtualNetworkManagerStore = new DistributedVirtualNetworkStore(); | ||
119 | + | ||
120 | + coreService = new VirtualNetworkIntentServiceTest.TestCoreService(); | ||
121 | + | ||
122 | + Intent.unbindIdGenerator(idGenerator); | ||
123 | + Intent.bindIdGenerator(idGenerator); | ||
124 | + | ||
125 | + virtualNetworkManagerStore.setCoreService(coreService); | ||
126 | + TestUtils.setField(coreService, "coreService", new VirtualNetworkIntentServiceTest.TestCoreService()); | ||
127 | + TestUtils.setField(virtualNetworkManagerStore, "storageService", new TestStorageService()); | ||
128 | + virtualNetworkManagerStore.activate(); | ||
129 | + | ||
130 | + manager = new VirtualNetworkManager(); | ||
131 | + manager.store = virtualNetworkManagerStore; | ||
132 | + NetTestTools.injectEventDispatcher(manager, new TestEventDispatcher()); | ||
133 | + manager.intentService = intentService; | ||
134 | + manager.activate(); | ||
135 | + intentService.addListener(listener); | ||
136 | + | ||
137 | + // Register a compiler and an installer both setup for success. | ||
138 | + intentExtensionService = intentService; | ||
139 | + intentExtensionService.registerCompiler(VirtualNetworkIntent.class, compiler); | ||
140 | + | ||
141 | + created = new Semaphore(0, true); | ||
142 | + withdrawn = new Semaphore(0, true); | ||
143 | + purged = new Semaphore(0, true); | ||
144 | + | ||
145 | + intentPartitionService = new IntentPartitionServiceAdapter(); | ||
146 | + testDirectory = new TestServiceDirectory() | ||
147 | + .add(VirtualNetworkStore.class, virtualNetworkManagerStore) | ||
148 | + .add(IntentService.class, intentService) | ||
149 | + .add(IntentPartitionService.class, intentPartitionService); | ||
150 | + BaseResource.setServiceDirectory(testDirectory); | ||
151 | + } | ||
152 | + | ||
153 | + @After | ||
154 | + public void tearDown() { | ||
155 | + virtualNetworkManagerStore.deactivate(); | ||
156 | + manager.deactivate(); | ||
157 | + NetTestTools.injectEventDispatcher(manager, null); | ||
158 | + Intent.unbindIdGenerator(idGenerator); | ||
159 | + intentService.removeListener(listener); | ||
160 | + created = null; | ||
161 | + withdrawn = null; | ||
162 | + purged = null; | ||
163 | + } | ||
164 | + | ||
165 | + /** | ||
166 | + * Method to create the virtual network for further testing. | ||
167 | + * | ||
168 | + * @return virtual network | ||
169 | + */ | ||
170 | + private VirtualNetwork setupVirtualNetworkTopology() { | ||
171 | + manager.registerTenantId(TenantId.tenantId(tenantIdValue1)); | ||
172 | + VirtualNetwork virtualNetwork = manager.createVirtualNetwork(TenantId.tenantId(tenantIdValue1)); | ||
173 | + VirtualDevice virtualDevice1 = | ||
174 | + manager.createVirtualDevice(virtualNetwork.id(), DID1); | ||
175 | + VirtualDevice virtualDevice2 = | ||
176 | + manager.createVirtualDevice(virtualNetwork.id(), DID2); | ||
177 | + VirtualDevice virtualDevice3 = | ||
178 | + manager.createVirtualDevice(virtualNetwork.id(), DID3); | ||
179 | + VirtualDevice virtualDevice4 = | ||
180 | + manager.createVirtualDevice(virtualNetwork.id(), DID4); | ||
181 | + | ||
182 | + Port port1 = new DefaultPort(virtualDevice1, PortNumber.portNumber(1), true); | ||
183 | + manager.createVirtualPort(virtualNetwork.id(), virtualDevice1.id(), port1.number(), port1); | ||
184 | + cp1 = new ConnectPoint(virtualDevice1.id(), port1.number()); | ||
185 | + | ||
186 | + Port port2 = new DefaultPort(virtualDevice1, PortNumber.portNumber(2), true); | ||
187 | + manager.createVirtualPort(virtualNetwork.id(), virtualDevice1.id(), port2.number(), port2); | ||
188 | + cp2 = new ConnectPoint(virtualDevice1.id(), port2.number()); | ||
189 | + | ||
190 | + Port port3 = new DefaultPort(virtualDevice2, PortNumber.portNumber(3), true); | ||
191 | + manager.createVirtualPort(virtualNetwork.id(), virtualDevice2.id(), port3.number(), port3); | ||
192 | + cp3 = new ConnectPoint(virtualDevice2.id(), port3.number()); | ||
193 | + | ||
194 | + Port port4 = new DefaultPort(virtualDevice2, PortNumber.portNumber(4), true); | ||
195 | + manager.createVirtualPort(virtualNetwork.id(), virtualDevice2.id(), port4.number(), port4); | ||
196 | + cp4 = new ConnectPoint(virtualDevice2.id(), port4.number()); | ||
197 | + | ||
198 | + Port port5 = new DefaultPort(virtualDevice3, PortNumber.portNumber(5), true); | ||
199 | + manager.createVirtualPort(virtualNetwork.id(), virtualDevice3.id(), port5.number(), port5); | ||
200 | + cp5 = new ConnectPoint(virtualDevice3.id(), port5.number()); | ||
201 | + | ||
202 | + Port port6 = new DefaultPort(virtualDevice3, PortNumber.portNumber(6), true); | ||
203 | + manager.createVirtualPort(virtualNetwork.id(), virtualDevice3.id(), port6.number(), port6); | ||
204 | + cp6 = new ConnectPoint(virtualDevice3.id(), port6.number()); | ||
205 | + | ||
206 | + link1 = manager.createVirtualLink(virtualNetwork.id(), cp1, cp3); | ||
207 | + virtualNetworkManagerStore.updateLink(link1, link1.tunnelId(), Link.State.ACTIVE); | ||
208 | + link2 = manager.createVirtualLink(virtualNetwork.id(), cp3, cp1); | ||
209 | + virtualNetworkManagerStore.updateLink(link2, link2.tunnelId(), Link.State.ACTIVE); | ||
210 | + link3 = manager.createVirtualLink(virtualNetwork.id(), cp4, cp5); | ||
211 | + virtualNetworkManagerStore.updateLink(link3, link3.tunnelId(), Link.State.ACTIVE); | ||
212 | + link4 = manager.createVirtualLink(virtualNetwork.id(), cp5, cp4); | ||
213 | + virtualNetworkManagerStore.updateLink(link4, link4.tunnelId(), Link.State.ACTIVE); | ||
214 | + | ||
215 | + vnetIntentService = new VirtualNetworkIntentService(manager, virtualNetwork, testDirectory); | ||
216 | + vnetIntentService.intentService = intentService; | ||
217 | + vnetIntentService.store = virtualNetworkManagerStore; | ||
218 | + vnetIntentService.partitionService = intentPartitionService; | ||
219 | + return virtualNetwork; | ||
220 | + } | ||
221 | + | ||
222 | + /** | ||
223 | + * Tests the submit(), withdraw(), and purge() methods. | ||
224 | + */ | ||
225 | + @Test | ||
226 | + public void testCreateAndRemoveIntent() { | ||
227 | + VirtualNetwork virtualNetwork = setupVirtualNetworkTopology(); | ||
228 | + | ||
229 | + Key intentKey = Key.of("test", APP_ID); | ||
230 | + | ||
231 | + List<Constraint> constraints = new ArrayList<>(); | ||
232 | + constraints.add(new EncapsulationConstraint(EncapsulationType.VLAN)); | ||
233 | + | ||
234 | + VirtualNetworkIntent virtualIntent = VirtualNetworkIntent.builder() | ||
235 | + .networkId(virtualNetwork.id()) | ||
236 | + .key(intentKey) | ||
237 | + .appId(APP_ID) | ||
238 | + .ingressPoint(cp1) | ||
239 | + .egressPoint(cp5) | ||
240 | + .constraints(constraints) | ||
241 | + .build(); | ||
242 | + // Test the submit() method. | ||
243 | + vnetIntentService.submit(virtualIntent); | ||
244 | + | ||
245 | + // Wait for the both intents to go into an INSTALLED state. | ||
246 | + try { | ||
247 | + if (!created.tryAcquire(MAX_PERMITS, MAX_WAIT_TIME, TimeUnit.SECONDS)) { | ||
248 | + fail("Failed to wait for intent to get installed."); | ||
249 | + } | ||
250 | + } catch (InterruptedException e) { | ||
251 | + fail("Semaphore exception during intent installation." + e.getMessage()); | ||
252 | + } | ||
253 | + | ||
254 | + // Test the getIntentState() method | ||
255 | + assertEquals("The intent state did not match as expected.", IntentState.INSTALLED, | ||
256 | + vnetIntentService.getIntentState(virtualIntent.key())); | ||
257 | + | ||
258 | + // Test the withdraw() method. | ||
259 | + vnetIntentService.withdraw(virtualIntent); | ||
260 | + // Wait for the both intents to go into a WITHDRAWN state. | ||
261 | + try { | ||
262 | + if (!withdrawn.tryAcquire(MAX_PERMITS, MAX_WAIT_TIME, TimeUnit.SECONDS)) { | ||
263 | + fail("Failed to wait for intent to get withdrawn."); | ||
264 | + } | ||
265 | + } catch (InterruptedException e) { | ||
266 | + fail("Semaphore exception during intent withdrawal." + e.getMessage()); | ||
267 | + } | ||
268 | + | ||
269 | + // Test the getIntentState() method | ||
270 | + assertEquals("The intent state did not match as expected.", IntentState.WITHDRAWN, | ||
271 | + vnetIntentService.getIntentState(virtualIntent.key())); | ||
272 | + | ||
273 | + // Test the purge() method. | ||
274 | + vnetIntentService.purge(virtualIntent); | ||
275 | + // Wait for the both intents to be removed/purged. | ||
276 | + try { | ||
277 | + if (!purged.tryAcquire(MAX_PERMITS, MAX_WAIT_TIME, TimeUnit.SECONDS)) { | ||
278 | + fail("Failed to wait for intent to get purged."); | ||
279 | + } | ||
280 | + } catch (InterruptedException e) { | ||
281 | + fail("Semaphore exception during intent purging." + e.getMessage()); | ||
282 | + } | ||
283 | + | ||
284 | + } | ||
285 | + | ||
286 | + /** | ||
287 | + * Tests the getIntents, getIntent(), getIntentData(), getIntentCount(), | ||
288 | + * isLocal() methods. | ||
289 | + */ | ||
290 | + @Test | ||
291 | + public void testGetIntents() { | ||
292 | + VirtualNetwork virtualNetwork = setupVirtualNetworkTopology(); | ||
293 | + | ||
294 | + Key intentKey = Key.of("test", APP_ID); | ||
295 | + | ||
296 | + List<Constraint> constraints = new ArrayList<>(); | ||
297 | + constraints.add(new EncapsulationConstraint(EncapsulationType.VLAN)); | ||
298 | + | ||
299 | + VirtualNetworkIntent virtualIntent = VirtualNetworkIntent.builder() | ||
300 | + .networkId(virtualNetwork.id()) | ||
301 | + .key(intentKey) | ||
302 | + .appId(APP_ID) | ||
303 | + .ingressPoint(cp1) | ||
304 | + .egressPoint(cp5) | ||
305 | + .constraints(constraints) | ||
306 | + .build(); | ||
307 | + // Test the submit() method. | ||
308 | + vnetIntentService.submit(virtualIntent); | ||
309 | + | ||
310 | + // Wait for the both intents to go into an INSTALLED state. | ||
311 | + try { | ||
312 | + if (!created.tryAcquire(MAX_PERMITS, MAX_WAIT_TIME, TimeUnit.SECONDS)) { | ||
313 | + fail("Failed to wait for intent to get installed."); | ||
314 | + } | ||
315 | + } catch (InterruptedException e) { | ||
316 | + fail("Semaphore exception during intent installation." + e.getMessage()); | ||
317 | + } | ||
318 | + | ||
319 | + // Test the getIntents() method | ||
320 | + assertEquals("The intents size did not match as expected.", 1, | ||
321 | + Iterators.size(vnetIntentService.getIntents().iterator())); | ||
322 | + | ||
323 | + // Test the getIntent() method | ||
324 | + assertNotNull("The intent should have been found.", vnetIntentService.getIntent(virtualIntent.key())); | ||
325 | + | ||
326 | + // Test the getIntentData() method | ||
327 | + assertEquals("The intent data size did not match as expected.", 1, | ||
328 | + Iterators.size(vnetIntentService.getIntentData().iterator())); | ||
329 | + | ||
330 | + // Test the getIntentCount() method | ||
331 | + assertEquals("The intent count did not match as expected.", 1, | ||
332 | + vnetIntentService.getIntentCount()); | ||
333 | + | ||
334 | + // Test the isLocal() method | ||
335 | + assertTrue("The intent should be local.", vnetIntentService.isLocal(virtualIntent.key())); | ||
336 | + | ||
337 | + } | ||
338 | + | ||
339 | + /** | ||
340 | + * Test listener to listen for intent events. | ||
341 | + */ | ||
342 | + private static class TestListener implements IntentListener { | ||
343 | + | ||
344 | + @Override | ||
345 | + public void event(IntentEvent event) { | ||
346 | + switch (event.type()) { | ||
347 | + case INSTALLED: | ||
348 | + // Release one permit on the created semaphore since the Intent event was received. | ||
349 | + virtualNetworkManagerStore.addOrUpdateIntent(event.subject(), IntentState.INSTALLED); | ||
350 | + created.release(); | ||
351 | + break; | ||
352 | + case WITHDRAWN: | ||
353 | + // Release one permit on the removed semaphore since the Intent event was received. | ||
354 | + virtualNetworkManagerStore.addOrUpdateIntent(event.subject(), IntentState.WITHDRAWN); | ||
355 | + withdrawn.release(); | ||
356 | + break; | ||
357 | + case PURGED: | ||
358 | + // Release one permit on the purged semaphore since the Intent event was received. | ||
359 | + purged.release(); | ||
360 | + break; | ||
361 | + default: | ||
362 | + break; | ||
363 | + } | ||
364 | + } | ||
365 | + } | ||
366 | + | ||
367 | + /** | ||
368 | + * Core service test class. | ||
369 | + */ | ||
370 | + private class TestCoreService extends CoreServiceAdapter { | ||
371 | + | ||
372 | + @Override | ||
373 | + public IdGenerator getIdGenerator(String topic) { | ||
374 | + return new IdGenerator() { | ||
375 | + private AtomicLong counter = new AtomicLong(0); | ||
376 | + | ||
377 | + @Override | ||
378 | + public long getNewId() { | ||
379 | + return counter.getAndIncrement(); | ||
380 | + } | ||
381 | + }; | ||
382 | + } | ||
383 | + } | ||
384 | + | ||
385 | + private static class TestIntentCompiler implements IntentCompiler<VirtualNetworkIntent> { | ||
386 | + @Override | ||
387 | + public List<Intent> compile(VirtualNetworkIntent intent, List<Intent> installable) { | ||
388 | + return Lists.newArrayList(new MockInstallableIntent()); | ||
389 | + } | ||
390 | + } | ||
391 | + | ||
392 | + private static class MockInstallableIntent extends FlowRuleIntent { | ||
393 | + | ||
394 | + public MockInstallableIntent() { | ||
395 | + super(APP_ID, Collections.singletonList(new IntentTestsMocks.MockFlowRule(100)), Collections.emptyList()); | ||
396 | + } | ||
397 | + } | ||
398 | +} |
... | @@ -35,6 +35,8 @@ import org.onosproject.net.Link; | ... | @@ -35,6 +35,8 @@ import org.onosproject.net.Link; |
35 | import org.onosproject.net.NetTestTools; | 35 | import org.onosproject.net.NetTestTools; |
36 | import org.onosproject.net.PortNumber; | 36 | import org.onosproject.net.PortNumber; |
37 | import org.onosproject.net.TestDeviceParams; | 37 | import org.onosproject.net.TestDeviceParams; |
38 | +import org.onosproject.net.intent.FakeIntentManager; | ||
39 | +import org.onosproject.net.intent.TestableIntentService; | ||
38 | import org.onosproject.net.link.LinkService; | 40 | import org.onosproject.net.link.LinkService; |
39 | import org.onosproject.store.service.TestStorageService; | 41 | import org.onosproject.store.service.TestStorageService; |
40 | 42 | ||
... | @@ -54,6 +56,7 @@ public class VirtualNetworkLinkServiceTest extends TestDeviceParams { | ... | @@ -54,6 +56,7 @@ public class VirtualNetworkLinkServiceTest extends TestDeviceParams { |
54 | private VirtualNetworkManager manager; | 56 | private VirtualNetworkManager manager; |
55 | private DistributedVirtualNetworkStore virtualNetworkManagerStore; | 57 | private DistributedVirtualNetworkStore virtualNetworkManagerStore; |
56 | private CoreService coreService; | 58 | private CoreService coreService; |
59 | + private TestableIntentService intentService = new FakeIntentManager(); | ||
57 | 60 | ||
58 | @Before | 61 | @Before |
59 | public void setUp() throws Exception { | 62 | public void setUp() throws Exception { |
... | @@ -67,6 +70,7 @@ public class VirtualNetworkLinkServiceTest extends TestDeviceParams { | ... | @@ -67,6 +70,7 @@ public class VirtualNetworkLinkServiceTest extends TestDeviceParams { |
67 | 70 | ||
68 | manager = new VirtualNetworkManager(); | 71 | manager = new VirtualNetworkManager(); |
69 | manager.store = virtualNetworkManagerStore; | 72 | manager.store = virtualNetworkManagerStore; |
73 | + manager.intentService = intentService; | ||
70 | NetTestTools.injectEventDispatcher(manager, new TestEventDispatcher()); | 74 | NetTestTools.injectEventDispatcher(manager, new TestEventDispatcher()); |
71 | manager.activate(); | 75 | manager.activate(); |
72 | } | 76 | } |
... | @@ -103,12 +107,12 @@ public class VirtualNetworkLinkServiceTest extends TestDeviceParams { | ... | @@ -103,12 +107,12 @@ public class VirtualNetworkLinkServiceTest extends TestDeviceParams { |
103 | Iterator<Link> it = linkService.getLinks().iterator(); | 107 | Iterator<Link> it = linkService.getLinks().iterator(); |
104 | assertEquals("The link set size did not match.", 2, Iterators.size(it)); | 108 | assertEquals("The link set size did not match.", 2, Iterators.size(it)); |
105 | 109 | ||
106 | - // test the getActiveLinks() method where no links are ACTIVE | 110 | + // test the getActiveLinks() method where all links are ACTIVE |
107 | Iterator<Link> it2 = linkService.getActiveLinks().iterator(); | 111 | Iterator<Link> it2 = linkService.getActiveLinks().iterator(); |
108 | - assertEquals("The link set size did not match.", 0, Iterators.size(it2)); | 112 | + assertEquals("The link set size did not match.", 2, Iterators.size(it2)); |
109 | 113 | ||
110 | // test the getActiveLinks() method where one link is ACTIVE | 114 | // test the getActiveLinks() method where one link is ACTIVE |
111 | - virtualNetworkManagerStore.updateLink(link1, link1.tunnelId(), Link.State.ACTIVE); | 115 | + virtualNetworkManagerStore.updateLink(link1, link1.tunnelId(), Link.State.INACTIVE); |
112 | Iterator<Link> it3 = linkService.getActiveLinks().iterator(); | 116 | Iterator<Link> it3 = linkService.getActiveLinks().iterator(); |
113 | assertEquals("The link set size did not match.", 1, Iterators.size(it3)); | 117 | assertEquals("The link set size did not match.", 1, Iterators.size(it3)); |
114 | 118 | ... | ... |
... | @@ -27,6 +27,7 @@ import org.onosproject.core.CoreService; | ... | @@ -27,6 +27,7 @@ import org.onosproject.core.CoreService; |
27 | import org.onosproject.core.CoreServiceAdapter; | 27 | import org.onosproject.core.CoreServiceAdapter; |
28 | import org.onosproject.core.IdGenerator; | 28 | import org.onosproject.core.IdGenerator; |
29 | import org.onosproject.event.Event; | 29 | import org.onosproject.event.Event; |
30 | +import org.onosproject.incubator.net.tunnel.TunnelId; | ||
30 | import org.onosproject.incubator.net.virtual.DefaultVirtualNetwork; | 31 | import org.onosproject.incubator.net.virtual.DefaultVirtualNetwork; |
31 | import org.onosproject.incubator.net.virtual.NetworkId; | 32 | import org.onosproject.incubator.net.virtual.NetworkId; |
32 | import org.onosproject.incubator.net.virtual.TenantId; | 33 | import org.onosproject.incubator.net.virtual.TenantId; |
... | @@ -35,6 +36,7 @@ import org.onosproject.incubator.net.virtual.VirtualHost; | ... | @@ -35,6 +36,7 @@ import org.onosproject.incubator.net.virtual.VirtualHost; |
35 | import org.onosproject.incubator.net.virtual.VirtualLink; | 36 | import org.onosproject.incubator.net.virtual.VirtualLink; |
36 | import org.onosproject.incubator.net.virtual.VirtualNetwork; | 37 | import org.onosproject.incubator.net.virtual.VirtualNetwork; |
37 | import org.onosproject.incubator.net.virtual.VirtualNetworkEvent; | 38 | import org.onosproject.incubator.net.virtual.VirtualNetworkEvent; |
39 | +import org.onosproject.incubator.net.virtual.VirtualNetworkIntent; | ||
38 | import org.onosproject.incubator.net.virtual.VirtualNetworkListener; | 40 | import org.onosproject.incubator.net.virtual.VirtualNetworkListener; |
39 | import org.onosproject.incubator.net.virtual.VirtualNetworkService; | 41 | import org.onosproject.incubator.net.virtual.VirtualNetworkService; |
40 | import org.onosproject.incubator.net.virtual.VirtualPort; | 42 | import org.onosproject.incubator.net.virtual.VirtualPort; |
... | @@ -46,6 +48,12 @@ import org.onosproject.net.NetTestTools; | ... | @@ -46,6 +48,12 @@ import org.onosproject.net.NetTestTools; |
46 | import org.onosproject.net.Port; | 48 | import org.onosproject.net.Port; |
47 | import org.onosproject.net.PortNumber; | 49 | import org.onosproject.net.PortNumber; |
48 | import org.onosproject.net.TestDeviceParams; | 50 | import org.onosproject.net.TestDeviceParams; |
51 | +import org.onosproject.net.intent.FakeIntentManager; | ||
52 | +import org.onosproject.net.intent.Intent; | ||
53 | +import org.onosproject.net.intent.IntentState; | ||
54 | +import org.onosproject.net.intent.Key; | ||
55 | +import org.onosproject.net.intent.MockIdGenerator; | ||
56 | +import org.onosproject.net.intent.TestableIntentService; | ||
49 | import org.onosproject.store.service.TestStorageService; | 57 | import org.onosproject.store.service.TestStorageService; |
50 | 58 | ||
51 | import java.util.Collection; | 59 | import java.util.Collection; |
... | @@ -54,6 +62,7 @@ import java.util.Set; | ... | @@ -54,6 +62,7 @@ import java.util.Set; |
54 | import java.util.concurrent.atomic.AtomicLong; | 62 | import java.util.concurrent.atomic.AtomicLong; |
55 | 63 | ||
56 | import static org.junit.Assert.*; | 64 | import static org.junit.Assert.*; |
65 | +import static org.onosproject.net.NetTestTools.APP_ID; | ||
57 | 66 | ||
58 | /** | 67 | /** |
59 | * Junit tests for VirtualNetworkManager. | 68 | * Junit tests for VirtualNetworkManager. |
... | @@ -67,10 +76,13 @@ public class VirtualNetworkManagerTest extends TestDeviceParams { | ... | @@ -67,10 +76,13 @@ public class VirtualNetworkManagerTest extends TestDeviceParams { |
67 | private DistributedVirtualNetworkStore virtualNetworkManagerStore; | 76 | private DistributedVirtualNetworkStore virtualNetworkManagerStore; |
68 | private CoreService coreService; | 77 | private CoreService coreService; |
69 | private TestListener listener = new TestListener(); | 78 | private TestListener listener = new TestListener(); |
79 | + private TestableIntentService intentService = new FakeIntentManager(); | ||
80 | + private IdGenerator idGenerator = new MockIdGenerator(); | ||
70 | 81 | ||
71 | @Before | 82 | @Before |
72 | public void setUp() throws Exception { | 83 | public void setUp() throws Exception { |
73 | virtualNetworkManagerStore = new DistributedVirtualNetworkStore(); | 84 | virtualNetworkManagerStore = new DistributedVirtualNetworkStore(); |
85 | + Intent.bindIdGenerator(idGenerator); | ||
74 | 86 | ||
75 | coreService = new TestCoreService(); | 87 | coreService = new TestCoreService(); |
76 | virtualNetworkManagerStore.setCoreService(coreService); | 88 | virtualNetworkManagerStore.setCoreService(coreService); |
... | @@ -81,6 +93,7 @@ public class VirtualNetworkManagerTest extends TestDeviceParams { | ... | @@ -81,6 +93,7 @@ public class VirtualNetworkManagerTest extends TestDeviceParams { |
81 | manager = new VirtualNetworkManager(); | 93 | manager = new VirtualNetworkManager(); |
82 | manager.store = virtualNetworkManagerStore; | 94 | manager.store = virtualNetworkManagerStore; |
83 | manager.addListener(listener); | 95 | manager.addListener(listener); |
96 | + manager.intentService = intentService; | ||
84 | NetTestTools.injectEventDispatcher(manager, new TestEventDispatcher()); | 97 | NetTestTools.injectEventDispatcher(manager, new TestEventDispatcher()); |
85 | manager.activate(); | 98 | manager.activate(); |
86 | virtualNetworkManagerService = manager; | 99 | virtualNetworkManagerService = manager; |
... | @@ -92,6 +105,7 @@ public class VirtualNetworkManagerTest extends TestDeviceParams { | ... | @@ -92,6 +105,7 @@ public class VirtualNetworkManagerTest extends TestDeviceParams { |
92 | manager.removeListener(listener); | 105 | manager.removeListener(listener); |
93 | manager.deactivate(); | 106 | manager.deactivate(); |
94 | NetTestTools.injectEventDispatcher(manager, null); | 107 | NetTestTools.injectEventDispatcher(manager, null); |
108 | + Intent.unbindIdGenerator(idGenerator); | ||
95 | } | 109 | } |
96 | 110 | ||
97 | /** | 111 | /** |
... | @@ -377,6 +391,95 @@ public class VirtualNetworkManagerTest extends TestDeviceParams { | ... | @@ -377,6 +391,95 @@ public class VirtualNetworkManagerTest extends TestDeviceParams { |
377 | } | 391 | } |
378 | 392 | ||
379 | /** | 393 | /** |
394 | + * Tests the addOrUpdateIntent() method in the store with a null intent. | ||
395 | + */ | ||
396 | + @Test(expected = NullPointerException.class) | ||
397 | + public void testAddOrUpdateNullIntent() { | ||
398 | + manager.store.addOrUpdateIntent(null, null); | ||
399 | + } | ||
400 | + | ||
401 | + /** | ||
402 | + * Tests the removeIntent() method in the store with a null intent key. | ||
403 | + */ | ||
404 | + @Test(expected = NullPointerException.class) | ||
405 | + public void testRemoveNullIntentKey() { | ||
406 | + manager.store.removeIntent(null); | ||
407 | + } | ||
408 | + | ||
409 | + /** | ||
410 | + * Tests the addOrUpdateIntent(), getIntents(), getIntent(), removeIntent() methods with the store. | ||
411 | + */ | ||
412 | + @Test | ||
413 | + public void testAddOrUpdateIntent() { | ||
414 | + manager.registerTenantId(TenantId.tenantId(tenantIdValue1)); | ||
415 | + VirtualNetwork virtualNetwork = manager.createVirtualNetwork(TenantId.tenantId(tenantIdValue1)); | ||
416 | + ConnectPoint cp1 = new ConnectPoint(DID1, P1); | ||
417 | + ConnectPoint cp2 = new ConnectPoint(DID2, P1); | ||
418 | + | ||
419 | + VirtualNetworkIntent virtualIntent = VirtualNetworkIntent.builder() | ||
420 | + .networkId(virtualNetwork.id()) | ||
421 | + .key(Key.of("Test", APP_ID)) | ||
422 | + .appId(APP_ID) | ||
423 | + .ingressPoint(cp1) | ||
424 | + .egressPoint(cp2) | ||
425 | + .build(); | ||
426 | + | ||
427 | + // Add the intent to the store. | ||
428 | + manager.store.addOrUpdateIntent(virtualIntent, IntentState.INSTALL_REQ); | ||
429 | + assertEquals("The intent size should match.", 1, manager.store.getIntents().size()); | ||
430 | + assertNotNull("The intent should not be null.", manager.store.getIntent(virtualIntent.key())); | ||
431 | + | ||
432 | + // remove the intent from the store. | ||
433 | + manager.store.removeIntent(virtualIntent.key()); | ||
434 | + assertTrue("The intents should be empty.", manager.store.getIntents().isEmpty()); | ||
435 | + assertNull("The intent should be null.", manager.store.getIntent(virtualIntent.key())); | ||
436 | + } | ||
437 | + | ||
438 | + /** | ||
439 | + * Tests the addTunnelId() method in the store with a null intent. | ||
440 | + */ | ||
441 | + @Test(expected = NullPointerException.class) | ||
442 | + public void testAddTunnelIdNullIntent() { | ||
443 | + manager.store.addTunnelId(null, null); | ||
444 | + } | ||
445 | + | ||
446 | + /** | ||
447 | + * Tests the removeTunnelId() method in the store with a null intent. | ||
448 | + */ | ||
449 | + @Test(expected = NullPointerException.class) | ||
450 | + public void testRemoveTunnelIdNullIntent() { | ||
451 | + manager.store.removeTunnelId(null, null); | ||
452 | + } | ||
453 | + | ||
454 | + /** | ||
455 | + * Tests the addTunnelId, getTunnelIds(), removeTunnelId() methods with the store. | ||
456 | + */ | ||
457 | + @Test | ||
458 | + public void testAddTunnelId() { | ||
459 | + manager.registerTenantId(TenantId.tenantId(tenantIdValue1)); | ||
460 | + VirtualNetwork virtualNetwork = manager.createVirtualNetwork(TenantId.tenantId(tenantIdValue1)); | ||
461 | + ConnectPoint cp1 = new ConnectPoint(DID1, P1); | ||
462 | + ConnectPoint cp2 = new ConnectPoint(DID2, P1); | ||
463 | + | ||
464 | + VirtualNetworkIntent virtualIntent = VirtualNetworkIntent.builder() | ||
465 | + .networkId(virtualNetwork.id()) | ||
466 | + .key(Key.of("Test", APP_ID)) | ||
467 | + .appId(APP_ID) | ||
468 | + .ingressPoint(cp1) | ||
469 | + .egressPoint(cp2) | ||
470 | + .build(); | ||
471 | + | ||
472 | + TunnelId tunnelId = TunnelId.valueOf("virtual tunnel"); | ||
473 | + // Add the intent to tunnelID mapping to the store. | ||
474 | + manager.store.addTunnelId(virtualIntent, tunnelId); | ||
475 | + assertEquals("The tunnels size should match.", 1, manager.store.getTunnelIds(virtualIntent).size()); | ||
476 | + | ||
477 | + // Remove the intent to tunnelID mapping from the store. | ||
478 | + manager.store.removeTunnelId(virtualIntent, tunnelId); | ||
479 | + assertTrue("The tunnels should be empty.", manager.store.getTunnelIds(virtualIntent).isEmpty()); | ||
480 | + } | ||
481 | + | ||
482 | + /** | ||
380 | * Method to validate that the actual versus expected virtual network events were | 483 | * Method to validate that the actual versus expected virtual network events were |
381 | * received correctly. | 484 | * received correctly. |
382 | * | 485 | * | ... | ... |
... | @@ -38,6 +38,8 @@ import org.onosproject.net.NetTestTools; | ... | @@ -38,6 +38,8 @@ import org.onosproject.net.NetTestTools; |
38 | import org.onosproject.net.Path; | 38 | import org.onosproject.net.Path; |
39 | import org.onosproject.net.PortNumber; | 39 | import org.onosproject.net.PortNumber; |
40 | import org.onosproject.net.TestDeviceParams; | 40 | import org.onosproject.net.TestDeviceParams; |
41 | +import org.onosproject.net.intent.FakeIntentManager; | ||
42 | +import org.onosproject.net.intent.TestableIntentService; | ||
41 | import org.onosproject.net.topology.LinkWeight; | 43 | import org.onosproject.net.topology.LinkWeight; |
42 | import org.onosproject.net.topology.Topology; | 44 | import org.onosproject.net.topology.Topology; |
43 | import org.onosproject.net.topology.TopologyCluster; | 45 | import org.onosproject.net.topology.TopologyCluster; |
... | @@ -62,6 +64,7 @@ public class VirtualNetworkTopologyServiceTest extends TestDeviceParams { | ... | @@ -62,6 +64,7 @@ public class VirtualNetworkTopologyServiceTest extends TestDeviceParams { |
62 | private VirtualNetworkManager manager; | 64 | private VirtualNetworkManager manager; |
63 | private DistributedVirtualNetworkStore virtualNetworkManagerStore; | 65 | private DistributedVirtualNetworkStore virtualNetworkManagerStore; |
64 | private CoreService coreService; | 66 | private CoreService coreService; |
67 | + private TestableIntentService intentService = new FakeIntentManager(); | ||
65 | 68 | ||
66 | @Before | 69 | @Before |
67 | public void setUp() throws Exception { | 70 | public void setUp() throws Exception { |
... | @@ -75,6 +78,7 @@ public class VirtualNetworkTopologyServiceTest extends TestDeviceParams { | ... | @@ -75,6 +78,7 @@ public class VirtualNetworkTopologyServiceTest extends TestDeviceParams { |
75 | 78 | ||
76 | manager = new VirtualNetworkManager(); | 79 | manager = new VirtualNetworkManager(); |
77 | manager.store = virtualNetworkManagerStore; | 80 | manager.store = virtualNetworkManagerStore; |
81 | + manager.intentService = intentService; | ||
78 | NetTestTools.injectEventDispatcher(manager, new TestEventDispatcher()); | 82 | NetTestTools.injectEventDispatcher(manager, new TestEventDispatcher()); |
79 | manager.activate(); | 83 | manager.activate(); |
80 | } | 84 | } | ... | ... |
... | @@ -42,6 +42,7 @@ import org.onosproject.incubator.net.virtual.VirtualHost; | ... | @@ -42,6 +42,7 @@ import org.onosproject.incubator.net.virtual.VirtualHost; |
42 | import org.onosproject.incubator.net.virtual.VirtualLink; | 42 | import org.onosproject.incubator.net.virtual.VirtualLink; |
43 | import org.onosproject.incubator.net.virtual.VirtualNetwork; | 43 | import org.onosproject.incubator.net.virtual.VirtualNetwork; |
44 | import org.onosproject.incubator.net.virtual.VirtualNetworkEvent; | 44 | import org.onosproject.incubator.net.virtual.VirtualNetworkEvent; |
45 | +import org.onosproject.incubator.net.virtual.VirtualNetworkIntent; | ||
45 | import org.onosproject.incubator.net.virtual.VirtualNetworkService; | 46 | import org.onosproject.incubator.net.virtual.VirtualNetworkService; |
46 | import org.onosproject.incubator.net.virtual.VirtualNetworkStore; | 47 | import org.onosproject.incubator.net.virtual.VirtualNetworkStore; |
47 | import org.onosproject.incubator.net.virtual.VirtualNetworkStoreDelegate; | 48 | import org.onosproject.incubator.net.virtual.VirtualNetworkStoreDelegate; |
... | @@ -54,6 +55,10 @@ import org.onosproject.net.HostLocation; | ... | @@ -54,6 +55,10 @@ import org.onosproject.net.HostLocation; |
54 | import org.onosproject.net.Link; | 55 | import org.onosproject.net.Link; |
55 | import org.onosproject.net.Port; | 56 | import org.onosproject.net.Port; |
56 | import org.onosproject.net.PortNumber; | 57 | import org.onosproject.net.PortNumber; |
58 | +import org.onosproject.net.intent.Intent; | ||
59 | +import org.onosproject.net.intent.IntentData; | ||
60 | +import org.onosproject.net.intent.IntentState; | ||
61 | +import org.onosproject.net.intent.Key; | ||
57 | import org.onosproject.store.AbstractStore; | 62 | import org.onosproject.store.AbstractStore; |
58 | import org.onosproject.store.serializers.KryoNamespaces; | 63 | import org.onosproject.store.serializers.KryoNamespaces; |
59 | import org.onosproject.store.service.ConsistentMap; | 64 | import org.onosproject.store.service.ConsistentMap; |
... | @@ -64,6 +69,7 @@ import org.onosproject.store.service.Serializer; | ... | @@ -64,6 +69,7 @@ import org.onosproject.store.service.Serializer; |
64 | import org.onosproject.store.service.SetEvent; | 69 | import org.onosproject.store.service.SetEvent; |
65 | import org.onosproject.store.service.SetEventListener; | 70 | import org.onosproject.store.service.SetEventListener; |
66 | import org.onosproject.store.service.StorageService; | 71 | import org.onosproject.store.service.StorageService; |
72 | +import org.onosproject.store.service.WallClockTimestamp; | ||
67 | import org.slf4j.Logger; | 73 | import org.slf4j.Logger; |
68 | 74 | ||
69 | import java.util.HashSet; | 75 | import java.util.HashSet; |
... | @@ -134,6 +140,14 @@ public class DistributedVirtualNetworkStore | ... | @@ -134,6 +140,14 @@ public class DistributedVirtualNetworkStore |
134 | private ConsistentMap<NetworkId, Set<VirtualPort>> networkIdVirtualPortSetConsistentMap; | 140 | private ConsistentMap<NetworkId, Set<VirtualPort>> networkIdVirtualPortSetConsistentMap; |
135 | private Map<NetworkId, Set<VirtualPort>> networkIdVirtualPortSetMap; | 141 | private Map<NetworkId, Set<VirtualPort>> networkIdVirtualPortSetMap; |
136 | 142 | ||
143 | + // Track intent key to intent data | ||
144 | + private ConsistentMap<Key, IntentData> intentKeyIntentDataConsistentMap; | ||
145 | + private Map<Key, IntentData> intentKeyIntentDataMap; | ||
146 | + | ||
147 | + // Track intent ID to TunnelIds | ||
148 | + private ConsistentMap<Key, Set<TunnelId>> intentKeyTunnelIdSetConsistentMap; | ||
149 | + private Map<Key, Set<TunnelId>> intentKeyTunnelIdSetMap; | ||
150 | + | ||
137 | private static final Serializer SERIALIZER = Serializer | 151 | private static final Serializer SERIALIZER = Serializer |
138 | .using(new KryoNamespace.Builder().register(KryoNamespaces.API) | 152 | .using(new KryoNamespace.Builder().register(KryoNamespaces.API) |
139 | .register(TenantId.class) | 153 | .register(TenantId.class) |
... | @@ -150,8 +164,11 @@ public class DistributedVirtualNetworkStore | ... | @@ -150,8 +164,11 @@ public class DistributedVirtualNetworkStore |
150 | .register(DefaultVirtualPort.class) | 164 | .register(DefaultVirtualPort.class) |
151 | .register(Device.class) | 165 | .register(Device.class) |
152 | .register(TunnelId.class) | 166 | .register(TunnelId.class) |
167 | + .register(IntentData.class) | ||
168 | + .register(VirtualNetworkIntent.class) | ||
169 | + .register(WallClockTimestamp.class) | ||
153 | .nextId(KryoNamespaces.BEGIN_USER_CUSTOM_ID) | 170 | .nextId(KryoNamespaces.BEGIN_USER_CUSTOM_ID) |
154 | - .build("VirtualNetworkStore")); | 171 | + .build()); |
155 | 172 | ||
156 | /** | 173 | /** |
157 | * Distributed network store service activate method. | 174 | * Distributed network store service activate method. |
... | @@ -220,11 +237,25 @@ public class DistributedVirtualNetworkStore | ... | @@ -220,11 +237,25 @@ public class DistributedVirtualNetworkStore |
220 | 237 | ||
221 | networkIdVirtualPortSetConsistentMap = storageService.<NetworkId, Set<VirtualPort>>consistentMapBuilder() | 238 | networkIdVirtualPortSetConsistentMap = storageService.<NetworkId, Set<VirtualPort>>consistentMapBuilder() |
222 | .withSerializer(SERIALIZER) | 239 | .withSerializer(SERIALIZER) |
223 | - .withName("onos-networkId-virtualportss") | 240 | + .withName("onos-networkId-virtualports") |
224 | .withRelaxedReadConsistency() | 241 | .withRelaxedReadConsistency() |
225 | .build(); | 242 | .build(); |
226 | networkIdVirtualPortSetMap = networkIdVirtualPortSetConsistentMap.asJavaMap(); | 243 | networkIdVirtualPortSetMap = networkIdVirtualPortSetConsistentMap.asJavaMap(); |
227 | 244 | ||
245 | + intentKeyTunnelIdSetConsistentMap = storageService.<Key, Set<TunnelId>>consistentMapBuilder() | ||
246 | + .withSerializer(SERIALIZER) | ||
247 | + .withName("onos-intentKey-tunnelIds") | ||
248 | + .withRelaxedReadConsistency() | ||
249 | + .build(); | ||
250 | + intentKeyTunnelIdSetMap = intentKeyTunnelIdSetConsistentMap.asJavaMap(); | ||
251 | + | ||
252 | + intentKeyIntentDataConsistentMap = storageService.<Key, IntentData>consistentMapBuilder() | ||
253 | + .withSerializer(SERIALIZER) | ||
254 | + .withName("onos-intentKey-intentData") | ||
255 | + .withRelaxedReadConsistency() | ||
256 | + .build(); | ||
257 | + intentKeyIntentDataMap = intentKeyIntentDataConsistentMap.asJavaMap(); | ||
258 | + | ||
228 | log.info("Started"); | 259 | log.info("Started"); |
229 | } | 260 | } |
230 | 261 | ||
... | @@ -607,6 +638,85 @@ public class DistributedVirtualNetworkStore | ... | @@ -607,6 +638,85 @@ public class DistributedVirtualNetworkStore |
607 | return ImmutableSet.copyOf(portSet); | 638 | return ImmutableSet.copyOf(portSet); |
608 | } | 639 | } |
609 | 640 | ||
641 | + @Override | ||
642 | + public synchronized void addOrUpdateIntent(Intent intent, IntentState state) { | ||
643 | + checkNotNull(intent, "Intent cannot be null"); | ||
644 | + IntentData intentData = removeIntent(intent.key()); | ||
645 | + if (intentData == null) { | ||
646 | + intentData = new IntentData(intent, state, new WallClockTimestamp(System.currentTimeMillis())); | ||
647 | + } else { | ||
648 | + intentData = new IntentData(intent, state, intentData.version()); | ||
649 | + } | ||
650 | + intentKeyIntentDataMap.put(intent.key(), intentData); | ||
651 | + } | ||
652 | + | ||
653 | + @Override | ||
654 | + public IntentData removeIntent(Key intentKey) { | ||
655 | + checkNotNull(intentKey, "Intent key cannot be null"); | ||
656 | + return intentKeyIntentDataMap.remove(intentKey); | ||
657 | + } | ||
658 | + | ||
659 | + @Override | ||
660 | + public void addTunnelId(Intent intent, TunnelId tunnelId) { | ||
661 | + // Add the tunnelId to the intent key set map | ||
662 | + Set<TunnelId> tunnelIdSet = intentKeyTunnelIdSetMap.remove(intent.key()); | ||
663 | + if (tunnelIdSet == null) { | ||
664 | + tunnelIdSet = new HashSet<>(); | ||
665 | + } | ||
666 | + tunnelIdSet.add(tunnelId); | ||
667 | + intentKeyTunnelIdSetMap.put(intent.key(), tunnelIdSet); | ||
668 | + } | ||
669 | + | ||
670 | + @Override | ||
671 | + public Set<TunnelId> getTunnelIds(Intent intent) { | ||
672 | + Set<TunnelId> tunnelIdSet = intentKeyTunnelIdSetMap.get(intent.key()); | ||
673 | + return tunnelIdSet == null ? new HashSet<TunnelId>() : ImmutableSet.copyOf(tunnelIdSet); | ||
674 | + } | ||
675 | + | ||
676 | + @Override | ||
677 | + public void removeTunnelId(Intent intent, TunnelId tunnelId) { | ||
678 | + Set<TunnelId> tunnelIdSet = new HashSet<>(); | ||
679 | + intentKeyTunnelIdSetMap.get(intent.key()).forEach(tunnelId1 -> { | ||
680 | + if (tunnelId1.equals(tunnelId)) { | ||
681 | + tunnelIdSet.add(tunnelId); | ||
682 | + } | ||
683 | + }); | ||
684 | + | ||
685 | + if (!tunnelIdSet.isEmpty()) { | ||
686 | + intentKeyTunnelIdSetMap.compute(intent.key(), (key, existingTunnelIds) -> { | ||
687 | + if (existingTunnelIds == null || existingTunnelIds.isEmpty()) { | ||
688 | + return new HashSet<>(); | ||
689 | + } else { | ||
690 | + return new HashSet<>(Sets.difference(existingTunnelIds, tunnelIdSet)); | ||
691 | + } | ||
692 | + }); | ||
693 | + } | ||
694 | + } | ||
695 | + | ||
696 | + @Override | ||
697 | + public Set<Intent> getIntents() { | ||
698 | + Set<Intent> intents = new HashSet<>(); | ||
699 | + intentKeyIntentDataMap.values().forEach(intentData -> intents.add(intentData.intent())); | ||
700 | + return ImmutableSet.copyOf(intents); | ||
701 | + } | ||
702 | + | ||
703 | + @Override | ||
704 | + public Intent getIntent(Key key) { | ||
705 | + IntentData intentData = intentKeyIntentDataMap.get(key); | ||
706 | + return intentData == null ? null : intentData.intent(); | ||
707 | + } | ||
708 | + | ||
709 | + @Override | ||
710 | + public Set<IntentData> getIntentData() { | ||
711 | + return ImmutableSet.copyOf(intentKeyIntentDataMap.values()); | ||
712 | + } | ||
713 | + | ||
714 | + @Override | ||
715 | + public IntentData getIntentData(Key key) { | ||
716 | + IntentData intentData = intentKeyIntentDataMap.get(key); | ||
717 | + return intentData == null ? null : new IntentData(intentData); | ||
718 | + } | ||
719 | + | ||
610 | /** | 720 | /** |
611 | * Listener class to map listener set events to the virtual network events. | 721 | * Listener class to map listener set events to the virtual network events. |
612 | */ | 722 | */ | ... | ... |
... | @@ -142,6 +142,12 @@ | ... | @@ -142,6 +142,12 @@ |
142 | 142 | ||
143 | <dependency> | 143 | <dependency> |
144 | <groupId>org.onosproject</groupId> | 144 | <groupId>org.onosproject</groupId> |
145 | + <artifactId>onos-incubator-net</artifactId> | ||
146 | + <version>${project.version}</version> | ||
147 | + </dependency> | ||
148 | + | ||
149 | + <dependency> | ||
150 | + <groupId>org.onosproject</groupId> | ||
145 | <artifactId>onos-core-common</artifactId> | 151 | <artifactId>onos-core-common</artifactId> |
146 | <version>${project.version}</version> | 152 | <version>${project.version}</version> |
147 | </dependency> | 153 | </dependency> | ... | ... |
-
Please register or login to post a comment