/**
* Copyright 2014-2017 Linagora, Université Joseph Fourier, Floralis
*
* The present code is developed in the scope of the joint LINAGORA -
* Université Joseph Fourier - Floralis research program and is designated
* as a "Result" pursuant to the terms and conditions of the LINAGORA
* - Université Joseph Fourier - Floralis research program. Each copyright
* holder of Results enumerated here above fully & independently holds complete
* ownership of the complete Intellectual Property rights applicable to the whole
* of said Results, and may freely exploit it in any manner which does not infringe
* the moral rights of the other copyright holders.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.roboconf.target.docker.internal;
import static net.roboconf.target.docker.internal.DockerUtils.extractBoolean;
import java.util.UUID;
import java.util.logging.Logger;
import org.ops4j.pax.url.mvn.MavenResolver;
import com.github.dockerjava.api.DockerClient;
import com.github.dockerjava.api.command.InspectContainerResponse.ContainerState;
import com.github.dockerjava.api.model.Container;
import net.roboconf.core.model.beans.Instance;
import net.roboconf.core.utils.Utils;
import net.roboconf.target.api.AbstractThreadedTargetHandler;
import net.roboconf.target.api.TargetException;
import net.roboconf.target.api.TargetHandlerParameters;
/**
* @author Pierre-Yves Gibello - Linagora
* @author Pierre Bourret - Université Joseph Fourier
* @author Amadou Diarra - Université Joseph Fourier
*/
public class DockerHandler extends AbstractThreadedTargetHandler {
// Injected by iPojo
private MavenResolver mavenResolver;
// Other properties
public static final String TARGET_ID = "docker";
static final String MESSAGING_TYPE = "net.roboconf.messaging.type";
static final String AGENT_JRE_AND_PACKAGES_DEFAULT = "openjdk-7-jre-headless";
// Container creation
static final String IMAGE_ID = "docker.image";
static final String ENDPOINT = "docker.endpoint";
static final String USER = "docker.user";
static final String PASSWORD = "docker.password";
static final String EMAIL = "docker.email";
static final String VERSION = "docker.version";
static final String RUN_EXEC = "docker.run.exec";
// Image generation
static final String GENERATE_IMAGE = "docker.generate.image";
static final String BASE_IMAGE = "docker.base.image";
static final String AGENT_PACKAGE_URL = "docker.agent.package.url";
static final String AGENT_JRE_AND_PACKAGES = "docker.agent.jre-packages";
static final String ADDITIONAL_PACKAGES = "docker.additional.packages";
static final String ADDITIONAL_DEPLOY = "docker.additional.deploy";
static final String DOWNLOAD_BASE_IMAGE = "docker.download.base-image";
static final String DOCKER_IMAGE_REGISTRY = "docker.image.registry";
static final String DEFAULT_DOCKER_IMAGE_REGISTRY = "registry.hub.docker.com";
// Docker exec markers for Roboconf configuration injection.
static final String MARKER_MESSAGING_CONFIGURATION = "$msgConfig$";
static final String MARKER_APPLICATION_NAME = "$applicationName$";
static final String MARKER_INSTANCE_PATH = "$instancePath$";
static final String MARKER_MESSAGING_TYPE = "$messagingType$";
static final String OPTION_PREFIX = "docker.option.";
static final String OPTION_PREFIX_RUN = OPTION_PREFIX + "run.";
static final String OPTION_PREFIX_ENV = OPTION_PREFIX + "env.";
private final Logger logger = Logger.getLogger( getClass().getName());
/**
* Constructor.
*/
public DockerHandler() {
// Wait 2 seconds between every polling
this.delay = 2000;
}
/*
* (non-Javadoc)
* @see net.roboconf.target.api.TargetHandler#getTargetId()
*/
@Override
public String getTargetId() {
return TARGET_ID;
}
/*
* (non-Javadoc)
* @see net.roboconf.target.api.TargetHandler
* #createMachine(net.roboconf.target.api.TargetHandlerParameters)
*/
@Override
public String createMachine( TargetHandlerParameters parameters ) throws TargetException {
this.logger.fine( "Creating a new machine." );
// Search an existing image in the local Docker repository
DockerUtils.verifyDockerClient( parameters.getTargetProperties());
// We do not do anything else here.
// We return a UUID.
return "rbcf_" + UUID.randomUUID().toString();
}
/*
* (non-Javadoc)
* @see net.roboconf.target.api.AbstractThreadedTargetHandler#machineConfigurator(
* net.roboconf.target.api.TargetHandlerParameters, java.lang.String, net.roboconf.core.model.beans.Instance)
*/
@Override
public MachineConfigurator machineConfigurator( TargetHandlerParameters parameters, String machineId, Instance scopedInstance ) {
// machineId does not match a real container ID.
// It is the name of the container we will create.
DockerMachineConfigurator configurator = new DockerMachineConfigurator(
parameters.getTargetProperties(),
parameters.getMessagingProperties(),
machineId,
parameters.getScopedInstancePath(),
parameters.getApplicationName(),
scopedInstance );
configurator.setMavenResolver( this.mavenResolver );
return configurator;
}
/*
* (non-Javadoc)
* @see net.roboconf.target.api.TargetHandler
* #isMachineRunning(net.roboconf.target.api.TargetHandlerParameters, java.lang.String)
*/
@Override
public boolean isMachineRunning( TargetHandlerParameters parameters, String machineId )
throws TargetException {
boolean result = false;
try {
DockerClient dockerClient = DockerUtils.createDockerClient( parameters.getTargetProperties());
ContainerState state = DockerUtils.getContainerState( machineId, dockerClient );
result = state != null && extractBoolean( state.getRunning());
} catch( Exception e ) {
// nothing, we consider it is not running
Utils.logException( this.logger, e );
}
return result;
}
/*
* (non-Javadoc)
* @see net.roboconf.target.api.TargetHandler
* #terminateMachine(net.roboconf.target.api.TargetHandlerParameters, java.lang.String)
*/
@Override
public void terminateMachine( TargetHandlerParameters parameters, String machineId )
throws TargetException {
this.logger.fine( "Terminating machine " + machineId );
try {
cancelMachineConfigurator( machineId );
DockerClient dockerClient = DockerUtils.createDockerClient( parameters.getTargetProperties());
Container container = DockerUtils.findContainerByIdOrByName( machineId, dockerClient );
// The case "container == null" is possible.
// Indeed, it may have been killed manually. This method will then
// just mark the Roboconf instance as "not deployed" without throwing an exception.
if( container != null ) {
ContainerState state = DockerUtils.getContainerState( machineId, dockerClient );
if( state != null
&& ( extractBoolean( state.getRunning()) || extractBoolean( state.getPaused())))
dockerClient.killContainerCmd( container.getId()).exec();
dockerClient.removeContainerCmd( container.getId()).withForce( true ).exec();
}
} catch( Exception e ) {
throw new TargetException( e );
}
}
/*
* (non-Javadoc)
* @see net.roboconf.target.api.TargetHandler
* #retrievePublicIpAddress(net.roboconf.target.api.TargetHandlerParameters, java.lang.String)
*/
@Override
public String retrievePublicIpAddress( TargetHandlerParameters parameters, String machineId )
throws TargetException {
return "localhost";
}
}