/******************************************************************************* * Copyright (c) 2014, 2016 Red Hat Inc. and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Red Hat - Initial Contribution *******************************************************************************/ package org.eclipse.linuxtools.internal.docker.ui.commands; import static org.eclipse.linuxtools.internal.docker.ui.commands.CommandUtils.getRunConsole; import org.eclipse.core.commands.AbstractHandler; import org.eclipse.core.commands.ExecutionEvent; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.SubMonitor; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.linuxtools.docker.core.DockerContainerNotFoundException; import org.eclipse.linuxtools.docker.core.DockerException; import org.eclipse.linuxtools.docker.core.EnumDockerLoggingStatus; import org.eclipse.linuxtools.docker.core.IDockerConnection; import org.eclipse.linuxtools.docker.core.IDockerContainer; import org.eclipse.linuxtools.docker.core.IDockerContainerConfig; import org.eclipse.linuxtools.docker.core.IDockerHostConfig; import org.eclipse.linuxtools.docker.core.IDockerImage; import org.eclipse.linuxtools.docker.ui.Activator; import org.eclipse.linuxtools.internal.docker.core.DockerConnection; import org.eclipse.linuxtools.internal.docker.ui.consoles.RunConsole; import org.eclipse.linuxtools.internal.docker.ui.launch.LaunchConfigurationUtils; import org.eclipse.linuxtools.internal.docker.ui.views.DVMessages; import org.eclipse.linuxtools.internal.docker.ui.wizards.ImageRun; import org.eclipse.swt.widgets.Display; import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.console.IConsoleConstants; import org.eclipse.ui.handlers.HandlerUtil; /** * @author xcoulon * */ public class RunImageCommandHandler extends AbstractHandler { private static final String ERROR_CREATING_CONTAINER = "ContainerCreateError.msg"; //$NON-NLS-1$ private static final String ERROR_REMOVING_CONTAINER = "ContainerRemoveError.msg"; //$NON-NLS-1$ @Override public Object execute(final ExecutionEvent event) { final IWorkbenchPart activePart = HandlerUtil.getActivePart(event); final IDockerImage selectedImage = CommandUtils .getSelectedImage(activePart); if (selectedImage == null) { Activator.log(new DockerException( DVMessages.getString("RunImageUnableToRetrieveError.msg"))); //$NON-NLS-1$ } else { try { final ImageRun wizard = new ImageRun(selectedImage); final boolean runImage = CommandUtils.openWizard(wizard, HandlerUtil.getActiveShell(event)); if (runImage) { final IDockerContainerConfig containerConfig = wizard .getDockerContainerConfig(); final IDockerHostConfig hostConfig = wizard .getDockerHostConfig(); runImage(selectedImage, containerConfig, hostConfig, wizard.getDockerContainerName(), wizard.removeWhenExits()); } } catch (DockerException | CoreException e) { Activator.log(e); } } return null; } /** * Run the given {@link IDockerImage} with the given settings * * @param image * @param containerConfig * @param hostConfig * @param containerName * @param removeWhenExits */ public static void runImage(final IDockerImage image, final IDockerContainerConfig containerConfig, final IDockerHostConfig hostConfig, final String containerName, final boolean removeWhenExits) { final IDockerConnection connection = image.getConnection(); if (containerConfig.tty()) { // show the console view Display.getDefault().asyncExec(() -> { try { PlatformUI.getWorkbench().getActiveWorkbenchWindow() .getActivePage() .showView(IConsoleConstants.ID_CONSOLE_VIEW); } catch (Exception e) { Activator.log(e); } }); } // Create the container in a non-UI thread. final Job runImageJob = new Job( DVMessages.getString("RunImageCreateContainer.job")) { //$NON-NLS-1$ @Override protected IStatus run(final IProgressMonitor monitor) { monitor.beginTask( DVMessages.getString("RunImageRunningTask.msg"), 2); //$NON-NLS-1$ String containerId = null; RunConsole console = null; try { final SubMonitor createContainerMonitor = SubMonitor .convert(monitor, 1); // create the container createContainerMonitor.beginTask( DVMessages.getString( "RunImageCreatingContainerTask.msg"), //$NON-NLS-1$ 1); containerId = ((DockerConnection) connection) .createContainer(containerConfig, hostConfig, containerName); final IDockerContainer container = ((DockerConnection) connection) .getContainer(containerId); createContainerMonitor.done(); // abort if operation was cancelled if (monitor.isCanceled()) { return Status.CANCEL_STATUS; } // start the container final SubMonitor startContainerMonitor = SubMonitor .convert(monitor, 1); startContainerMonitor.beginTask(DVMessages .getString("RunImageStartingContainerTask.msg"), 1); //$NON-NLS-1$ console = getRunConsole(connection, container); if (console != null) { // if we are auto-logging, show the console console.showConsole(); ((DockerConnection) connection).startContainer( containerId, console.getOutputStream()); } else { ((DockerConnection) connection) .startContainer(containerId, null); } startContainerMonitor.done(); // create a launch configuration from the container LaunchConfigurationUtils.createRunImageLaunchConfiguration(image, containerConfig, hostConfig, containerName, removeWhenExits); } catch (final DockerException | InterruptedException e) { if (console != null) { RunConsole.removeConsole(console); } Display.getDefault().syncExec(() -> MessageDialog.openError( PlatformUI.getWorkbench().getActiveWorkbenchWindow() .getShell(), DVMessages.getFormattedString( ERROR_CREATING_CONTAINER, containerConfig.image()), e.getMessage())); } finally { final String tmpContainerId = containerId; if (removeWhenExits) { final Job waitContainerJob = new Job( CommandMessages.getString( "RunImageCommandHandler.waitContainer.label")) { //$NON-NLS-1$ @Override protected IStatus run(IProgressMonitor monitor) { try { if (tmpContainerId != null) { // Wait for the container to finish ((DockerConnection) connection) .waitForContainer(tmpContainerId); // Drain the logging thread before we remove the // container ((DockerConnection) connection) .stopLoggingThread(tmpContainerId); while (((DockerConnection) connection) .loggingStatus( tmpContainerId) == EnumDockerLoggingStatus.LOGGING_ACTIVE) { Thread.sleep(1000); } } } catch (DockerContainerNotFoundException e) { // container not created correctly return Status.OK_STATUS; } catch (DockerException | InterruptedException e) { // ignore any errors in waiting for container or // draining log } try { // try and remove the container if it was created if (tmpContainerId != null) ((DockerConnection) connection) .removeContainer(tmpContainerId); } catch (DockerException | InterruptedException e) { final String id = tmpContainerId; Display.getDefault() .syncExec(() -> MessageDialog.openError( PlatformUI.getWorkbench() .getActiveWorkbenchWindow() .getShell(), DVMessages.getFormattedString( ERROR_REMOVING_CONTAINER, id), e.getMessage())); } return Status.OK_STATUS; } }; // Do not display this job in the UI waitContainerJob.setSystem(true); waitContainerJob.schedule(); } monitor.done(); } return Status.OK_STATUS; } }; runImageJob.schedule(); } }