blob: 67bd6bad3fe14939522b2557991044f95acc732f [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",
Arnav Jaina359b182019-07-19 11:00:49 -070057 description = "Command name (install|activate|deactivate|uninstall|download|installreg)",
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) {
Arnav Jaina359b182019-07-19 11:00:49 -070093
Thomas Vachuskaa7a0f562015-04-14 23:27:44 -070094 try {
Jon Halla3fcf672017-03-28 16:53:22 -070095 if ("-".equals(url)) {
Thomas Vachuskaa7a0f562015-04-14 23:27:44 -070096 service.install(System.in);
Arnav Jaina359b182019-07-19 11:00:49 -070097 } else if (url.contains("oar")) {
98 service.install(new URL(url).openStream());
Thomas Vachuskaa7a0f562015-04-14 23:27:44 -070099 } else {
Arnav Jain80f2cb82019-07-15 10:54:17 -0700100 Set<Application> app = get(ApplicationService.class)
Arnav Jaina359b182019-07-19 11:00:49 -0700101 .getRegisteredApplications();
Arnav Jain80f2cb82019-07-15 10:54:17 -0700102 if (app.isEmpty()) {
Arnav Jaina359b182019-07-19 11:00:49 -0700103 System.out.println("Could Not Install " + url);
104 return false;
Arnav Jain80f2cb82019-07-15 10:54:17 -0700105 }
106 Iterator<Application> iterator = app.iterator();
Arnav Jaina359b182019-07-19 11:00:49 -0700107 Application recent = null;
Arnav Jain80f2cb82019-07-15 10:54:17 -0700108 while (iterator.hasNext()) {
109 Application application = iterator.next();
Arnav Jaina359b182019-07-19 11:00:49 -0700110 if (recent == null && application.id().name().equals(url)) {
111 recent = application;
112 } else if (application.version().compareTo(recent.version()) > 0 &&
113 application.id().name().equals(url)) {
114 recent = application;
Arnav Jain80f2cb82019-07-15 10:54:17 -0700115 }
116 }
Arnav Jaina359b182019-07-19 11:00:49 -0700117 service.install(recent.imageUrl().openStream());
Thomas Vachuskaa7a0f562015-04-14 23:27:44 -0700118 }
119 } catch (IOException e) {
120 error("Unable to get URL: %s", url);
121 return false;
122 }
123 return true;
124 }
125
Thomas Vachuska08b4dec2017-08-31 15:20:17 -0700126 // Downloads the application bits to the standard output.
127 private boolean downloadApp(ApplicationAdminService service, String name) {
128 try {
129 ByteStreams.copy(service.getApplicationArchive(service.getId(name)),
130 System.out);
131 } catch (IOException e) {
132 error("Unable to download bits for application %s", name);
133 return false;
134 }
135 return true;
136 }
137
Thomas Vachuskaa7a0f562015-04-14 23:27:44 -0700138 // Manages the specified application.
139 private boolean manageApp(ApplicationAdminService service, String name) {
140 ApplicationId appId = service.getId(name);
141 if (appId == null) {
Yuta HIGUCHI315baad2017-01-31 15:14:30 -0800142 List<Application> matches = service.getApplications().stream()
143 .filter(app -> app.id().name().matches(".*\\." + name + "$"))
144 .collect(Collectors.toList());
145
146 if (matches.size() == 1) {
147 // Found match
148 appId = matches.iterator().next().id();
149 } else if (!matches.isEmpty()) {
150 print("Did you mean one of: %s",
151 matches.stream()
152 .map(Application::id)
153 .map(ApplicationId::name)
154 .collect(Collectors.toList()));
155 return false;
156 }
157 }
158 if (appId == null) {
Thomas Vachuskaa7a0f562015-04-14 23:27:44 -0700159 print("No such application: %s", name);
160 return false;
161 }
162
Jonathan Hartb5132fa2017-02-02 13:20:35 -0800163 String action;
Thomas Vachuskaa7a0f562015-04-14 23:27:44 -0700164 if (command.equals(UNINSTALL)) {
165 service.uninstall(appId);
Jonathan Hartb5132fa2017-02-02 13:20:35 -0800166 action = "Uninstalled";
Thomas Vachuskaa7a0f562015-04-14 23:27:44 -0700167 } else if (command.equals(ACTIVATE)) {
168 service.activate(appId);
Jonathan Hartb5132fa2017-02-02 13:20:35 -0800169 action = "Activated";
Thomas Vachuskaa7a0f562015-04-14 23:27:44 -0700170 } else if (command.equals(DEACTIVATE)) {
171 service.deactivate(appId);
Jonathan Hartb5132fa2017-02-02 13:20:35 -0800172 action = "Deactivated";
Thomas Vachuskaa7a0f562015-04-14 23:27:44 -0700173 } else {
174 print("Unsupported command: %s", command);
175 return false;
176 }
Jonathan Hartb5132fa2017-02-02 13:20:35 -0800177 print("%s %s", action, appId.name());
Thomas Vachuskaa7a0f562015-04-14 23:27:44 -0700178 return true;
179 }
180
Thomas Vachuska1dcb0482015-02-18 18:21:28 -0800181}