blob: 9b5e91f2b31dc29d23596855769454c1deeab95a [file] [log] [blame]
Thomas Vachuska1dcb0482015-02-18 18:21:28 -08001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2015-present Open Networking Foundation
Thomas Vachuska1dcb0482015-02-18 18:21:28 -08003 *
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 */
16package org.onosproject.cli.app;
17
Thomas Vachuska08b4dec2017-08-31 15:20:17 -070018import com.google.common.io.ByteStreams;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070019import org.apache.karaf.shell.api.action.Argument;
20import org.apache.karaf.shell.api.action.Command;
Ray Milkey9dcc0e82018-10-01 10:26:53 -070021import org.apache.karaf.shell.api.action.Completion;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070022import org.apache.karaf.shell.api.action.lifecycle.Service;
Thomas Vachuska1dcb0482015-02-18 18:21:28 -080023import org.onosproject.app.ApplicationAdminService;
Arnav Jain80f2cb82019-07-15 10:54:17 -070024import org.onosproject.app.ApplicationService;
Thomas Vachuska1dcb0482015-02-18 18:21:28 -080025import org.onosproject.cli.AbstractShellCommand;
Yuta HIGUCHI315baad2017-01-31 15:14:30 -080026import org.onosproject.core.Application;
Thomas Vachuska1dcb0482015-02-18 18:21:28 -080027import org.onosproject.core.ApplicationId;
Arnav Jain80f2cb82019-07-15 10:54:17 -070028import org.onosproject.core.VersionService;
29import org.osgi.service.component.annotations.Reference;
30import org.osgi.service.component.annotations.ReferenceCardinality;
Thomas Vachuska1dcb0482015-02-18 18:21:28 -080031
Thomas Vachuskaa7a0f562015-04-14 23:27:44 -070032import java.io.IOException;
33import java.net.URL;
Arnav Jain80f2cb82019-07-15 10:54:17 -070034import java.util.Iterator;
Yuta HIGUCHI315baad2017-01-31 15:14:30 -080035import java.util.List;
Arnav Jain80f2cb82019-07-15 10:54:17 -070036import java.util.Set;
Yuta HIGUCHI315baad2017-01-31 15:14:30 -080037import java.util.stream.Collectors;
Thomas Vachuskaa7a0f562015-04-14 23:27:44 -070038
Thomas Vachuska1dcb0482015-02-18 18:21:28 -080039/**
40 * Manages application inventory.
41 */
Ray Milkeyd84f89b2018-08-17 14:54:17 -070042@Service
Thomas Vachuska1dcb0482015-02-18 18:21:28 -080043@Command(scope = "onos", name = "app",
44 description = "Manages application inventory")
45public class ApplicationCommand extends AbstractShellCommand {
46
47 static final String INSTALL = "install";
48 static final String UNINSTALL = "uninstall";
49 static final String ACTIVATE = "activate";
50 static final String DEACTIVATE = "deactivate";
Thomas Vachuska08b4dec2017-08-31 15:20:17 -070051 static final String DOWNLOAD = "download";
Thomas Vachuska1dcb0482015-02-18 18:21:28 -080052
Arnav Jain80f2cb82019-07-15 10:54:17 -070053 @Reference(cardinality = ReferenceCardinality.MANDATORY)
54 protected VersionService versionService;
55
Thomas Vachuska1dcb0482015-02-18 18:21:28 -080056 @Argument(index = 0, name = "command",
Thomas Vachuska08b4dec2017-08-31 15:20:17 -070057 description = "Command name (install|activate|deactivate|uninstall|download)",
Ray Milkey9dcc0e82018-10-01 10:26:53 -070058 required = true)
59 @Completion(ApplicationCommandCompleter.class)
Thomas Vachuska1dcb0482015-02-18 18:21:28 -080060 String command = null;
61
Thomas Vachuskaa7a0f562015-04-14 23:27:44 -070062 @Argument(index = 1, name = "names", description = "Application name(s) or URL(s)",
Thomas Vachuskafba28572015-03-25 18:48:59 -070063 required = true, multiValued = true)
Ray Milkey9dcc0e82018-10-01 10:26:53 -070064 @Completion(ApplicationNameCompleter.class)
Thomas Vachuskafba28572015-03-25 18:48:59 -070065 String[] names = null;
Thomas Vachuska1dcb0482015-02-18 18:21:28 -080066
67 @Override
Ray Milkeyd84f89b2018-08-17 14:54:17 -070068 protected void doExecute() {
Thomas Vachuska1dcb0482015-02-18 18:21:28 -080069 ApplicationAdminService service = get(ApplicationAdminService.class);
70 if (command.equals(INSTALL)) {
Thomas Vachuskaa7a0f562015-04-14 23:27:44 -070071 for (String name : names) {
72 if (!installApp(service, name)) {
73 return;
74 }
75 }
Thomas Vachuska08b4dec2017-08-31 15:20:17 -070076 } else if (command.equals(DOWNLOAD)) {
Thomas Vachuskafba28572015-03-25 18:48:59 -070077 for (String name : names) {
Thomas Vachuska08b4dec2017-08-31 15:20:17 -070078 if (!downloadApp(service, name)) {
Thomas Vachuskafba28572015-03-25 18:48:59 -070079 return;
80 }
Thomas Vachuska1dcb0482015-02-18 18:21:28 -080081 }
Thomas Vachuska08b4dec2017-08-31 15:20:17 -070082 } else {
83 for (String name : names) {
84 if (!manageApp(service, name)) {
85 return;
86 }
87 }
88 }
Thomas Vachuska1dcb0482015-02-18 18:21:28 -080089 }
Thomas Vachuska1dcb0482015-02-18 18:21:28 -080090
Thomas Vachuskaa7a0f562015-04-14 23:27:44 -070091 // Installs the application from input of the specified URL
92 private boolean installApp(ApplicationAdminService service, String url) {
93 try {
Jon Halla3fcf672017-03-28 16:53:22 -070094 if ("-".equals(url)) {
Thomas Vachuskaa7a0f562015-04-14 23:27:44 -070095 service.install(System.in);
96 } else {
Arnav Jain80f2cb82019-07-15 10:54:17 -070097 Set<Application> app = get(ApplicationService.class)
98 .getRegisteredApplications().stream()
99 .filter(ra -> ra.id().toString().equals(url))
100 .collect(Collectors.toSet());
101 if (app.isEmpty()) {
102 service.install(new URL(url).openStream());
103 }
104 Iterator<Application> iterator = app.iterator();
105 while (iterator.hasNext()) {
106 Application application = iterator.next();
107 if (application.version().toString().equals(versionService.version().toString())) {
108 service.install(application.imageUrl().openStream());
109 }
110 }
Thomas Vachuskaa7a0f562015-04-14 23:27:44 -0700111 }
112 } catch (IOException e) {
113 error("Unable to get URL: %s", url);
114 return false;
115 }
116 return true;
117 }
118
Thomas Vachuska08b4dec2017-08-31 15:20:17 -0700119 // Downloads the application bits to the standard output.
120 private boolean downloadApp(ApplicationAdminService service, String name) {
121 try {
122 ByteStreams.copy(service.getApplicationArchive(service.getId(name)),
123 System.out);
124 } catch (IOException e) {
125 error("Unable to download bits for application %s", name);
126 return false;
127 }
128 return true;
129 }
130
Thomas Vachuskaa7a0f562015-04-14 23:27:44 -0700131 // Manages the specified application.
132 private boolean manageApp(ApplicationAdminService service, String name) {
133 ApplicationId appId = service.getId(name);
134 if (appId == null) {
Yuta HIGUCHI315baad2017-01-31 15:14:30 -0800135 List<Application> matches = service.getApplications().stream()
136 .filter(app -> app.id().name().matches(".*\\." + name + "$"))
137 .collect(Collectors.toList());
138
139 if (matches.size() == 1) {
140 // Found match
141 appId = matches.iterator().next().id();
142 } else if (!matches.isEmpty()) {
143 print("Did you mean one of: %s",
144 matches.stream()
145 .map(Application::id)
146 .map(ApplicationId::name)
147 .collect(Collectors.toList()));
148 return false;
149 }
150 }
151 if (appId == null) {
Thomas Vachuskaa7a0f562015-04-14 23:27:44 -0700152 print("No such application: %s", name);
153 return false;
154 }
155
Jonathan Hartb5132fa2017-02-02 13:20:35 -0800156 String action;
Thomas Vachuskaa7a0f562015-04-14 23:27:44 -0700157 if (command.equals(UNINSTALL)) {
158 service.uninstall(appId);
Jonathan Hartb5132fa2017-02-02 13:20:35 -0800159 action = "Uninstalled";
Thomas Vachuskaa7a0f562015-04-14 23:27:44 -0700160 } else if (command.equals(ACTIVATE)) {
161 service.activate(appId);
Jonathan Hartb5132fa2017-02-02 13:20:35 -0800162 action = "Activated";
Thomas Vachuskaa7a0f562015-04-14 23:27:44 -0700163 } else if (command.equals(DEACTIVATE)) {
164 service.deactivate(appId);
Jonathan Hartb5132fa2017-02-02 13:20:35 -0800165 action = "Deactivated";
Thomas Vachuskaa7a0f562015-04-14 23:27:44 -0700166 } else {
167 print("Unsupported command: %s", command);
168 return false;
169 }
Jonathan Hartb5132fa2017-02-02 13:20:35 -0800170 print("%s %s", action, appId.name());
Thomas Vachuskaa7a0f562015-04-14 23:27:44 -0700171 return true;
172 }
173
Thomas Vachuska1dcb0482015-02-18 18:21:28 -0800174}