Thomas Vachuska
Committed by Ray Milkey

ONOS-785 Adding distributed store for apps & app admin CLIs

Change-Id: Ia7639f3258fca2a18ba513f0c95de0ab8ea7ceee
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,13 +203,19 @@ public class ApplicationManager implements ApplicationService, ApplicationAdminS ...@@ -202,13 +203,19 @@ 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()) {
205 - featuresService.installFeature(name); 206 + Feature feature = featuresService.getFeature(name);
207 + if (!featuresService.isInstalled(feature)) {
208 + featuresService.installFeature(name);
209 + }
206 } 210 }
207 } 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()) {
211 - featuresService.uninstallFeature(name); 215 + Feature feature = featuresService.getFeature(name);
216 + if (featuresService.isInstalled(feature)) {
217 + featuresService.uninstallFeature(name);
218 + }
212 } 219 }
213 } 220 }
214 221
......
...@@ -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>
......
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.&nbsp;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.&nbsp;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 }
......