Committed by
Gerrit Code Review
ONOS-2184 - Initial implementation of Virtual network Intent service.
Change-Id: I03103b4eca797cd32480fbd0e3b4cf0385b50ef2
Showing
24 changed files
with
1543 additions
and
7 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 | +} |
This diff is collapsed. Click to expand it.
| ... | @@ -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 | } | ... | ... |
This diff is collapsed. Click to expand it.
| ... | @@ -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