mirror of
https://github.com/opennetworkinglab/onos.git
synced 2026-05-05 20:26:16 +02:00
ONOS-6980 Adding support for download of application bits.
Change-Id: I742950690b50038cac0bb2ad2da4eaac5781da85
This commit is contained in:
parent
ac5f0fbf59
commit
08b4decc39
@ -15,6 +15,7 @@
|
||||
*/
|
||||
package org.onosproject.cli.app;
|
||||
|
||||
import com.google.common.io.ByteStreams;
|
||||
import org.apache.karaf.shell.commands.Argument;
|
||||
import org.apache.karaf.shell.commands.Command;
|
||||
import org.onosproject.app.ApplicationAdminService;
|
||||
@ -38,9 +39,10 @@ public class ApplicationCommand extends AbstractShellCommand {
|
||||
static final String UNINSTALL = "uninstall";
|
||||
static final String ACTIVATE = "activate";
|
||||
static final String DEACTIVATE = "deactivate";
|
||||
static final String DOWNLOAD = "download";
|
||||
|
||||
@Argument(index = 0, name = "command",
|
||||
description = "Command name (install|activate|deactivate|uninstall)",
|
||||
description = "Command name (install|activate|deactivate|uninstall|download)",
|
||||
required = true, multiValued = false)
|
||||
String command = null;
|
||||
|
||||
@ -58,14 +60,20 @@ public class ApplicationCommand extends AbstractShellCommand {
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
} else if (command.equals(DOWNLOAD)) {
|
||||
for (String name : names) {
|
||||
if (!manageApp(service, name)) {
|
||||
if (!downloadApp(service, name)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (String name : names) {
|
||||
if (!manageApp(service, name)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Installs the application from input of the specified URL
|
||||
private boolean installApp(ApplicationAdminService service, String url) {
|
||||
@ -82,6 +90,18 @@ public class ApplicationCommand extends AbstractShellCommand {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Downloads the application bits to the standard output.
|
||||
private boolean downloadApp(ApplicationAdminService service, String name) {
|
||||
try {
|
||||
ByteStreams.copy(service.getApplicationArchive(service.getId(name)),
|
||||
System.out);
|
||||
} catch (IOException e) {
|
||||
error("Unable to download bits for application %s", name);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Manages the specified application.
|
||||
private boolean manageApp(ApplicationAdminService service, String name) {
|
||||
ApplicationId appId = service.getId(name);
|
||||
|
||||
@ -28,7 +28,7 @@ import static org.onosproject.cli.app.ApplicationCommand.*;
|
||||
public class ApplicationCommandCompleter extends AbstractChoicesCompleter {
|
||||
@Override
|
||||
public List<String> choices() {
|
||||
return ImmutableList.of(INSTALL, UNINSTALL, ACTIVATE, DEACTIVATE);
|
||||
return ImmutableList.of(INSTALL, UNINSTALL, ACTIVATE, DEACTIVATE, DOWNLOAD);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -63,7 +63,7 @@ public class ApplicationNameCompleter extends AbstractCompleter {
|
||||
// if (previousApps.contains(app.id().name())) {
|
||||
// continue;
|
||||
// }
|
||||
if ("uninstall".equals(cmd) ||
|
||||
if ("uninstall".equals(cmd) || "download".equals(cmd) ||
|
||||
("activate".equals(cmd) && state == INSTALLED) ||
|
||||
("deactivate".equals(cmd) && state == ACTIVE)) {
|
||||
strings.add(app.id().name());
|
||||
|
||||
@ -20,6 +20,7 @@ import org.onosproject.core.ApplicationId;
|
||||
import org.onosproject.event.ListenerService;
|
||||
import org.onosproject.security.Permission;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
@ -74,4 +75,14 @@ public interface ApplicationService
|
||||
* @param hook pre-deactivation hook
|
||||
*/
|
||||
void registerDeactivateHook(ApplicationId appId, Runnable hook);
|
||||
|
||||
/**
|
||||
* Returns stream that contains the application OAR/JAR file contents.
|
||||
*
|
||||
* @param appId application identifier
|
||||
* @return input stream containing the app OAR/JAR file
|
||||
*/
|
||||
default InputStream getApplicationArchive(ApplicationId appId) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@ -105,4 +105,14 @@ public interface ApplicationStore extends Store<ApplicationEvent, ApplicationSto
|
||||
*/
|
||||
void setPermissions(ApplicationId appId, Set<Permission> permissions);
|
||||
|
||||
/**
|
||||
* Returns stream that contains the application OAR/JAR file contents.
|
||||
*
|
||||
* @param appId application identifier
|
||||
* @return input stream containing the app OAR/JAR file
|
||||
*/
|
||||
default InputStream getApplicationArchive(ApplicationId appId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -199,13 +199,11 @@ public class ApplicationArchive
|
||||
checkState(!appFile(desc.name(), APP_XML).exists(),
|
||||
"Application %s already installed", desc.name());
|
||||
|
||||
boolean isSelfContainedJar = false;
|
||||
|
||||
if (plainXml) {
|
||||
expandPlainApplication(cache, desc);
|
||||
} else {
|
||||
bis.reset();
|
||||
isSelfContainedJar = expandZippedApplication(bis, desc);
|
||||
boolean isSelfContainedJar = expandZippedApplication(bis, desc);
|
||||
|
||||
if (isSelfContainedJar) {
|
||||
bis.reset();
|
||||
@ -254,7 +252,7 @@ public class ApplicationArchive
|
||||
|
||||
/**
|
||||
* Returns application archive stream for the specified application. This
|
||||
* will be either the application ZIP file or the application XML file.
|
||||
* will be either the application OAR file, JAR file or the plain XML file.
|
||||
*
|
||||
* @param appName application name
|
||||
* @return application archive stream
|
||||
|
||||
@ -179,6 +179,12 @@ public class ApplicationManager
|
||||
store.setPermissions(appId, permissions);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getApplicationArchive(ApplicationId appId) {
|
||||
checkNotNull(appId, APP_ID_NULL);
|
||||
return store.getApplicationArchive(appId);
|
||||
}
|
||||
|
||||
private void updateStoreAndWaitForNotificationHandling(ApplicationId appId,
|
||||
Consumer<ApplicationId> storeUpdateTask) {
|
||||
CountDownLatch latch = new CountDownLatch(1);
|
||||
|
||||
@ -437,6 +437,11 @@ public class DistributedApplicationStore extends ApplicationArchive
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getApplicationArchive(ApplicationId appId) {
|
||||
return getApplicationInputStream(appId.name());
|
||||
}
|
||||
|
||||
private class AppActivator implements Consumer<Application> {
|
||||
@Override
|
||||
public void accept(Application app) {
|
||||
|
||||
@ -13,7 +13,7 @@
|
||||
~ See the License for the specific language governing permissions and
|
||||
~ limitations under the License.
|
||||
-->
|
||||
<scenario name="yang-lve-compile" description="Live YANG compilation">
|
||||
<scenario name="yang-live-compile" description="Live YANG compilation">
|
||||
<group name="YANG-Live-Compile">
|
||||
<step name="Activate-YANG-Runtime" exec="onos ${OC1} app activate org.onosproject.yang"/>
|
||||
<step name="Pre-Cleanup-YANG-Model" exec="onos ${OC1} app uninstall l3vpn" env="~"/>
|
||||
|
||||
@ -207,6 +207,23 @@ public class ApplicationsWebResource extends AbstractWebResource {
|
||||
return response(appId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get application OAR/JAR file.
|
||||
* Returns the OAR/JAR file used to install the specified application.
|
||||
*
|
||||
* @param name application name
|
||||
* @return 200 OK; 404; 401
|
||||
*/
|
||||
@GET
|
||||
@Produces(MediaType.APPLICATION_OCTET_STREAM)
|
||||
@Path("{name}/bits")
|
||||
public Response getAppBits(@PathParam("name") String name) {
|
||||
ApplicationAdminService service = get(ApplicationAdminService.class);
|
||||
ApplicationId appId = nullIsNotFound(service.getId(name), APP_ID_NOT_FOUND);
|
||||
InputStream bits = service.getApplicationArchive(appId);
|
||||
return ok(bits).build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets applicationId entry by either id or name.
|
||||
*
|
||||
|
||||
@ -58,6 +58,26 @@ public class ApplicationResource extends BaseResource {
|
||||
return Response.ok().build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get application OAR/JAR file.
|
||||
* Returns the OAR/JAR file used to install the specified application.
|
||||
*
|
||||
* @param name application name
|
||||
* @return 200 OK; 404; 401
|
||||
*/
|
||||
@GET
|
||||
@Produces(MediaType.APPLICATION_OCTET_STREAM)
|
||||
@Path("{name}/download")
|
||||
public Response download(@PathParam("name") String name) {
|
||||
ApplicationAdminService service = get(ApplicationAdminService.class);
|
||||
ApplicationId appId = service.getId(name);
|
||||
InputStream bits = service.getApplicationArchive(appId);
|
||||
String fileName = appId.name() + ".oar";
|
||||
return Response.ok(bits)
|
||||
.header("Content-Disposition", "attachment; filename=\"" + fileName + "\"")
|
||||
.build();
|
||||
}
|
||||
|
||||
@Path("{name}/icon")
|
||||
@GET
|
||||
@Produces("image/png")
|
||||
|
||||
@ -26,6 +26,7 @@ tt_ctl_upload=Upload an application (.oar file)
|
||||
tt_ctl_activate=Activate selected application
|
||||
tt_ctl_deactivate=Deactivate selected application
|
||||
tt_ctl_uninstall=Uninstall selected application
|
||||
tt_ctl_download=Download selected application (.oar file)
|
||||
|
||||
# Quick-Help panel
|
||||
qh_hint_esc=Deselect application
|
||||
|
||||
@ -23,7 +23,7 @@
|
||||
}
|
||||
|
||||
#ov-app div.ctrl-btns {
|
||||
width: 250px;
|
||||
width: 290px;
|
||||
}
|
||||
|
||||
/* -- Drag-n-Drop oar file upload -- */
|
||||
|
||||
@ -38,6 +38,12 @@
|
||||
tooltip tt-msg="uninstallTip"
|
||||
ng-class="{active: ctrlBtnState.selection}">
|
||||
</div>
|
||||
<!-- FIXME: create proper download icon -->
|
||||
<div icon icon-size="42" icon-id="downArrow"
|
||||
ng-click="downloadApp()"
|
||||
tooltip tt-msg="downloadTip"
|
||||
ng-class="{active: ctrlBtnState.selection}">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@ -45,8 +45,9 @@
|
||||
detailsResp = 'appDetailsResponse',
|
||||
fileUploadUrl = 'applications/upload',
|
||||
activateOption = '?activate=true',
|
||||
iconUrlPrefix = 'rs/applications/',
|
||||
appUrlPrefix = 'rs/applications/',
|
||||
iconUrlSuffix = '/icon',
|
||||
downloadSuffix = '/download',
|
||||
dialogId = 'app-dialog',
|
||||
dialogOpts = {
|
||||
edge: 'right',
|
||||
@ -167,7 +168,7 @@
|
||||
}
|
||||
|
||||
function addIcon(elem, value) {
|
||||
elem.append('img').attr('src', iconUrlPrefix + value + iconUrlSuffix);
|
||||
elem.append('img').attr('src', appUrlPrefix + value + iconUrlSuffix);
|
||||
}
|
||||
|
||||
function populateTop(details) {
|
||||
@ -250,6 +251,7 @@
|
||||
$scope.activateTip = lion('tt_ctl_activate');
|
||||
$scope.deactivateTip = lion('tt_ctl_deactivate');
|
||||
$scope.uninstallTip = lion('tt_ctl_uninstall');
|
||||
$scope.downloadTip = lion('tt_ctl_download');
|
||||
|
||||
|
||||
var handlers = {};
|
||||
@ -359,6 +361,12 @@
|
||||
}
|
||||
};
|
||||
|
||||
$scope.downloadApp = function () {
|
||||
if ($scope.ctrlBtnState.selection) {
|
||||
window.location = appUrlPrefix + $scope.selId + downloadSuffix;
|
||||
}
|
||||
};
|
||||
|
||||
$scope.$on('FileChanged', function () {
|
||||
var formData = new FormData(),
|
||||
url;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user