Adding STC scenario for testing host intent-based connectivity.
Change-Id: I7375a9fdb121a6a288df5d54a23cfbd9d54258f3
Showing
4 changed files
with
120 additions
and
66 deletions
... | @@ -33,6 +33,7 @@ import java.util.Objects; | ... | @@ -33,6 +33,7 @@ import java.util.Objects; |
33 | import java.util.concurrent.CountDownLatch; | 33 | import java.util.concurrent.CountDownLatch; |
34 | import java.util.concurrent.TimeUnit; | 34 | import java.util.concurrent.TimeUnit; |
35 | 35 | ||
36 | +import static com.google.common.base.Strings.isNullOrEmpty; | ||
36 | import static org.onosproject.net.intent.IntentState.FAILED; | 37 | import static org.onosproject.net.intent.IntentState.FAILED; |
37 | import static org.onosproject.net.intent.IntentState.WITHDRAWN; | 38 | import static org.onosproject.net.intent.IntentState.WITHDRAWN; |
38 | 39 | ||
... | @@ -40,17 +41,17 @@ import static org.onosproject.net.intent.IntentState.WITHDRAWN; | ... | @@ -40,17 +41,17 @@ import static org.onosproject.net.intent.IntentState.WITHDRAWN; |
40 | * Removes an intent. | 41 | * Removes an intent. |
41 | */ | 42 | */ |
42 | @Command(scope = "onos", name = "remove-intent", | 43 | @Command(scope = "onos", name = "remove-intent", |
43 | - description = "Removes the specified intent") | 44 | + description = "Removes the specified intent") |
44 | public class IntentRemoveCommand extends AbstractShellCommand { | 45 | public class IntentRemoveCommand extends AbstractShellCommand { |
45 | 46 | ||
46 | @Argument(index = 0, name = "app", | 47 | @Argument(index = 0, name = "app", |
47 | - description = "Application ID", | 48 | + description = "Application ID", |
48 | - required = true, multiValued = false) | 49 | + required = false, multiValued = false) |
49 | String applicationIdString = null; | 50 | String applicationIdString = null; |
50 | 51 | ||
51 | @Argument(index = 1, name = "key", | 52 | @Argument(index = 1, name = "key", |
52 | - description = "Intent Key", | 53 | + description = "Intent Key", |
53 | - required = true, multiValued = false) | 54 | + required = false, multiValued = false) |
54 | String keyString = null; | 55 | String keyString = null; |
55 | 56 | ||
56 | @Option(name = "-p", aliases = "--purge", | 57 | @Option(name = "-p", aliases = "--purge", |
... | @@ -69,7 +70,7 @@ public class IntentRemoveCommand extends AbstractShellCommand { | ... | @@ -69,7 +70,7 @@ public class IntentRemoveCommand extends AbstractShellCommand { |
69 | CoreService coreService = get(CoreService.class); | 70 | CoreService coreService = get(CoreService.class); |
70 | 71 | ||
71 | ApplicationId appId = appId(); | 72 | ApplicationId appId = appId(); |
72 | - if (applicationIdString != null) { | 73 | + if (!isNullOrEmpty(applicationIdString)) { |
73 | appId = coreService.getAppId(applicationIdString); | 74 | appId = coreService.getAppId(applicationIdString); |
74 | if (appId == null) { | 75 | if (appId == null) { |
75 | print("Cannot find application Id %s", applicationIdString); | 76 | print("Cannot find application Id %s", applicationIdString); |
... | @@ -77,73 +78,87 @@ public class IntentRemoveCommand extends AbstractShellCommand { | ... | @@ -77,73 +78,87 @@ public class IntentRemoveCommand extends AbstractShellCommand { |
77 | } | 78 | } |
78 | } | 79 | } |
79 | 80 | ||
80 | - final Key key; | 81 | + if (isNullOrEmpty(keyString)) { |
81 | - if (keyString.startsWith("0x")) { | 82 | + for (Intent intent : intentService.getIntents()) { |
82 | - // The intent uses a LongKey | 83 | + if (intent.appId().equals(appId)) { |
83 | - keyString = keyString.replaceFirst("0x", ""); | 84 | + removeIntent(intentService, intent); |
84 | - key = Key.of(new BigInteger(keyString, 16).longValue(), appId); | 85 | + } |
85 | - } else { | 86 | + } |
86 | - // The intent uses a StringKey | ||
87 | - key = Key.of(keyString, appId); | ||
88 | - } | ||
89 | 87 | ||
90 | - Intent intent = intentService.getIntent(key); | 88 | + } else { |
91 | - if (intent != null) { | 89 | + final Key key; |
92 | - IntentListener listener = null; | 90 | + if (keyString.startsWith("0x")) { |
93 | - final CountDownLatch withdrawLatch, purgeLatch; | 91 | + // The intent uses a LongKey |
94 | - if (purgeAfterRemove || sync) { | 92 | + keyString = keyString.replaceFirst("0x", ""); |
95 | - // set up latch and listener to track uninstall progress | 93 | + key = Key.of(new BigInteger(keyString, 16).longValue(), appId); |
96 | - withdrawLatch = new CountDownLatch(1); | ||
97 | - purgeLatch = purgeAfterRemove ? new CountDownLatch(1) : null; | ||
98 | - listener = (IntentEvent event) -> { | ||
99 | - if (Objects.equals(event.subject().key(), key)) { | ||
100 | - if (event.type() == IntentEvent.Type.WITHDRAWN || | ||
101 | - event.type() == IntentEvent.Type.FAILED) { | ||
102 | - withdrawLatch.countDown(); | ||
103 | - } else if (purgeAfterRemove && | ||
104 | - event.type() == IntentEvent.Type.PURGED) { | ||
105 | - purgeLatch.countDown(); | ||
106 | - } | ||
107 | - } | ||
108 | - }; | ||
109 | - intentService.addListener(listener); | ||
110 | } else { | 94 | } else { |
111 | - purgeLatch = null; | 95 | + // The intent uses a StringKey |
112 | - withdrawLatch = null; | 96 | + key = Key.of(keyString, appId); |
113 | } | 97 | } |
114 | 98 | ||
115 | - // request the withdraw | 99 | + Intent intent = intentService.getIntent(key); |
116 | - intentService.withdraw(intent); | 100 | + if (intent != null) { |
101 | + removeIntent(intentService, intent); | ||
102 | + } | ||
103 | + } | ||
104 | + } | ||
117 | 105 | ||
118 | - if (purgeAfterRemove || sync) { | 106 | + private void removeIntent(IntentService intentService, Intent intent) { |
119 | - try { // wait for withdraw event | 107 | + IntentListener listener = null; |
120 | - withdrawLatch.await(5, TimeUnit.SECONDS); | 108 | + Key key = intent.key(); |
121 | - } catch (InterruptedException e) { | 109 | + final CountDownLatch withdrawLatch, purgeLatch; |
122 | - print("Timed out waiting for intent {} withdraw", key); | 110 | + if (purgeAfterRemove || sync) { |
123 | - } | 111 | + // set up latch and listener to track uninstall progress |
124 | - // double check the state | 112 | + withdrawLatch = new CountDownLatch(1); |
125 | - IntentState state = intentService.getIntentState(key); | 113 | + purgeLatch = purgeAfterRemove ? new CountDownLatch(1) : null; |
126 | - if (purgeAfterRemove && (state == WITHDRAWN || state == FAILED)) { | 114 | + listener = (IntentEvent event) -> { |
127 | - intentService.purge(intent); | 115 | + if (Objects.equals(event.subject().key(), key)) { |
116 | + if (event.type() == IntentEvent.Type.WITHDRAWN || | ||
117 | + event.type() == IntentEvent.Type.FAILED) { | ||
118 | + withdrawLatch.countDown(); | ||
119 | + } else if (purgeAfterRemove && | ||
120 | + event.type() == IntentEvent.Type.PURGED) { | ||
121 | + purgeLatch.countDown(); | ||
122 | + } | ||
128 | } | 123 | } |
129 | - if (sync) { // wait for purge event | 124 | + }; |
125 | + intentService.addListener(listener); | ||
126 | + } else { | ||
127 | + purgeLatch = null; | ||
128 | + withdrawLatch = null; | ||
129 | + } | ||
130 | + | ||
131 | + // request the withdraw | ||
132 | + intentService.withdraw(intent); | ||
133 | + | ||
134 | + if (purgeAfterRemove || sync) { | ||
135 | + try { // wait for withdraw event | ||
136 | + withdrawLatch.await(5, TimeUnit.SECONDS); | ||
137 | + } catch (InterruptedException e) { | ||
138 | + print("Timed out waiting for intent {} withdraw", key); | ||
139 | + } | ||
140 | + // double check the state | ||
141 | + IntentState state = intentService.getIntentState(key); | ||
142 | + if (purgeAfterRemove && (state == WITHDRAWN || state == FAILED)) { | ||
143 | + intentService.purge(intent); | ||
144 | + } | ||
145 | + if (sync) { // wait for purge event | ||
130 | /* TODO | 146 | /* TODO |
131 | Technically, the event comes before map.remove() is called. | 147 | Technically, the event comes before map.remove() is called. |
132 | If we depend on sync and purge working together, we will | 148 | If we depend on sync and purge working together, we will |
133 | need to address this. | 149 | need to address this. |
134 | */ | 150 | */ |
135 | - try { | 151 | + try { |
136 | - purgeLatch.await(5, TimeUnit.SECONDS); | 152 | + purgeLatch.await(5, TimeUnit.SECONDS); |
137 | - } catch (InterruptedException e) { | 153 | + } catch (InterruptedException e) { |
138 | - print("Timed out waiting for intent {} purge", key); | 154 | + print("Timed out waiting for intent {} purge", key); |
139 | - } | ||
140 | } | 155 | } |
141 | } | 156 | } |
157 | + } | ||
142 | 158 | ||
143 | - if (listener != null) { | 159 | + if (listener != null) { |
144 | - // clean up the listener | 160 | + // clean up the listener |
145 | - intentService.removeListener(listener); | 161 | + intentService.removeListener(listener); |
146 | - } | ||
147 | } | 162 | } |
148 | } | 163 | } |
149 | } | 164 | } | ... | ... |
tools/test/scenarios/net-host-intent.xml
0 → 100644
1 | +<!-- | ||
2 | + ~ Copyright 2015 Open Networking Laboratory | ||
3 | + ~ | ||
4 | + ~ Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + ~ you may not use this file except in compliance with the License. | ||
6 | + ~ You may obtain a copy of the License at | ||
7 | + ~ | ||
8 | + ~ http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + ~ | ||
10 | + ~ Unless required by applicable law or agreed to in writing, software | ||
11 | + ~ distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + ~ See the License for the specific language governing permissions and | ||
14 | + ~ limitations under the License. | ||
15 | + --> | ||
16 | +<scenario name="net-host-intent" description="Network host intent connectivity test"> | ||
17 | + <!-- TODO: parametrize this via recipes --> | ||
18 | + <group name="Host-Intent-Connectivity"> | ||
19 | + <step name="Uninstall-Reactive-Forwarding" | ||
20 | + exec="onos ${OC1} app deactivate org.onosproject.fwd org.onosproject.ifwd"/> | ||
21 | + | ||
22 | + <step name="Find-Host-1" requires="^" | ||
23 | + exec="onos-mininet sendAndExpect h1 ping -c1 h4 --expect ."/> | ||
24 | + <step name="Find-Host-2" requires="^" | ||
25 | + exec="onos-mininet sendAndExpect h4 ping -c1 h1 --expect ."/> | ||
26 | + | ||
27 | + <step name="Create-Intent" requires="^" | ||
28 | + exec="onos ${OCI} add-host-intent 00:00:00:00:00:01/-1 00:00:00:00:00:04/-1"/> | ||
29 | + | ||
30 | + <import file="${ONOS_SCENARIOS}/net-link-down-up.xml" namespace="Host-Intent"/> | ||
31 | + <dependency name="Host-Intent.Net-Link-Down-Up" requires="Create-Intent"/> | ||
32 | + | ||
33 | + <step name="Remove-Intent" requires="Host-Intent.Net-Link-Down-Up" | ||
34 | + exec="onos ${OCI} remove-intent --purge"/> | ||
35 | + </group> | ||
36 | +</scenario> | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
... | @@ -13,9 +13,9 @@ | ... | @@ -13,9 +13,9 @@ |
13 | ~ See the License for the specific language governing permissions and | 13 | ~ See the License for the specific language governing permissions and |
14 | ~ limitations under the License. | 14 | ~ limitations under the License. |
15 | --> | 15 | --> |
16 | -<scenario name="net-link-up-down" description="Network link up-down test"> | 16 | +<scenario name="net-link-down-up" description="Network link up-down test"> |
17 | <!-- TODO: parametrize this via recipes --> | 17 | <!-- TODO: parametrize this via recipes --> |
18 | - <group name="Net-Link-Up-Down"> | 18 | + <group name="Net-Link-Down-Up"> |
19 | <step name="Ping-1" | 19 | <step name="Ping-1" |
20 | exec="onos-mininet sendAndExpect h1 ping -c1 h4 --expect \ 0% packet loss"/> | 20 | exec="onos-mininet sendAndExpect h1 ping -c1 h4 --expect \ 0% packet loss"/> |
21 | <step name="Link-1-Down" requires="Ping-1" | 21 | <step name="Link-1-Down" requires="Ping-1" | ... | ... |
... | @@ -17,13 +17,16 @@ | ... | @@ -17,13 +17,16 @@ |
17 | <group name="Net-Smoke"> | 17 | <group name="Net-Smoke"> |
18 | <import file="${ONOS_SCENARIOS}/net-setup.xml"/> | 18 | <import file="${ONOS_SCENARIOS}/net-setup.xml"/> |
19 | 19 | ||
20 | - <import file="${ONOS_SCENARIOS}/net-pingall.xml"/> | 20 | + <import file="${ONOS_SCENARIOS}/net-pingall.xml" namespace="Reactive-Forwarding"/> |
21 | - <dependency name="Net-Pingall" requires="Net-Setup"/> | 21 | + <dependency name="Reactive-Forwarding.Net-Pingall" requires="Net-Setup"/> |
22 | 22 | ||
23 | - <import file="${ONOS_SCENARIOS}/net-link-up-down.xml"/> | 23 | + <import file="${ONOS_SCENARIOS}/net-link-down-up.xml" namespace="Reactive-Forwarding"/> |
24 | - <dependency name="Net-Link-Up-Down" requires="~Net-Pingall"/> | 24 | + <dependency name="Reactive-Forwarding.Net-Link-Down-Up" requires="~Reactive-Forwarding.Net-Pingall"/> |
25 | + | ||
26 | + <import file="${ONOS_SCENARIOS}/net-host-intent.xml"/> | ||
27 | + <dependency name="Host-Intent-Connectivity" requires="~Reactive-Forwarding.Net-Link-Down-Up"/> | ||
25 | 28 | ||
26 | <import file="${ONOS_SCENARIOS}/net-teardown.xml"/> | 29 | <import file="${ONOS_SCENARIOS}/net-teardown.xml"/> |
27 | - <dependency name="Net-Teardown" requires="~Net-Link-Up-Down"/> | 30 | + <dependency name="Net-Teardown" requires="~Host-Intent-Connectivity"/> |
28 | </group> | 31 | </group> |
29 | </scenario> | 32 | </scenario> |
... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
-
Please register or login to post a comment