Committed by
Ray Milkey
ONOS-785 Adding distributed store for apps & app admin CLIs
Change-Id: Ia7639f3258fca2a18ba513f0c95de0ab8ea7ceee
Showing
16 changed files
with
386 additions
and
32 deletions
1 | +/* | ||
2 | + * Copyright 2015 Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.onosproject.cli.app; | ||
17 | + | ||
18 | +import org.apache.karaf.shell.commands.Argument; | ||
19 | +import org.apache.karaf.shell.commands.Command; | ||
20 | +import org.onosproject.app.ApplicationAdminService; | ||
21 | +import org.onosproject.cli.AbstractShellCommand; | ||
22 | +import org.onosproject.core.ApplicationId; | ||
23 | + | ||
24 | +/** | ||
25 | + * Activates an installed application. | ||
26 | + */ | ||
27 | +@Command(scope = "onos", name = "app-activate", | ||
28 | + description = "Activates an installed application") | ||
29 | +public class ApplicationActivateCommand extends AbstractShellCommand { | ||
30 | + | ||
31 | + @Argument(index = 0, name = "name", description = "Application name", | ||
32 | + required = true, multiValued = false) | ||
33 | + String name = null; | ||
34 | + | ||
35 | + @Override | ||
36 | + protected void execute() { | ||
37 | + ApplicationAdminService service = get(ApplicationAdminService.class); | ||
38 | + ApplicationId appId = service.getId(name); | ||
39 | + if (appId != null) { | ||
40 | + service.activate(appId); | ||
41 | + } else { | ||
42 | + print("No such application: %s", name); | ||
43 | + } | ||
44 | + } | ||
45 | + | ||
46 | +} |
1 | +/* | ||
2 | + * Copyright 2015 Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.onosproject.cli.app; | ||
17 | + | ||
18 | +import org.apache.karaf.shell.commands.Argument; | ||
19 | +import org.apache.karaf.shell.commands.Command; | ||
20 | +import org.onosproject.app.ApplicationAdminService; | ||
21 | +import org.onosproject.cli.AbstractShellCommand; | ||
22 | +import org.onosproject.core.ApplicationId; | ||
23 | + | ||
24 | +/** | ||
25 | + * Deactivates an installed application. | ||
26 | + */ | ||
27 | +@Command(scope = "onos", name = "app-deactivate", | ||
28 | + description = "Deactivates an installed application") | ||
29 | +public class ApplicationDeactivateCommand extends AbstractShellCommand { | ||
30 | + | ||
31 | + @Argument(index = 0, name = "name", description = "Application name", | ||
32 | + required = true, multiValued = false) | ||
33 | + String name = null; | ||
34 | + | ||
35 | + @Override | ||
36 | + protected void execute() { | ||
37 | + ApplicationAdminService service = get(ApplicationAdminService.class); | ||
38 | + ApplicationId appId = service.getId(name); | ||
39 | + if (appId != null) { | ||
40 | + service.deactivate(appId); | ||
41 | + } else { | ||
42 | + print("No such application: %s", name); | ||
43 | + } | ||
44 | + } | ||
45 | + | ||
46 | +} |
... | @@ -13,12 +13,14 @@ | ... | @@ -13,12 +13,14 @@ |
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 | -package org.onosproject.cli; | 16 | +package org.onosproject.cli.app; |
17 | 17 | ||
18 | import com.fasterxml.jackson.databind.JsonNode; | 18 | import com.fasterxml.jackson.databind.JsonNode; |
19 | import com.fasterxml.jackson.databind.ObjectMapper; | 19 | import com.fasterxml.jackson.databind.ObjectMapper; |
20 | import com.fasterxml.jackson.databind.node.ArrayNode; | 20 | import com.fasterxml.jackson.databind.node.ArrayNode; |
21 | import org.apache.karaf.shell.commands.Command; | 21 | import org.apache.karaf.shell.commands.Command; |
22 | +import org.onosproject.cli.AbstractShellCommand; | ||
23 | +import org.onosproject.cli.Comparators; | ||
22 | import org.onosproject.core.ApplicationId; | 24 | import org.onosproject.core.ApplicationId; |
23 | import org.onosproject.core.CoreService; | 25 | import org.onosproject.core.CoreService; |
24 | 26 | ||
... | @@ -30,7 +32,7 @@ import static com.google.common.collect.Lists.newArrayList; | ... | @@ -30,7 +32,7 @@ import static com.google.common.collect.Lists.newArrayList; |
30 | /** | 32 | /** |
31 | * Lists application ID information. | 33 | * Lists application ID information. |
32 | */ | 34 | */ |
33 | -@Command(scope = "onos", name = "apps", | 35 | +@Command(scope = "onos", name = "app-ids", |
34 | description = "Lists application ID information") | 36 | description = "Lists application ID information") |
35 | public class ApplicationIdListCommand extends AbstractShellCommand { | 37 | public class ApplicationIdListCommand extends AbstractShellCommand { |
36 | 38 | ... | ... |
1 | +/* | ||
2 | + * Copyright 2015 Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.onosproject.cli.app; | ||
17 | + | ||
18 | +import org.apache.karaf.shell.console.Completer; | ||
19 | +import org.apache.karaf.shell.console.completer.StringsCompleter; | ||
20 | +import org.onosproject.app.ApplicationService; | ||
21 | +import org.onosproject.cli.AbstractShellCommand; | ||
22 | +import org.onosproject.core.Application; | ||
23 | + | ||
24 | +import java.util.Iterator; | ||
25 | +import java.util.List; | ||
26 | +import java.util.SortedSet; | ||
27 | + | ||
28 | +/** | ||
29 | + * Application name completer. | ||
30 | + */ | ||
31 | +public class ApplicationNameCompleter implements Completer { | ||
32 | + @Override | ||
33 | + public int complete(String buffer, int cursor, List<String> candidates) { | ||
34 | + // Delegate string completer | ||
35 | + StringsCompleter delegate = new StringsCompleter(); | ||
36 | + | ||
37 | + // Fetch our service and feed it's offerings to the string completer | ||
38 | + ApplicationService service = AbstractShellCommand.get(ApplicationService.class); | ||
39 | + Iterator<Application> it = service.getApplications().iterator(); | ||
40 | + SortedSet<String> strings = delegate.getStrings(); | ||
41 | + while (it.hasNext()) { | ||
42 | + strings.add(it.next().id().name()); | ||
43 | + } | ||
44 | + | ||
45 | + // Now let the completer do the work for figuring out what to offer. | ||
46 | + return delegate.complete(buffer, cursor, candidates); | ||
47 | + } | ||
48 | + | ||
49 | +} |
1 | +/* | ||
2 | + * Copyright 2015 Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.onosproject.cli.app; | ||
17 | + | ||
18 | +import org.apache.karaf.shell.commands.Argument; | ||
19 | +import org.apache.karaf.shell.commands.Command; | ||
20 | +import org.onosproject.app.ApplicationAdminService; | ||
21 | +import org.onosproject.cli.AbstractShellCommand; | ||
22 | +import org.onosproject.core.ApplicationId; | ||
23 | + | ||
24 | +/** | ||
25 | + * Uninstalls an application. | ||
26 | + */ | ||
27 | +@Command(scope = "onos", name = "app-uninstall", | ||
28 | + description = "Uninstalls an application") | ||
29 | +public class ApplicationUninstallCommand extends AbstractShellCommand { | ||
30 | + | ||
31 | + @Argument(index = 0, name = "name", description = "Application name", | ||
32 | + required = true, multiValued = false) | ||
33 | + String name = null; | ||
34 | + | ||
35 | + @Override | ||
36 | + protected void execute() { | ||
37 | + ApplicationAdminService service = get(ApplicationAdminService.class); | ||
38 | + ApplicationId appId = service.getId(name); | ||
39 | + if (appId != null) { | ||
40 | + service.uninstall(appId); | ||
41 | + } else { | ||
42 | + print("No such application: %s", name); | ||
43 | + } | ||
44 | + } | ||
45 | + | ||
46 | +} |
... | @@ -13,32 +13,33 @@ | ... | @@ -13,32 +13,33 @@ |
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 | -package org.onosproject.cli; | 16 | +package org.onosproject.cli.app; |
17 | 17 | ||
18 | import org.apache.karaf.shell.commands.Command; | 18 | import org.apache.karaf.shell.commands.Command; |
19 | +import org.onosproject.app.ApplicationService; | ||
20 | +import org.onosproject.cli.AbstractShellCommand; | ||
21 | +import org.onosproject.core.Application; | ||
19 | 22 | ||
20 | -import java.io.BufferedReader; | 23 | +import static org.onosproject.app.ApplicationState.ACTIVE; |
21 | -import java.io.IOException; | ||
22 | -import java.io.InputStreamReader; | ||
23 | 24 | ||
24 | /** | 25 | /** |
25 | - * Lists application ID information. | 26 | + * Lists application information. |
26 | */ | 27 | */ |
27 | -@Command(scope = "onos", name = "app-install", | 28 | +@Command(scope = "onos", name = "apps", |
28 | - description = "Lists application ID information") | 29 | + description = "Lists application information") |
29 | -public class ApplicationInstallCommand extends AbstractShellCommand { | 30 | +public class ApplicationsListCommand extends AbstractShellCommand { |
31 | + | ||
32 | + private static final String FMT = | ||
33 | + "%s id=%d, name=%s, version=%s, origin=%s, description=%s, " + | ||
34 | + "features=%s, featuresRepo=%s, permissions=%s"; | ||
30 | 35 | ||
31 | @Override | 36 | @Override |
32 | protected void execute() { | 37 | protected void execute() { |
33 | - // FIXME: merely an experiment for now | 38 | + ApplicationService service = get(ApplicationService.class); |
34 | - try (InputStreamReader isr = new InputStreamReader(System.in); | 39 | + for (Application app : service.getApplications()) { |
35 | - BufferedReader br = new BufferedReader(isr)) { | 40 | + print(FMT, service.getState(app.id()) == ACTIVE ? "*" : " ", |
36 | - String line; | 41 | + app.id().id(), app.id().name(), app.version(), app.origin(), |
37 | - while ((line = br.readLine()) != null) { | 42 | + app.description(), app.features(), app.featuresRepo(), app.permissions()); |
38 | - print("%s", line.toUpperCase()); | ||
39 | - } | ||
40 | - } catch (IOException e) { | ||
41 | - e.printStackTrace(); | ||
42 | } | 43 | } |
43 | } | 44 | } |
44 | 45 | ... | ... |
... | @@ -21,7 +21,31 @@ | ... | @@ -21,7 +21,31 @@ |
21 | </command> | 21 | </command> |
22 | 22 | ||
23 | <command> | 23 | <command> |
24 | - <action class="org.onosproject.cli.ApplicationInstallCommand"/> | 24 | + <action class="org.onosproject.cli.app.ApplicationsListCommand"/> |
25 | + </command> | ||
26 | + | ||
27 | + <command> | ||
28 | + <action class="org.onosproject.cli.app.ApplicationActivateCommand"/> | ||
29 | + <completers> | ||
30 | + <ref component-id="appNameCompleter"/> | ||
31 | + <null/> | ||
32 | + </completers> | ||
33 | + </command> | ||
34 | + | ||
35 | + <command> | ||
36 | + <action class="org.onosproject.cli.app.ApplicationDeactivateCommand"/> | ||
37 | + <completers> | ||
38 | + <ref component-id="appNameCompleter"/> | ||
39 | + <null/> | ||
40 | + </completers> | ||
41 | + </command> | ||
42 | + | ||
43 | + <command> | ||
44 | + <action class="org.onosproject.cli.app.ApplicationUninstallCommand"/> | ||
45 | + <completers> | ||
46 | + <ref component-id="appNameCompleter"/> | ||
47 | + <null/> | ||
48 | + </completers> | ||
25 | </command> | 49 | </command> |
26 | 50 | ||
27 | <command> | 51 | <command> |
... | @@ -77,7 +101,7 @@ | ... | @@ -77,7 +101,7 @@ |
77 | <action class="org.onosproject.cli.BalanceMastersCommand"/> | 101 | <action class="org.onosproject.cli.BalanceMastersCommand"/> |
78 | </command> | 102 | </command> |
79 | <command> | 103 | <command> |
80 | - <action class="org.onosproject.cli.ApplicationIdListCommand"/> | 104 | + <action class="org.onosproject.cli.app.ApplicationIdListCommand"/> |
81 | </command> | 105 | </command> |
82 | 106 | ||
83 | <command> | 107 | <command> |
... | @@ -275,6 +299,7 @@ | ... | @@ -275,6 +299,7 @@ |
275 | </command> | 299 | </command> |
276 | </command-bundle> | 300 | </command-bundle> |
277 | 301 | ||
302 | + <bean id="appNameCompleter" class="org.onosproject.cli.app.ApplicationNameCompleter"/> | ||
278 | <bean id="nodeIdCompleter" class="org.onosproject.cli.NodeIdCompleter"/> | 303 | <bean id="nodeIdCompleter" class="org.onosproject.cli.NodeIdCompleter"/> |
279 | <bean id="deviceIdCompleter" class="org.onosproject.cli.net.DeviceIdCompleter"/> | 304 | <bean id="deviceIdCompleter" class="org.onosproject.cli.net.DeviceIdCompleter"/> |
280 | <bean id="clusterIdCompleter" class="org.onosproject.cli.net.ClusterIdCompleter"/> | 305 | <bean id="clusterIdCompleter" class="org.onosproject.cli.net.ClusterIdCompleter"/> | ... | ... |
... | @@ -39,6 +39,7 @@ import java.io.FileNotFoundException; | ... | @@ -39,6 +39,7 @@ import java.io.FileNotFoundException; |
39 | import java.io.IOException; | 39 | import java.io.IOException; |
40 | import java.io.InputStream; | 40 | import java.io.InputStream; |
41 | import java.net.URI; | 41 | import java.net.URI; |
42 | +import java.nio.file.NoSuchFileException; | ||
42 | import java.util.Set; | 43 | import java.util.Set; |
43 | import java.util.zip.ZipEntry; | 44 | import java.util.zip.ZipEntry; |
44 | import java.util.zip.ZipInputStream; | 45 | import java.util.zip.ZipInputStream; |
... | @@ -63,17 +64,25 @@ public class ApplicationArchive | ... | @@ -63,17 +64,25 @@ public class ApplicationArchive |
63 | 64 | ||
64 | private static Logger log = LoggerFactory.getLogger(ApplicationArchive.class); | 65 | private static Logger log = LoggerFactory.getLogger(ApplicationArchive.class); |
65 | private static final String APP_XML = "app.xml"; | 66 | private static final String APP_XML = "app.xml"; |
67 | + private static final String M2_PREFIX = "m2"; | ||
68 | + | ||
69 | + private static final String KARAF_ROOT = "."; | ||
70 | + private static final String M2_ROOT = "system/"; | ||
66 | private static final String APPS_ROOT = "data/apps/"; | 71 | private static final String APPS_ROOT = "data/apps/"; |
67 | 72 | ||
68 | - private File appsDir = new File(APPS_ROOT); | 73 | + private File karafRoot = new File(KARAF_ROOT); |
74 | + private File m2Dir = new File(karafRoot, M2_ROOT); | ||
75 | + private File appsDir = new File(karafRoot, APPS_ROOT); | ||
69 | 76 | ||
70 | /** | 77 | /** |
71 | * Sets the root directory where application artifacts are kept. | 78 | * Sets the root directory where application artifacts are kept. |
72 | * | 79 | * |
73 | * @param appsRoot top-level applications directory path | 80 | * @param appsRoot top-level applications directory path |
74 | */ | 81 | */ |
75 | - protected void setAppsRoot(String appsRoot) { | 82 | + protected void setRootPath(String appsRoot) { |
76 | - this.appsDir = new File(appsRoot); | 83 | + this.karafRoot = new File(appsRoot); |
84 | + this.appsDir = new File(karafRoot, APPS_ROOT); | ||
85 | + this.m2Dir = new File(karafRoot, M2_ROOT); | ||
77 | } | 86 | } |
78 | 87 | ||
79 | /** | 88 | /** |
... | @@ -81,8 +90,8 @@ public class ApplicationArchive | ... | @@ -81,8 +90,8 @@ public class ApplicationArchive |
81 | * | 90 | * |
82 | * @return top-level applications directory path | 91 | * @return top-level applications directory path |
83 | */ | 92 | */ |
84 | - protected String getAppsRoot() { | 93 | + protected String getRootPath() { |
85 | - return appsDir.getPath(); | 94 | + return karafRoot.getPath(); |
86 | } | 95 | } |
87 | 96 | ||
88 | /** | 97 | /** |
... | @@ -238,10 +247,20 @@ public class ApplicationArchive | ... | @@ -238,10 +247,20 @@ public class ApplicationArchive |
238 | } | 247 | } |
239 | 248 | ||
240 | // Installs application artifacts into M2 repository. | 249 | // Installs application artifacts into M2 repository. |
241 | - private void installArtifacts(ApplicationDescription desc) { | 250 | + private void installArtifacts(ApplicationDescription desc) throws IOException { |
242 | - // FIXME: implement M2 repository copy | 251 | + try { |
252 | + Tools.copyDirectory(appFile(desc.name(), M2_PREFIX), m2Dir); | ||
253 | + } catch (NoSuchFileException e) { | ||
254 | + log.debug("Application {} has no M2 artifacts", desc.name()); | ||
255 | + } | ||
243 | } | 256 | } |
244 | 257 | ||
258 | + /** | ||
259 | + * Marks the app as active by creating token file in the app directory. | ||
260 | + * | ||
261 | + * @param appName application name | ||
262 | + * @return true if file was created | ||
263 | + */ | ||
245 | protected boolean setActive(String appName) { | 264 | protected boolean setActive(String appName) { |
246 | try { | 265 | try { |
247 | return appFile(appName, "active").createNewFile(); | 266 | return appFile(appName, "active").createNewFile(); |
... | @@ -250,10 +269,22 @@ public class ApplicationArchive | ... | @@ -250,10 +269,22 @@ public class ApplicationArchive |
250 | } | 269 | } |
251 | } | 270 | } |
252 | 271 | ||
272 | + /** | ||
273 | + * Clears the app as active by deleting token file in the app directory. | ||
274 | + * | ||
275 | + * @param appName application name | ||
276 | + * @return true if file was deleted | ||
277 | + */ | ||
253 | protected boolean clearActive(String appName) { | 278 | protected boolean clearActive(String appName) { |
254 | return appFile(appName, "active").delete(); | 279 | return appFile(appName, "active").delete(); |
255 | } | 280 | } |
256 | 281 | ||
282 | + /** | ||
283 | + * Indicates whether the app was marked as active by checking for token file. | ||
284 | + * | ||
285 | + * @param appName application name | ||
286 | + * @return true if the app is marked as active | ||
287 | + */ | ||
257 | protected boolean isActive(String appName) { | 288 | protected boolean isActive(String appName) { |
258 | return appFile(appName, "active").exists(); | 289 | return appFile(appName, "active").exists(); |
259 | } | 290 | } | ... | ... |
... | @@ -17,13 +17,17 @@ package org.onosproject.common.app; | ... | @@ -17,13 +17,17 @@ package org.onosproject.common.app; |
17 | 17 | ||
18 | import com.google.common.collect.ImmutableSet; | 18 | import com.google.common.collect.ImmutableSet; |
19 | import com.google.common.io.ByteStreams; | 19 | import com.google.common.io.ByteStreams; |
20 | +import org.junit.After; | ||
20 | import org.junit.Before; | 21 | import org.junit.Before; |
21 | import org.junit.Test; | 22 | import org.junit.Test; |
23 | +import org.onlab.util.Tools; | ||
22 | import org.onosproject.app.ApplicationDescription; | 24 | import org.onosproject.app.ApplicationDescription; |
23 | import org.onosproject.app.ApplicationException; | 25 | import org.onosproject.app.ApplicationException; |
24 | 26 | ||
27 | +import java.io.File; | ||
25 | import java.io.IOException; | 28 | import java.io.IOException; |
26 | import java.io.InputStream; | 29 | import java.io.InputStream; |
30 | +import java.util.Random; | ||
27 | import java.util.Set; | 31 | import java.util.Set; |
28 | 32 | ||
29 | import static org.junit.Assert.assertArrayEquals; | 33 | import static org.junit.Assert.assertArrayEquals; |
... | @@ -32,13 +36,20 @@ import static org.onosproject.app.DefaultApplicationDescriptionTest.*; | ... | @@ -32,13 +36,20 @@ import static org.onosproject.app.DefaultApplicationDescriptionTest.*; |
32 | 36 | ||
33 | public class ApplicationArchiveTest { | 37 | public class ApplicationArchiveTest { |
34 | 38 | ||
35 | - static final String ROOT = "/tmp/app-junit"; | 39 | + static final String ROOT = "/tmp/app-junit/" + new Random().nextInt(); |
36 | 40 | ||
37 | private ApplicationArchive aar = new ApplicationArchive(); | 41 | private ApplicationArchive aar = new ApplicationArchive(); |
38 | 42 | ||
39 | @Before | 43 | @Before |
40 | public void setUp() { | 44 | public void setUp() { |
41 | - aar.setAppsRoot(ROOT); | 45 | + aar.setRootPath(ROOT); |
46 | + } | ||
47 | + | ||
48 | + @After | ||
49 | + public void tearDown() throws IOException { | ||
50 | + if (new File(aar.getRootPath()).exists()) { | ||
51 | + Tools.removeDirectory(aar.getRootPath()); | ||
52 | + } | ||
42 | } | 53 | } |
43 | 54 | ||
44 | private void validate(ApplicationDescription app) { | 55 | private void validate(ApplicationDescription app) { |
... | @@ -77,7 +88,8 @@ public class ApplicationArchiveTest { | ... | @@ -77,7 +88,8 @@ public class ApplicationArchiveTest { |
77 | public void purgeApp() throws IOException { | 88 | public void purgeApp() throws IOException { |
78 | saveApp(); | 89 | saveApp(); |
79 | aar.purgeApplication(APP_NAME); | 90 | aar.purgeApplication(APP_NAME); |
80 | - assertEquals("incorrect names", ImmutableSet.of(), aar.getApplicationNames()); | 91 | + assertEquals("incorrect names", ImmutableSet.<String>of(), |
92 | + aar.getApplicationNames()); | ||
81 | } | 93 | } |
82 | 94 | ||
83 | @Test | 95 | @Test | ... | ... |
... | @@ -21,6 +21,7 @@ import org.apache.felix.scr.annotations.Deactivate; | ... | @@ -21,6 +21,7 @@ import org.apache.felix.scr.annotations.Deactivate; |
21 | import org.apache.felix.scr.annotations.Reference; | 21 | import org.apache.felix.scr.annotations.Reference; |
22 | import org.apache.felix.scr.annotations.ReferenceCardinality; | 22 | import org.apache.felix.scr.annotations.ReferenceCardinality; |
23 | import org.apache.felix.scr.annotations.Service; | 23 | import org.apache.felix.scr.annotations.Service; |
24 | +import org.apache.karaf.features.Feature; | ||
24 | import org.apache.karaf.features.FeaturesService; | 25 | import org.apache.karaf.features.FeaturesService; |
25 | import org.onosproject.app.ApplicationAdminService; | 26 | import org.onosproject.app.ApplicationAdminService; |
26 | import org.onosproject.app.ApplicationEvent; | 27 | import org.onosproject.app.ApplicationEvent; |
... | @@ -202,14 +203,20 @@ public class ApplicationManager implements ApplicationService, ApplicationAdminS | ... | @@ -202,14 +203,20 @@ public class ApplicationManager implements ApplicationService, ApplicationAdminS |
202 | 203 | ||
203 | private void installAppFeatures(Application app) throws Exception { | 204 | private void installAppFeatures(Application app) throws Exception { |
204 | for (String name : app.features()) { | 205 | for (String name : app.features()) { |
206 | + Feature feature = featuresService.getFeature(name); | ||
207 | + if (!featuresService.isInstalled(feature)) { | ||
205 | featuresService.installFeature(name); | 208 | featuresService.installFeature(name); |
206 | } | 209 | } |
207 | } | 210 | } |
211 | + } | ||
208 | 212 | ||
209 | private void uninstallAppFeatures(Application app) throws Exception { | 213 | private void uninstallAppFeatures(Application app) throws Exception { |
210 | for (String name : app.features()) { | 214 | for (String name : app.features()) { |
215 | + Feature feature = featuresService.getFeature(name); | ||
216 | + if (featuresService.isInstalled(feature)) { | ||
211 | featuresService.uninstallFeature(name); | 217 | featuresService.uninstallFeature(name); |
212 | } | 218 | } |
213 | } | 219 | } |
220 | + } | ||
214 | 221 | ||
215 | } | 222 | } | ... | ... |
... | @@ -43,6 +43,11 @@ | ... | @@ -43,6 +43,11 @@ |
43 | <artifactId>onlab-netty</artifactId> | 43 | <artifactId>onlab-netty</artifactId> |
44 | <version>${project.version}</version> | 44 | <version>${project.version}</version> |
45 | </dependency> | 45 | </dependency> |
46 | + | ||
47 | + <dependency> | ||
48 | + <groupId>org.onosproject</groupId> | ||
49 | + <artifactId>onos-core-common</artifactId> | ||
50 | + </dependency> | ||
46 | <!-- | 51 | <!-- |
47 | <dependency> | 52 | <dependency> |
48 | <groupId>net.kuujo.copycat</groupId> | 53 | <groupId>net.kuujo.copycat</groupId> | ... | ... |
This diff is collapsed. Click to expand it.
1 | +/* | ||
2 | + * Copyright 2015 Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | + | ||
17 | +/** | ||
18 | + * Implementation of distributed applications store. | ||
19 | + */ | ||
20 | +package org.onosproject.store.app; |
... | @@ -28,14 +28,17 @@ import org.onlab.packet.IpPrefix; | ... | @@ -28,14 +28,17 @@ import org.onlab.packet.IpPrefix; |
28 | import org.onlab.packet.MacAddress; | 28 | import org.onlab.packet.MacAddress; |
29 | import org.onlab.packet.VlanId; | 29 | import org.onlab.packet.VlanId; |
30 | import org.onlab.util.KryoNamespace; | 30 | import org.onlab.util.KryoNamespace; |
31 | +import org.onosproject.app.ApplicationState; | ||
31 | import org.onosproject.cluster.ControllerNode; | 32 | import org.onosproject.cluster.ControllerNode; |
32 | import org.onosproject.cluster.DefaultControllerNode; | 33 | import org.onosproject.cluster.DefaultControllerNode; |
33 | import org.onosproject.cluster.Leadership; | 34 | import org.onosproject.cluster.Leadership; |
34 | import org.onosproject.cluster.LeadershipEvent; | 35 | import org.onosproject.cluster.LeadershipEvent; |
35 | import org.onosproject.cluster.NodeId; | 36 | import org.onosproject.cluster.NodeId; |
36 | import org.onosproject.cluster.RoleInfo; | 37 | import org.onosproject.cluster.RoleInfo; |
38 | +import org.onosproject.core.DefaultApplication; | ||
37 | import org.onosproject.core.DefaultApplicationId; | 39 | import org.onosproject.core.DefaultApplicationId; |
38 | import org.onosproject.core.DefaultGroupId; | 40 | import org.onosproject.core.DefaultGroupId; |
41 | +import org.onosproject.core.Version; | ||
39 | import org.onosproject.mastership.MastershipTerm; | 42 | import org.onosproject.mastership.MastershipTerm; |
40 | import org.onosproject.net.ConnectPoint; | 43 | import org.onosproject.net.ConnectPoint; |
41 | import org.onosproject.net.DefaultAnnotations; | 44 | import org.onosproject.net.DefaultAnnotations; |
... | @@ -192,7 +195,10 @@ public final class KryoNamespaces { | ... | @@ -192,7 +195,10 @@ public final class KryoNamespaces { |
192 | .register(MISC) | 195 | .register(MISC) |
193 | .nextId(KryoNamespace.INITIAL_ID + 30 + 10) | 196 | .nextId(KryoNamespace.INITIAL_ID + 30 + 10) |
194 | .register( | 197 | .register( |
198 | + Version.class, | ||
195 | ControllerNode.State.class, | 199 | ControllerNode.State.class, |
200 | + ApplicationState.class, | ||
201 | + DefaultApplication.class, | ||
196 | Device.Type.class, | 202 | Device.Type.class, |
197 | Port.Type.class, | 203 | Port.Type.class, |
198 | ChassisId.class, | 204 | ChassisId.class, | ... | ... |
... | @@ -8,4 +8,4 @@ export OCN="10.128.11.4" | ... | @@ -8,4 +8,4 @@ export OCN="10.128.11.4" |
8 | 8 | ||
9 | export OCI="${OC1}" | 9 | export OCI="${OC1}" |
10 | 10 | ||
11 | -export ONOS_FEATURES="webconsole,onos-api,onos-core,onos-cli,onos-openflow,onos-gui,onos-rest,onos-app-fwd,onos-app-proxyarp,onos-app-foo" | 11 | +export ONOS_FEATURES="webconsole,onos-api,onos-core,onos-cli,onos-openflow,onos-gui,onos-rest,onos-app-fwd,onos-app-proxyarp" | ... | ... |
... | @@ -27,9 +27,11 @@ import java.io.InputStreamReader; | ... | @@ -27,9 +27,11 @@ import java.io.InputStreamReader; |
27 | import java.lang.Thread.UncaughtExceptionHandler; | 27 | import java.lang.Thread.UncaughtExceptionHandler; |
28 | import java.nio.charset.StandardCharsets; | 28 | import java.nio.charset.StandardCharsets; |
29 | import java.nio.file.FileVisitResult; | 29 | import java.nio.file.FileVisitResult; |
30 | +import java.nio.file.Files; | ||
30 | import java.nio.file.Path; | 31 | import java.nio.file.Path; |
31 | import java.nio.file.Paths; | 32 | import java.nio.file.Paths; |
32 | import java.nio.file.SimpleFileVisitor; | 33 | import java.nio.file.SimpleFileVisitor; |
34 | +import java.nio.file.StandardCopyOption; | ||
33 | import java.nio.file.attribute.BasicFileAttributes; | 35 | import java.nio.file.attribute.BasicFileAttributes; |
34 | import java.util.ArrayList; | 36 | import java.util.ArrayList; |
35 | import java.util.List; | 37 | import java.util.List; |
... | @@ -200,4 +202,60 @@ public abstract class Tools { | ... | @@ -200,4 +202,60 @@ public abstract class Tools { |
200 | } | 202 | } |
201 | } | 203 | } |
202 | 204 | ||
205 | + | ||
206 | + /** | ||
207 | + * Copies the specified directory path. Use with great caution since | ||
208 | + * no attempt is made to check for symbolic links, which could result in | ||
209 | + * copy of unintended files. | ||
210 | + * | ||
211 | + * @param src directory to be copied | ||
212 | + * @param dst destination directory to be removed | ||
213 | + * @throws java.io.IOException if unable to remove contents | ||
214 | + */ | ||
215 | + public static void copyDirectory(String src, String dst) throws IOException { | ||
216 | + walkFileTree(Paths.get(src), new DirectoryCopier(src, dst)); | ||
217 | + } | ||
218 | + | ||
219 | + /** | ||
220 | + * Copies the specified directory path. Use with great caution since | ||
221 | + * no attempt is made to check for symbolic links, which could result in | ||
222 | + * copy of unintended files. | ||
223 | + * | ||
224 | + * @param src directory to be copied | ||
225 | + * @param dst destination directory to be removed | ||
226 | + * @throws java.io.IOException if unable to remove contents | ||
227 | + */ | ||
228 | + public static void copyDirectory(File src, File dst) throws IOException { | ||
229 | + walkFileTree(Paths.get(src.getAbsolutePath()), | ||
230 | + new DirectoryCopier(src.getAbsolutePath(), | ||
231 | + dst.getAbsolutePath())); | ||
232 | + } | ||
233 | + | ||
234 | + | ||
235 | + public static class DirectoryCopier extends SimpleFileVisitor<Path> { | ||
236 | + private Path src; | ||
237 | + private Path dst; | ||
238 | + private StandardCopyOption copyOption = StandardCopyOption.REPLACE_EXISTING; | ||
239 | + | ||
240 | + DirectoryCopier(String src, String dst) { | ||
241 | + this.src = Paths.get(src); | ||
242 | + this.dst = Paths.get(dst); | ||
243 | + } | ||
244 | + | ||
245 | + @Override | ||
246 | + public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException { | ||
247 | + Path targetPath = dst.resolve(src.relativize(dir)); | ||
248 | + if (!Files.exists(targetPath)) { | ||
249 | + Files.createDirectory(targetPath); | ||
250 | + } | ||
251 | + return FileVisitResult.CONTINUE; | ||
252 | + } | ||
253 | + | ||
254 | + @Override | ||
255 | + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { | ||
256 | + Files.copy(file, dst.resolve(src.relativize(file)), copyOption); | ||
257 | + return FileVisitResult.CONTINUE; | ||
258 | + } | ||
259 | + } | ||
260 | + | ||
203 | } | 261 | } | ... | ... |
-
Please register or login to post a comment