/** * This file is part of CloudML [ http://cloudml.org ] * * Copyright (C) 2012 - SINTEF ICT * Contact: Franck Chauvel <franck.chauvel@sintef.no> * * Module: root * * CloudML is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * CloudML is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General * Public License along with CloudML. If not, see * <http://www.gnu.org/licenses/>. */ package org.cloudml.deployer; import java.io.IOException; import java.net.*; import java.util.*; import java.util.logging.Level; import java.util.logging.Logger; import org.apache.commons.jxpath.JXPathContext; import org.apache.commons.jxpath.JXPathNotFoundException; import org.cloudml.connectors.*; import org.cloudml.connectors.util.CloudMLQueryUtil; import org.cloudml.connectors.util.ConfigValet; import org.cloudml.connectors.util.MercurialConnector; import org.cloudml.core.*; import org.cloudml.core.InternalComponentInstance.State; import org.cloudml.core.actions.StandardLibrary; import org.cloudml.core.collections.*; import org.cloudml.monitoring.status.StatusConfiguration; import org.cloudml.monitoring.status.StatusMonitor; import org.cloudml.monitoring.synchronization.MonitoringPlatformConfiguration; import org.cloudml.monitoring.synchronization.MonitoringSynch; import org.cloudml.mrt.Coordinator; import org.cloudml.mrt.SimpleModelRepo; /* * The deployment Engine * author: Nicolas Ferry * author: Hui Song */ public class CloudAppDeployer { private static final Logger journal = Logger.getLogger(CloudAppDeployer.class.getName()); private static boolean DEBUG=false; ComponentInstanceGroup<ComponentInstance<? extends Component>> alreadyDeployed = new ComponentInstanceGroup<ComponentInstance<? extends Component>>(); ComponentInstanceGroup<ComponentInstance<? extends Component>> alreadyStarted = new ComponentInstanceGroup<ComponentInstance<? extends Component>>(); private Deployment currentModel; private Deployment targetModel; private Coordinator coordinator; private boolean statusMonitorActive; private StatusMonitor statusMonitor; //always check if active public CloudAppDeployer() { System.setProperty("jsse.enableSNIExtension", "false"); } public Deployment getCurrentModel(){ return currentModel; } public StatusMonitor getStatusMonitor(){ return this.statusMonitor; } public Coordinator getCoordinator(){ return coordinator; } public void setCoordinator(Coordinator coordinator){ this.coordinator=coordinator; } /** * Deploy from a deployment model * * @param targetModel a deployment model */ public void deploy(Deployment targetModel) { unlessNotNull("Cannot deploy null!", targetModel); this.targetModel = targetModel; //set up the monitoring StatusConfiguration.StatusMonitorProperties statusMonitorProperties = StatusConfiguration.load(); if (currentModel == null) { journal.log(Level.INFO, ">> First deployment..."); this.currentModel = targetModel; if (statusMonitorProperties.getActivated() && statusMonitor == null) { statusMonitorActive = true; statusMonitor = new StatusMonitor(statusMonitorProperties.getFrequency(), false, coordinator); } // Provisioning vms and external services setExternalServices(targetModel.getComponentInstances().onlyExternals()); //Set env Variables setAllEnvVarComponent(targetModel); // Deploying on vms prepareComponents(targetModel.getComponentInstances(), targetModel.getRelationshipInstances()); //Configure the components with the relationships configureWithRelationships(targetModel.getRelationshipInstances()); //configuration process at SaaS level configureSaas(targetModel.getComponentInstances().onlyInternals()); //Run puppet configureWithPuppet(targetModel.getComponentInstances().onlyInternals()); generatePuppetManifestAndConfigure(); } else { journal.log(Level.INFO, ">> Updating a deployment..."); CloudMLModelComparator diff = new CloudMLModelComparator(currentModel, targetModel); diff.compareCloudMLModel(); updateCurrentModel(diff); //Added stuff setExternalServices(new ExternalComponentInstanceGroup(diff.getAddedECs()).onlyExternals()); setAllEnvVarComponent(currentModel); prepareComponents(new ComponentInstanceGroup(diff.getAddedComponents()), targetModel.getRelationshipInstances()); configureWithRelationships(new RelationshipInstanceGroup(diff.getAddedRelationships())); configureSaas(new ComponentInstanceGroup<InternalComponentInstance>(diff.getAddedComponents())); configureWithPuppet(targetModel.getComponentInstances().onlyInternals()); generatePuppetManifestAndConfigure(); journal.log(Level.INFO, ">> All components have been added"); //removed stuff unconfigureRelationships(diff.getRemovedRelationships()); stopInternalComponents(diff.getRemovedComponents()); terminateExternalServices(diff.getRemovedECs()); journal.log(Level.INFO, ">> Adaptation completed!"); if(coordinator != null) { coordinator.ack("Adaptation completed", this.getClass().getName()); } } //start the monitoring of VMs if (statusMonitorActive) { statusMonitor.start(); } //MODAClouds specific code if(targetModel.getProperties().get("sla_url") != null && targetModel.getProperties().get("agreement_id") != null){ Boolean status=startSLA(targetModel.getProperties().get("sla_url").getValue(),targetModel.getProperties().get("agreement_id").getValue()); if(status){ journal.log(Level.INFO, ">> SLA management started"); }else{ journal.log(Level.INFO, ">> SLA management not started"); } } } private Boolean startSLA(String url, String agreementId){ URL slaUrl = null; try { slaUrl = new URL(url+"/modaclouds/"+agreementId+"/start"); HttpURLConnection httpCon = (HttpURLConnection) slaUrl.openConnection(); httpCon.setRequestMethod("PUT"); httpCon.setRequestProperty("Content-Type", "application/json"); httpCon.connect(); if(httpCon.getResponseCode() == 202){ return true; } } catch (MalformedURLException e) { journal.log(Level.SEVERE, e.getMessage()); } catch (ProtocolException e) { journal.log(Level.SEVERE, e.getMessage()); } catch (IOException e) { journal.log(Level.SEVERE, e.getMessage()); } return false; } public void reset(){ setCurrentModel(null); alreadyDeployed=new ComponentInstanceGroup<ComponentInstance<? extends Component>>(); alreadyStarted=new ComponentInstanceGroup<ComponentInstance<? extends Component>>(); } public void deploy(Deployment targetModel, CloudMLModelComparator diff){ unlessNotNull("Cannot deploy null!", targetModel); this.targetModel = targetModel; //set up the monitoring StatusConfiguration.StatusMonitorProperties statusMonitorProperties = StatusConfiguration.load(); MonitoringPlatformConfiguration.MonitoringPlatformProperties monitoringPlatformProperties = MonitoringPlatformConfiguration.load(); journal.log(Level.INFO, ">> Updating a deployment..."); //Added stuff setExternalServices(new ExternalComponentInstanceGroup(diff.getAddedECs()).onlyExternals()); setAllEnvVarComponent(targetModel); prepareComponents(new ComponentInstanceGroup(diff.getAddedComponents()), targetModel.getRelationshipInstances()); configureWithRelationships(new RelationshipInstanceGroup(diff.getAddedRelationships())); configureSaas(new ComponentInstanceGroup<InternalComponentInstance>(diff.getAddedComponents())); configureWithPuppet(targetModel.getComponentInstances().onlyInternals()); generatePuppetManifestAndConfigure(); journal.log(Level.INFO, ">> All components have been added"); //removed stuff unconfigureRelationships(diff.getRemovedRelationships()); journal.log(Level.INFO, ">> Removed relationships unconfigured"); stopInternalComponents(diff.getRemovedComponents()); journal.log(Level.INFO, ">> Removed components uninstalled"); terminateExternalServices(diff.getRemovedECs()); journal.log(Level.INFO, ">> Removed external components terminated"); journal.log(Level.INFO, ">> Adaptation completed!"); if(coordinator != null) { coordinator.ack("Adaptation completed", this.getClass().getName()); } //MODAClouds specific code if(targetModel.getProperties().get("sla_url") != null && targetModel.getProperties().get("agreement_id") != null){ Boolean status=startSLA(targetModel.getProperties().get("sla_url").getValue(),targetModel.getProperties().get("agreement_id").getValue()); if(status){ journal.log(Level.INFO, ">> SLA management started"); }else{ journal.log(Level.INFO, ">> SLA management not started"); } } } private void unlessNotNull(String message, Object... obj) { if (obj != null) { for (Object o : obj) { if (o == null) { throw new IllegalArgumentException(message); } } } else { throw new IllegalArgumentException(message); } } /** * Update the currentModel with the targetModel and preserve all the CPSM * metadata * * @param diff a model comparator */ public void updateCurrentModel(CloudMLModelComparator diff) { if (diff != null) { currentModel.getComponents().addAll(targetModel.getComponents()); currentModel.getRelationships().addAll(targetModel.getRelationships()); currentModel.getComponentInstances().removeAll(diff.getRemovedComponents()); currentModel.getRelationshipInstances().removeAll(diff.getRemovedRelationships()); currentModel.getComponentInstances().removeAll(diff.getRemovedECs().keySet()); currentModel.getExecuteInstances().removeAll(diff.getRemovedExecutes()); alreadyDeployed.removeAll(diff.getRemovedComponents()); alreadyStarted.removeAll(diff.getRemovedComponents()); currentModel.getComponentInstances().replaceAll(diff.getAddedComponents()); currentModel.getRelationshipInstances().replaceAll(diff.getAddedRelationships()); currentModel.getComponentInstances().replaceAll(diff.getAddedECs()); currentModel.getExecuteInstances().replaceAll(diff.getAddedExecutes()); } else { throw new IllegalArgumentException("Cannot update current model without comparator!"); } } /** * Prepare the components before their start. Retrieves their resources, * builds their PaaS and installs them * * @param components a list of components * @throws MalformedURLException */ private void prepareComponents(ComponentInstanceGroup<ComponentInstance<? extends Component>> components, RelationshipInstanceGroup relationships) { unlessNotNull("Cannot prepare for deployment null!", components); for (ComponentInstance<? extends Component> x : components) { if (x instanceof InternalComponentInstance) { prepareAnInternalComponent((InternalComponentInstance) x, components, relationships); } } } /** * Prepare a component before it starts. Retrieves its resources, builds * its PaaS and installs it * * @param instance an InternalComponentInstance * @param components a list of components * @throws MalformedURLException */ private void prepareAnInternalComponent(InternalComponentInstance instance, ComponentInstanceGroup<ComponentInstance<? extends Component>> components, RelationshipInstanceGroup relationships) { unlessNotNull("Cannot deploy null!", instance); Connector jc; if (!alreadyDeployed.contains(instance) && (instance.getRequiredExecutionPlatform() != null)) { ExternalComponentInstance host = instance.externalHost(); if (host.isVM()) { VMInstance ownerVM = host.asVM(); VM n = ownerVM.getType(); jc = ConnectorFactory.createIaaSConnector(n.getProvider()); executeUploadCommands(instance, ownerVM, jc); executeRetrieveCommand(instance, ownerVM, jc); alreadyDeployed.add(instance); buildPaas(instance, relationships.toList()); executeInstallCommand(instance, ownerVM, jc); coordinator.updateStatusInternalComponent(instance.getName(), State.INSTALLED.toString(), CloudAppDeployer.class.getName()); //instance.setStatus(State.INSTALLED); jc.closeConnection(); } else { // If the destination is a PaaS platform ExternalComponent ownerType = (ExternalComponent) host.getType(); Provider p = ownerType.getProvider(); PaaSConnector connector = ConnectorFactory.createPaaSConnector(p); int minRam=0; String stack = ""; if(instance.getType().hasProperty("stack")) stack = instance.getType().getProperties().valueOf("stack"); if(instance.hasProperty("stack")) stack = instance.getProperties().valueOf("stack"); if(instance.getType().hasProperty("buildpack")) stack = instance.getType().getProperties().valueOf("buildpack"); if(instance.hasProperty("buildpack")) stack = instance.getProperties().valueOf("buildpack"); if(instance.getType().hasProperty("minRAM")) minRam = Integer.parseInt(instance.getType().getProperties().valueOf("minRAM")); String url=connector.createEnvironmentWithWar( instance.getName(), instance.getName(), host.getName(), stack, minRam, instance.getType().getProperties().valueOf("warfile"), instance.getType().hasProperty("version") ? instance.getType().getProperties().valueOf("version") : "default-cloudml" ); host.setPublicAddress(url); if(instance.hasProperty("containerSize")){ String size =instance.getProperties().valueOf("containerSize"); Map<String, String> params = new HashMap<String, String>(); params.put("containerSize", size); connector.configAppParameters(instance.getName(), params); } /*for(RelationshipInstance ri: currentModel.getRelationshipInstances()){ if(ri.isRequiredBy(instance)){ if(ri.getServerComponent().isInternal()){ ExternalComponentInstance ec=ri.getServerComponent().asInternal().getHost().asExternal(); if(!ec.isVM()){ if(ec.getType().asExternal().getServiceType() == null){ connector.setEnvVar(instance.getName(), instance.getName(), url); } } } } }*/ for(InternalComponentInstance ici: host.hostedComponents()){ coordinator.updateStatusInternalComponent(ici.getName(), InternalComponentInstance.State.RUNNING.toString(), CloudAppDeployer.class.getName()); } coordinator.updateStatusInternalComponent(host.getName(), ComponentInstance.State.RUNNING.toString(), CloudAppDeployer.class.getName()); } } } /** * Execute a command either on Linux or on Windows depending on the name of the OS set up in the type * @param owner the VMInstance on which the command will be executed * @param jc a connector * @param command the command to be executed */ private void executeCommand(VMInstance owner, Connector jc, String command) { if(DEBUG){ journal.log(Level.INFO, ">> Executing command: " + command); journal.log(Level.INFO, ">> On VM: " + owner.getName()); return; } if (!command.equals("")) { if (!owner.getType().getOs().toLowerCase().contains("windows")) { jc.execCommand(owner.getId(), command, "ubuntu", owner.getType().getPrivateKey()); } else { if (command != null && !command.isEmpty()) { PowerShellConnector run = null; try { Thread.sleep(90000); // crappy stuff: wati for windows .... TODO String cmd = "powershell \"" + command + " " + owner.getType().getPrivateKey() + " " + owner.getPublicAddress() + "\""; journal.log(Level.INFO, ">> Executing command: " + cmd); run = new PowerShellConnector(cmd); journal.log(Level.INFO, ">> STDOUT: " + run.getStandardOutput()); } catch (IOException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } } } } } private void executeInstallCommand(InternalComponentInstance x, VMInstance owner, Connector jc) { unlessNotNull("Cannot install with an argument at null", x, owner, jc); for (Resource r : x.getType().getResources()) { if (!r.getInstallCommand().equals("")) { if (r.getRequireCredentials()) { jc.execCommand(owner.getId(), CloudMLQueryUtil.cloudmlStringRecover(r.getInstallCommand(), r, x) + " " + owner.getType().getProvider().getCredentials().getLogin() + " " + owner.getType().getProvider().getCredentials().getPassword(), "ubuntu", owner.getType().getPrivateKey()); } else { executeCommand(owner, jc, CloudMLQueryUtil.cloudmlStringRecover(r.getInstallCommand(), r, x)); } } } } /** * Upload resources associated to an internal component on a specified * external component * * @param x the internal component with upload commands * @param owner the external component on which the resources are about to * be uploaded * @param jc the connector used to upload */ private void executeUploadCommands(InternalComponentInstance x, VMInstance owner, Connector jc) { journal.log(Level.INFO, ">> Upload "+x.getType().getName()); unlessNotNull("Cannot upload with an argument at null", x, owner, jc); for (Resource r : x.getType().getResources()) { for (String path : r.getUploadCommand().keySet()) { jc.uploadFile(path, r.getUploadCommand().get(path), owner.getId(), "ubuntu", owner.getType().getPrivateKey()); } } } /** * Retrieve the resources associated to an InternalComponent * * @param x the internalComponent we want to retrieve the resource * @param owner the externalComponent on which the resources will be * downloaded * @param jc the connector used to trigger the commands */ private void executeRetrieveCommand(InternalComponentInstance x, VMInstance owner, Connector jc) { unlessNotNull("Cannot retrieve resources of null!", x, owner, jc); for (Resource r : x.getType().getResources()) { if (!r.getRetrieveCommand().equals("")) { if (r.getRequireCredentials()) jc.execCommand(owner.getId(), CloudMLQueryUtil.cloudmlStringRecover(r.getRetrieveCommand(), r, x) + " " + owner.getType().getProvider().getCredentials().getLogin() + "" + owner.getType().getProvider().getCredentials().getPassword(), "ubuntu", owner.getType().getPrivateKey()); else executeCommand(owner, jc, CloudMLQueryUtil.cloudmlStringRecover(r.getRetrieveCommand(), r, x)); } } } /** * Retrieve the external component on which an component should be deployed * * @param component the component who want to retrieve the destination * @return */ public ExternalComponentInstance getDestination(ComponentInstance component) { unlessNotNull("Cannot find destination of null!", component); if (component instanceof InternalComponentInstance) { InternalComponentInstance internalComponent = (InternalComponentInstance) component; return internalComponent.externalHost(); } else { return (ExternalComponentInstance) component; } } private void generatePuppetManifestAndConfigure(VMInstanceGroup group){ for(VMInstance vmi : group){ PuppetManifestGenerator pmg = new PuppetManifestGenerator(vmi, currentModel); String path=pmg.generate(); if(path != null){ managePuppet(pmg.getSkeleton(), vmi, vmi.getName(), path); } } } /** * Generate the manifest file for each VM from the manifestEntry of each puppet resource and start puppet. */ private void generatePuppetManifestAndConfigure(){ for(VMInstance vmi : currentModel.getComponentInstances().onlyVMs()){ PuppetManifestGenerator pmg = new PuppetManifestGenerator(vmi, currentModel); String path=pmg.generate(); if(path != null){ managePuppet(pmg.getSkeleton(), vmi, vmi.getName(), path); } } } /** * Install puppet, manage the repo, change the hostname and execute puppet on a VM * @param pr the puppet resource * @param n the vm instance on which puppet will be installed and executed * @param hostname the new hostname of the vm for puppet * @param path the path to the puppet manifest */ private void managePuppet(PuppetResource pr, VMInstance n, String hostname, String path){ PuppetMarionnetteConnector puppet=new PuppetMarionnetteConnector(pr.getMaster(),n); //check if the configuration file is in the repo and manage the repo MercurialConnector mc=new MercurialConnector(pr.getRepo(),pr.getRepositoryKey()); journal.log(Level.INFO, ">> Mercurial connector created"); mc.addFile(path, pr.getUsername()); //Touch the site.pp file puppet.touchSiteFile(); //call the update host command puppet.configureHostname(n.getType().getPrivateKey(), n.getType().getLogin(),n.getType().getPasswd(), n.getPublicAddress(), pr.getMaster(), hostname, pr.getConfigureHostnameCommand()); //start the puppet run puppet.install(n); } /** * For each component, execute the puppet manifest associated * @param components */ private void configureWithPuppet(ComponentInstanceGroup<InternalComponentInstance> components){ unlessNotNull("Cannot configure null!", components); Connector jc; for (InternalComponentInstance ic : components) { if(ic.externalHost().isVM()){ for(Resource r: ic.getType().getResources()){ if(r instanceof PuppetResource){ PuppetResource pr=(PuppetResource)r; if(!pr.getConfigurationFile().isEmpty()){ journal.log(Level.INFO, ">> Using Puppet to configure the following component: "+ic.getName()); VMInstance n= ic.getHost().asExternal().asVM(); Provider p = n.getType().getProvider(); managePuppet(pr,n, pr.getName(),pr.getConfigurationFile()); } } } } } } private void startExecutes(InternalComponentInstance x){ VMInstance ownerVM = x.externalHost().asVM(); //need some tests but if you need to build PaaS then it means that you want to deploy on IaaS VM n = ownerVM.getType(); Connector jc = ConnectorFactory.createIaaSConnector(n.getProvider()); ComponentInstance host = x.getHost(); if (!alreadyStarted.contains(host)) { if (host.isInternal()) { startExecutes(host.asInternal()); for (Resource r : host.getType().getResources()) { String startCommand = CloudMLQueryUtil.cloudmlStringRecover(r.getStartCommand(), r, x); start(jc, n, ownerVM, startCommand); } coordinator.updateStatusInternalComponent(host.getName(), State.RUNNING.toString(), CloudAppDeployer.class.getName()); alreadyStarted.add(host); } } jc.closeConnection(); } private void buildExecutes(InternalComponentInstance x) { VMInstance ownerVM = x.externalHost().asVM(); //need some tests but if you need to build PaaS then it means that you want to deploy on IaaS VM n = ownerVM.getType(); Connector jc; jc = ConnectorFactory.createIaaSConnector(n.getProvider()); ComponentInstance host = x.getHost(); if (!alreadyDeployed.contains(host)) { if (host.isInternal()) { buildExecutes(host.asInternal()); journal.log(Level.INFO, ">> Installing host: " + host.getName()); executeUploadCommands(host.asInternal(),ownerVM,jc); executeRetrieveCommand(host.asInternal(), ownerVM, jc); executeInstallCommand(host.asInternal(), ownerVM, jc); coordinator.updateStatusInternalComponent(host.getName(), State.INSTALLED.toString(), CloudAppDeployer.class.getName()); //host.asInternal().setStatus(State.INSTALLED); for (Resource r : host.getType().getResources()) { String configurationCommand = CloudMLQueryUtil.cloudmlStringRecover(r.getConfigureCommand(), r, x); configure(jc, n, ownerVM, configurationCommand, r.getRequireCredentials()); } coordinator.updateStatusInternalComponent(host.getName(), State.CONFIGURED.toString(), CloudAppDeployer.class.getName()); //host.asInternal().setStatus(State.CONFIGURED); for (Resource r : host.getType().getResources()) { String startCommand = CloudMLQueryUtil.cloudmlStringRecover(r.getStartCommand(), r, x); start(jc, n, ownerVM, startCommand); } coordinator.updateStatusInternalComponent(host.getName(), State.RUNNING.toString(), CloudAppDeployer.class.getName()); //host.asInternal().setStatus(State.RUNNING); alreadyStarted.add(host); alreadyDeployed.add(host); } } jc.closeConnection(); } /** * Build the paas of an component instance * * @param x An component instance * @throws MalformedURLException */ private void buildPaas(InternalComponentInstance x, List<RelationshipInstance> relationships) { unlessNotNull("Cannot deploy null", x, relationships); VMInstance ownerVM = x.externalHost().asVM(); //need some tests but if you need to build PaaS then it means that you want to deploy on IaaS VM n = ownerVM.getType(); Connector jc; jc = ConnectorFactory.createIaaSConnector(n.getProvider()); buildExecutes(x); for (RelationshipInstance bi : relationships) { if (bi.getRequiredEnd().getType().isMandatory() && x.getRequiredPorts().contains(bi.getRequiredEnd())) { final ComponentInstance<? extends Component> serverComponent = bi.getServerComponent(); if( getDestination(serverComponent).isVM()){ VMInstance owner = (VMInstance) getDestination(serverComponent); if (owner == null) { owner = ownerVM; } if (!alreadyDeployed.contains(serverComponent)) { for (Resource r : serverComponent.getType().getResources()) { executeUploadCommands(serverComponent.asInternal(),owner,jc); } for (Resource r : serverComponent.getType().getResources()) { executeRetrieveCommand(serverComponent.asInternal(),owner,jc); //executeCommand(owner, jc, CloudMLQueryUtil.cloudmlStringRecover(r.getRetrieveCommand(), r, x)); //jc.execCommand(owner.getId(), r.getRetrieveCommand(), "ubuntu", n.getPrivateKey()); } for (Resource r : serverComponent.getType().getResources()) { executeInstallCommand(serverComponent.asInternal(),owner,jc); //executeCommand(owner, jc, CloudMLQueryUtil.cloudmlStringRecover(r.getInstallCommand(), r, x)); //jc.execCommand(owner.getId(), r.getInstallCommand(), "ubuntu", n.getPrivateKey()); } if (serverComponent.isInternal()) { coordinator.updateStatusInternalComponent(serverComponent.getName(), State.INSTALLED.toString(), CloudAppDeployer.class.getName()); //serverComponent.asInternal().setStatus(State.INSTALLED); } for (Resource r : serverComponent.getType().getResources()) { String configurationCommand = r.getConfigureCommand(); configure(jc, n, owner, configurationCommand, r.getRequireCredentials()); } if (serverComponent.isInternal()) { coordinator.updateStatusInternalComponent(serverComponent.getName(), State.CONFIGURED.toString(), CloudAppDeployer.class.getName()); //serverComponent.asInternal().setStatus(State.CONFIGURED); } for (Resource r : serverComponent.getType().getResources()) { String startCommand = CloudMLQueryUtil.cloudmlStringRecover(r.getStartCommand(), r, x); start(jc, n, owner, startCommand); } if (serverComponent.isInternal()) { coordinator.updateStatusInternalComponent(serverComponent.getName(), State.RUNNING.toString(), CloudAppDeployer.class.getName()); //serverComponent.asInternal().setStatus(State.RUNNING); } alreadyStarted.add(serverComponent); alreadyDeployed.add(serverComponent); } } } } jc.closeConnection(); } /** * Configure and start SaaS components * * @param components a list of components * @throws MalformedURLException */ private void configureSaas(ComponentInstanceGroup<InternalComponentInstance> components) { unlessNotNull("Cannot configure null!", components); Connector jc; for (InternalComponentInstance x : components) { if (!alreadyStarted.contains(x)) { ExternalComponentInstance owner = x.externalHost(); if (owner instanceof VMInstance) { //TODO: refactor and be more generic for external component in general VMInstance ownerVM = (VMInstance) owner; VM n = ownerVM.getType(); jc = ConnectorFactory.createIaaSConnector(n.getProvider()); //jc=new JCloudsConnector(n.getProvider().getName(), n.getProvider().getLogin(), n.getProvider().getPasswd()); for (Resource r : x.getType().getResources()) { String configurationCommand = CloudMLQueryUtil.cloudmlStringRecover(r.getConfigureCommand(), r, x); configure(jc, n, ownerVM, configurationCommand, r.getRequireCredentials()); } coordinator.updateStatusInternalComponent(x.getName(), State.CONFIGURED.toString(), CloudAppDeployer.class.getName()); //x.setStatus(State.CONFIGURED); for (Resource r : x.getType().getResources()) { String startCommand = CloudMLQueryUtil.cloudmlStringRecover(r.getStartCommand(), r, x); start(jc, n, ownerVM, startCommand); } coordinator.updateStatusInternalComponent(x.getName(), State.RUNNING.toString(), CloudAppDeployer.class.getName()); //x.setStatus(State.RUNNING); alreadyStarted.add(x); jc.closeConnection(); } }//TODO if not InternalComponent } } /** * Configure a component * * @param jc a connector * @param n A VM type * @param ni a VM instance * @param configurationCommand the command to configure the component, * parameters are: IP IPDest portDest */ protected void configure(Connector jc, VM n, VMInstance ni, String configurationCommand, Boolean keyRequired) { if (!configurationCommand.equals("")) { if(keyRequired) jc.execCommand(ni.getId(), configurationCommand+" "+ni.getType().getProvider().getCredentials().getLogin()+" "+ni.getType().getProvider().getCredentials().getPassword(), "ubuntu", n.getPrivateKey()); else executeCommand(ni, jc, configurationCommand); } } /** * start a component * * @param jc a connector * @param n A VM type * @param ni a VM instance * @param startCommand the command to start the component */ protected void start(Connector jc, VM n, VMInstance ni, String startCommand) { unlessNotNull("Cannot start without connector", jc, n, ni, startCommand); if (!startCommand.equals("")) { executeCommand(ni, jc, startCommand); } } /** * Provision the VMs and upload the model with informations about the VM * <p/> * Added: Also deal with PaaS platforms * * @param ems A list of vms */ private void setExternalServices(ExternalComponentInstanceGroup ems) { for (ExternalComponentInstance n : ems) { if (n instanceof VMInstance) provisionAVM((VMInstance) n); else provisionAPlatform(n); } for (ExternalComponentInstance n : ems){ try{ if("loadbalancer".equals(n.getType().asExternal().getServiceType().toLowerCase())) configSubLoadBalancers(n); } catch(Exception e){ continue; } } } /** * For each load balancer instance, found the sub load balancers, and * configure the backend targets with their endpoints. * * A separate method is used and called after "provisionAPlatform" is * finished on all the external components, so that the super instances * have been properly configured. * * @param eci A load balancer instance */ private void configSubLoadBalancers(ExternalComponentInstance eci){ ExternalComponent ec = eci.getType().asExternal(); PyHrapiConnector connector = ConnectorFactory.createLoadBalancerProvider(ec.getEndPoint()); String substext = null; try{ Property p = eci.getProperties().get("subLoadBalancers"); substext = p.getValue(); } catch(NullPointerException e){ return; } String[] subs = substext.split(","); Map backend = connector.getBackEnd(eci.getName()+"Back"); for(int i = 0; i<subs.length; ++i){ String sub = subs[i].trim(); ExternalComponentInstance subEci = ((Deployment)eci.getOwner().get()) .getComponentInstances() .firstNamed(sub) .asExternal(); ExternalComponent subEc = subEci.getType().asExternal(); String subEndPoint = subEc.getEndPoint(); if(subEndPoint.startsWith("https://")) subEndPoint = subEndPoint.substring(8); if(subEndPoint.startsWith("http://")) subEndPoint = subEndPoint.substring(7); String accessPort = subEci.hasProperty("port") ? subEci.getProperties().valueOf("port") : "8080"; subEndPoint = subEndPoint.split(":")[0].trim()+":"+accessPort; //((Map)backend.get("targets")).remove("targetOneHold"); ((Map)backend.get("targets")).put( subEci.getName(), subEndPoint); } journal.log(Level.INFO, ">>Modify backend: " + connector.addPool(eci.getName()+"Back", backend)); journal.log(Level.INFO, ">>Delete Target: "+ connector.deleteTarget(eci.getName()+"Back", "targetOneHold")); connector.start(); } /** * Provision a VM * * @param n a VMInstance */ private void provisionAVM(VMInstance n) { if(DEBUG){ journal.log(Level.INFO, ">> Provision: "+n.getName()); return; } Provider p = n.getType().getProvider(); Connector jc = ConnectorFactory.createIaaSConnector(p); coordinator.updateStatus(n.getName(), ComponentInstance.State.PENDING, CloudAppDeployer.class.getName()); HashMap<String,Object> runtimeInformation = jc.createInstance(n); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } journal.log(Level.INFO, ">> Status: "+runtimeInformation.get("status")); coordinator.updateStatus(n.getName(), (ComponentInstance.State)runtimeInformation.get("status"), CloudAppDeployer.class.getName()); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } coordinator.updateIP(n.getName(),runtimeInformation.get("publicAddress").toString(),CloudAppDeployer.class.getName()); //enable the monitoring of the new machine if (statusMonitorActive) { statusMonitor.attachModule(jc); } jc.closeConnection(); } /** * Provision a platform. * So far (with only two examples of BeansTalk and CloudBees), the main PaaS * platforms are not necessary to be provisioned before deployment, so this * method is basically used to launch a DB * * @param n: an external component instance for the platform */ private void provisionAPlatform(ExternalComponentInstance n) { ExternalComponentInstance<? extends ExternalComponent> eci = (ExternalComponentInstance<? extends ExternalComponent>) n; ExternalComponent ec = eci.getType(); Provider p = eci.getType().getProvider(); PaaSConnector connector = null; if(!ec.getServiceType().toLowerCase().equals("loadbalancer")) //LoadBalancer need a special connector... connector = ConnectorFactory.createPaaSConnector(p); if (ec.getServiceType() == null) return; if (ec.getServiceType().toLowerCase().equals("database")) {//For now we use string but this will evolve to an enum connector.createDBInstance( ec.hasProperty("DB-Engine") ? ec.getProperties().valueOf("DB-Engine") : null, ec.hasProperty("DB-Version") ? ec.getProperties().valueOf("DB-Version") : null, eci.getName(), ec.hasProperty("DB-Name") ? ec.getProperties().valueOf("DB-Name") : null, ec.getLogin(), ec.getPasswd(), ec.hasProperty("allocatedSize") ? Integer.parseInt(ec.getProperties().valueOf("allocatedSize")) : 0, null, ec.hasProperty("securityGroup") ? ec.getProperties().valueOf("securityGroup") : ""); String pa=connector.getDBEndPoint(eci.getName(), 600); eci.setPublicAddress(pa); coordinator.updateIP(n.getName(),pa,CloudAppDeployer.class.getName()); coordinator.updateStatus(n.getName(), ComponentInstance.State.RUNNING, CloudAppDeployer.class.getName()); //execute the configure command /*if (!n.getType().getResources().isEmpty()) { for (Resource r : n.getType().getResources()) { if (r.getConfigureCommand() != null) { connector.restoreDB(eci.getPublicAddress(), "3306", ec.getLogin(), ec.getPasswd(), ec.hasProperty("DB-Name") ? ec.getProperties().valueOf("DB-Name") : null, r.getConfigureCommand()); } } }*/ } if (ec.getServiceType().toLowerCase().equals("messagequeue")) { String url = connector.createQueue(n.getName()); eci.setPublicAddress(url); coordinator.updateStatus(n.getName(), ComponentInstance.State.RUNNING, CloudAppDeployer.class.getName()); } if(ec.getServiceType().toLowerCase().equals("loadbalancer")){ String endpoint = ec.getEndPoint(); if(endpoint==null){ Map<String, String> env = System.getenv(); if(env.containsKey("MODACLOUDS_LOAD_BALANCER_CONTROLLER_ENDPOINT_IP") && env.containsKey("MODACLOUDS_LOAD_BALANCER_CONTROLLER_ENDPOINT_PORT")){ endpoint=env.get("MODACLOUDS_LOAD_BALANCER_CONTROLLER_ENDPOINT_IP")+":"+env.get("MODACLOUDS_LOAD_BALANCER_CONTROLLER_ENDPOINT_PORT"); } } PyHrapiConnector pConnector = ConnectorFactory.createLoadBalancerProvider(endpoint); Map<String, Object> gateway = new HashMap<String, Object>(); String GATEWAY = eci.getName()+"GateWay"; gateway.put("gateway", GATEWAY); gateway.put("protocol", "http"); gateway.put("defaultBack", eci.getName()+"Back"); Map<String, String> endpoints = new HashMap<String, String>(); String accessPort = eci.hasProperty("port") ? eci.getProperties().valueOf("port") : "8080"; endpoints.put("endOne", "0.0.0.0:"+accessPort); //TODO: Now only support one load balancer gateway.put("endpoints", endpoints); gateway.put("enable", "True"); Map<String, Object> testPool = new HashMap<String, Object>(); testPool.put("enabled", Boolean.TRUE); Map<String, String> targets = new HashMap<String, String>(); targets.put("targetOneHold","109.105.109.218:80"); testPool.put("targets", targets); journal.log(Level.INFO, ">>Add pool:" + pConnector.addPool(eci.getName() + "Back", testPool)); journal.log(Level.INFO, ">> " + pConnector.addGateway(gateway)); coordinator.updateStatus(n.getName(), ComponentInstance.State.RUNNING, CloudAppDeployer.class.getName()); } if (statusMonitorActive) { statusMonitor.attachModule(connector); } } private Map<String, String> loadbalancerTargets = new HashMap<String, String>(); //only useful for load balancer /** * Configure components according to the relationships * * @param relationships a list of relationships * @throws MalformedURLException */ protected void configureWithRelationships(RelationshipInstanceGroup relationships) { loadbalancerTargets.clear(); //Configure on the basis of the relationships //parameters transmitted to the configuration scripts are "ip ipDestination portDestination" for (RelationshipInstance bi : relationships) { ComponentInstance serveri = bi.getProvidedEnd().getOwner().get(); ComponentInstance clienti = bi.getRequiredEnd().getOwner().get(); if (serveri.isExternal() && "database".equals(((ExternalComponentInstance<ExternalComponent>) serveri).getType().getServiceType())) { //For DB for (Resource res : bi.getType().getResources()) { ConfigValet valet = ConfigValet.createValet(bi, res); if (valet != null) valet.config(); else if(res.hasProperty("db-binding-alias")){ coordinator.updateStatus(bi.getProvidedEnd().getOwner().get().getName(), ComponentInstance.State.PENDING, CloudAppDeployer.class.getName()); try{ Provider p = ((ExternalComponent) bi.getProvidedEnd().getOwner().get().getType()).getProvider(); PaaSConnector connector = ConnectorFactory.createPaaSConnector(p); String alias = res.getProperties().valueOf("db-binding-alias"); connector.bindDbToApp(bi.getRequiredEnd().getOwner().getName(), bi.getProvidedEnd().getOwner().getName(), alias); coordinator.updateStatus(bi.getProvidedEnd().getOwner().get().getName(), ComponentInstance.State.RUNNING, CloudAppDeployer.class.getName()); }catch(Exception ex){ ex.printStackTrace(); journal.log(Level.INFO, ">> db-binding only works for PaaS databases" ); } } } Component client = clienti.getType(); ComponentInstance pltfi = getDestination(clienti); if(pltfi.isExternal()){ ExternalComponent pltf = (ExternalComponent) pltfi.getType(); if(!pltf.isVM()){ if(client.hasProperty("temp-warfile")) { try { PaaSConnector connector = (PaaSConnector) ConnectorFactory.createPaaSConnector(pltf.getProvider()); connector.uploadWar(client.getProperties().valueOf("temp-warfile"), "db-reconfig", clienti.getName(), pltfi.getName(), 600); coordinator.updateStatusInternalComponent(clienti.getName(), State.RUNNING.toString(), CloudAppDeployer.class.getName()); } catch (NullPointerException e) { journal.log(Level.INFO, ">> no temp-warfile specified, no re-deploy"); } } }else{ journal.log(Level.INFO, ">> Connection IaaS to PaaS ..."); RequiredPortInstance clientInternal = bi.getRequiredEnd(); ProvidedPortInstance server = bi.getProvidedEnd(); Resource clientResource = bi.getType().getClientResource(); Connector jcClient; VMInstance ownerVMClient = (VMInstance) getDestination(clientInternal.getOwner().get()); VM VMClient = ownerVMClient.getType(); jcClient = ConnectorFactory.createIaaSConnector(VMClient.getProvider()); String destinationIpAddress = getDestination(server.getOwner().get()).getPublicAddress(); int destinationPortNumber = server.getType().getPortNumber(); String ipAddress = getDestination(clientInternal.getOwner().get()).getPublicAddress(); if(clientResource == null) return; // ignore configuration if there is no resource at all if(clientResource.getRetrieveCommand() != null && !clientResource.getRetrieveCommand().equals("")) jcClient.execCommand(ownerVMClient.getId(), clientResource.getRetrieveCommand() + " \"" + ipAddress + "\" \"" + destinationIpAddress + "\" " + destinationPortNumber, "ubuntu", VMClient.getPrivateKey()); if(clientResource.getConfigureCommand() != null && !clientResource.getConfigureCommand().equals("")){ String configurationCommand = clientResource.getConfigureCommand() + " \"" + ipAddress + "\" \"" + destinationIpAddress + "\" " + destinationPortNumber; configure(jcClient, VMClient, ownerVMClient, configurationCommand, clientResource.getRequireCredentials()); } if(clientResource.getInstallCommand() != null && !clientResource.getInstallCommand().equals("")){ String installationCommand = clientResource.getInstallCommand() + " \"" + ipAddress + "\" \"" + destinationIpAddress + "\" " + destinationPortNumber; configure(jcClient, VMClient, ownerVMClient, installationCommand, clientResource.getRequireCredentials()); } jcClient.closeConnection(); } } } else if (serveri.isExternal() && "loadbalancer".equals(((ExternalComponentInstance<ExternalComponent>) serveri).getType().getServiceType())) { //For Loadbalancer String endpoint = serveri.getType().asExternal().getEndPoint(); if(endpoint==null){ Map<String, String> env = System.getenv(); if(env.containsKey("MODACLOUDS_LOAD_BALANCER_CONTROLLER_ENDPOINT_IP") && env.containsKey("MODACLOUDS_LOAD_BALANCER_CONTROLLER_ENDPOINT_PORT")){ endpoint=env.get("MODACLOUDS_LOAD_BALANCER_CONTROLLER_ENDPOINT_IP")+":"+env.get("MODACLOUDS_LOAD_BALANCER_CONTROLLER_ENDPOINT_PORT"); } } PyHrapiConnector connector = ConnectorFactory.createLoadBalancerProvider(endpoint); String ipAddress = null; String port = null; if(clienti.isExternal()){ ExternalComponentInstance<ExternalComponent> exclienti = ((ExternalComponentInstance) clienti); ipAddress = exclienti.getPublicAddress(); port = String.valueOf(bi.getRequiredEnd().getType().getPortNumber()); //port = exserveri.getType().getProvidedPorts().toArray()[0].toString(); //TODO: always use the first provided port, should be fixed. } else{ ipAddress = getDestination(clienti).getPublicAddress(); port = String.valueOf(bi.getRequiredEnd().getType().getPortNumber()); } Map backend = connector.getBackEnd(serveri.getName()+"Back"); //((Map)backend.get("targets")).remove("targetOneHold"); ((Map)backend.get("targets")).put(clienti.getName(), ipAddress+":"+port); journal.log(Level.INFO, ">>Modify backend: "+connector.addPool(serveri.getName()+"Back", backend)); journal.log(Level.INFO, ">>Delete Target: "+connector.deleteTarget(serveri.getName()+"Back", "targetOneHold")); connector.start(); coordinator.updateStatus(serveri.getName(), ComponentInstance.State.RUNNING, CloudAppDeployer.class.getName()); } else if (bi.getRequiredEnd().getType().isRemote()) { RequiredPortInstance client = bi.getRequiredEnd(); ProvidedPortInstance server = bi.getProvidedEnd(); Resource clientResource = bi.getType().getClientResource(); Resource serverResource = bi.getType().getServerResource(); this.bi=bi; retrieveIPandConfigure(serverResource,clientResource,server,client); } if(isPaaS2PaaS(bi)) { //ComponentInstance clienti2 = bi.getRequiredEnd().getOwner().get(); ComponentInstance s=bi.getProvidedEnd().getOwner().get().asInternal(); ExternalComponentInstance serveri2 = bi.getProvidedEnd().getOwner().get().asInternal().externalHost(); ExternalComponent pltf = clienti.asInternal().externalHost().getType(); PaaSConnector connector = (PaaSConnector) ConnectorFactory.createPaaSConnector(pltf.getProvider()); connector.setEnvVar(clienti.getName(), s.getName(), serveri2.getPublicAddress()); } } } private Boolean isPaaS2PaaS(RelationshipInstance bi){ if(bi.getRequiredEnd().getOwner().get().isInternal()){ if(bi.getProvidedEnd().getOwner().get().isInternal()){ if(!bi.getRequiredEnd().getOwner().get().asInternal().externalHost().isVM() && !bi.getProvidedEnd().getOwner().get().asInternal().externalHost().isVM()){ return true; } } } return false; } private RelationshipInstance bi = null; public void retrieveIPandConfigure(Resource serverResource, Resource clientResource, PortInstance<? extends Port> server, PortInstance<? extends Port> client){ String destinationIpAddress = getDestination(server.getOwner().get()).getPublicAddress(); int destinationPortNumber = server.getType().getPortNumber(); String ipAddress = getDestination(client.getOwner().get()).getPublicAddress(); if(clientResource == null && serverResource == null) return; // ignore configuration if there is no resource at all configureWithIP(serverResource, clientResource, server, client, destinationIpAddress, ipAddress, destinationPortNumber); } private void configureWithIP(Resource server, Resource client, PortInstance<? extends Port> pserver, PortInstance<? extends Port> pclient, String destinationIpAddress, String ipAddress, int destinationPortNumber) { if(DEBUG){ journal.log(Level.INFO, ">> Configure with IP "); return; } Connector jcServer; Connector jcClient; VMInstance ownerVMServer = (VMInstance) getDestination(pserver.getOwner().get());//TODO:generalization for PaaS VM VMserver = ownerVMServer.getType(); VMInstance ownerVMClient = (VMInstance) getDestination(pclient.getOwner().get());//TODO:generalization for PaaS VM VMClient = ownerVMClient.getType(); jcServer = ConnectorFactory.createIaaSConnector(VMserver.getProvider()); jcClient = ConnectorFactory.createIaaSConnector(VMClient.getProvider()); if(server != null){ if(server.getRetrieveCommand() != null && !server.getRetrieveCommand().equals("")) jcServer.execCommand(ownerVMServer.getId(), CloudMLQueryUtil.cloudmlStringRecover(server.getRetrieveCommand(), server, bi) + " \"" + ipAddress + "\" \"" + destinationIpAddress + "\" " + destinationPortNumber, "ubuntu", VMserver.getPrivateKey()); } if(client !=null){ if(client.getRetrieveCommand() != null && !client.getRetrieveCommand().equals("")) jcClient.execCommand(ownerVMClient.getId(), CloudMLQueryUtil.cloudmlStringRecover(client.getRetrieveCommand(), client, bi) + " \"" + ipAddress + "\" \"" + destinationIpAddress + "\" " + destinationPortNumber, "ubuntu", VMClient.getPrivateKey()); } if(server != null){ if(server.getConfigureCommand() != null && !server.getConfigureCommand().equals("")){ String configurationCommand = CloudMLQueryUtil.cloudmlStringRecover(server.getConfigureCommand(), server, bi) + " \"" + ipAddress + "\" \"" + destinationIpAddress + "\" " + destinationPortNumber; configure(jcServer, VMserver, ownerVMServer, configurationCommand, server.getRequireCredentials()); } } if(client != null){ if(client.getConfigureCommand() != null && !client.getConfigureCommand().equals("")){ String configurationCommand = CloudMLQueryUtil.cloudmlStringRecover(client.getConfigureCommand(), client, bi) + " \"" + ipAddress + "\" \"" + destinationIpAddress + "\" " + destinationPortNumber; configure(jcClient, VMClient, ownerVMClient, configurationCommand, client.getRequireCredentials()); } } if(server != null){ if(server.getInstallCommand() != null && !server.getInstallCommand().equals("")){ String installationCommand = CloudMLQueryUtil.cloudmlStringRecover(server.getInstallCommand(), server, bi) + " \"" + ipAddress + "\" \"" + destinationIpAddress + "\" " + destinationPortNumber; configure(jcServer, VMserver, ownerVMServer, installationCommand, server.getRequireCredentials()); } } if(client != null){ if(client.getInstallCommand() != null && !client.getInstallCommand().equals("")){ String installationCommand = CloudMLQueryUtil.cloudmlStringRecover(client.getInstallCommand(), client, bi) + " \"" + ipAddress + "\" \"" + destinationIpAddress + "\" " + destinationPortNumber; configure(jcClient, VMClient, ownerVMClient, installationCommand, client.getRequireCredentials()); } } jcServer.closeConnection(); jcClient.closeConnection(); } /** * Configuration with parameters IP, IPDest, PortDest * * @param r resources for configuration * @param i port of the component to be CONFIGURED * @param destinationIpAddress IP of the server * @param ipAddress IP of the client * @param destinationPortNumber port of the server * @throws MalformedURLException */ private void configureWithIP(Resource r, PortInstance<? extends Port> i, String destinationIpAddress, String ipAddress, int destinationPortNumber) { if(DEBUG){ journal.log(Level.INFO, ">> Configure with IP "); return; } Connector jc; if (r != null) { VMInstance ownerVM = (VMInstance) getDestination(i.getOwner().get());//TODO:generalization for PaaS VM n = ownerVM.getType(); jc = ConnectorFactory.createIaaSConnector(n.getProvider()); //jc=new JCloudsConnector(n.getProvider().getName(), n.getProvider().getLogin(), n.getProvider().getPasswd()); jc.execCommand(ownerVM.getId(), r.getRetrieveCommand(), "ubuntu", n.getPrivateKey()); if (r.getConfigureCommand() != null) { String configurationCommand = r.getConfigureCommand() + " \"" + ipAddress + "\" \"" + destinationIpAddress + "\" " + destinationPortNumber; configure(jc, n, ownerVM, configurationCommand, r.getRequireCredentials()); } if (r.getInstallCommand() != null) { String installationCommand = r.getInstallCommand() + " \"" + ipAddress + "\" \"" + destinationIpAddress + "\" " + destinationPortNumber; configure(jc, n, ownerVM, installationCommand, r.getRequireCredentials()); } jc.closeConnection(); } } /** * Terminates a set of VMs * * @param vms A list of vmInstances * @throws MalformedURLException */ private void terminateExternalServices(Map<ExternalComponentInstance<? extends ExternalComponent>,List<InternalComponentInstance>> vms) { for (ExternalComponentInstance n : vms.keySet()) { if (n instanceof VMInstance) { terminateVM((VMInstance) n); } else{ PaaSConnector pc = ConnectorFactory.createPaaSConnector(n.getType().asExternal().getProvider()); for(InternalComponentInstance c: vms.get(n)){ journal.log(Level.INFO, ">> Terminating app "+c.asInternal().getName()); pc.deleteApp(c.asInternal().getName()); } journal.log(Level.INFO, ">> Terminated!"); } } } /** * Terminate a VM * * @param n A VM instance to be terminated * @throws MalformedURLException */ private void terminateVM(VMInstance n) { Provider p = n.getType().getProvider(); Connector jc = ConnectorFactory.createIaaSConnector(p); jc.destroyVM(n.getId()); jc.closeConnection(); coordinator.updateStatus(n.getName(), ComponentInstance.State.STOPPED, CloudAppDeployer.class.getName()); //old way without using mrt //n.setStatusAsStopped(); } /** * Stop a list of component * * @param components a list of ComponentInstance * @throws MalformedURLException */ private void stopInternalComponents(List<InternalComponentInstance> components) {//TODO: List<InternalComponentInstances> for (InternalComponentInstance a : components) { stopInternalComponent(a); } } /** * Stop a specific component instance * * @param a An InternalComponent Instance * @throws MalformedURLException */ private void stopInternalComponent(InternalComponentInstance a) { VMInstance ownerVM = (VMInstance) findDestinationWhenNoRequiredExecutionPlatformSpecified(a); //TODO: to be generalized if (ownerVM != null) { VM n = ownerVM.getType(); Connector jc = ConnectorFactory.createIaaSConnector(n.getProvider()); for (Resource r : a.getType().getResources()) { String stopCommand = r.getStopCommand(); //jc.execCommand(ownerVM.getId(), stopCommand, "ubuntu", n.getPrivateKey()); executeCommand(ownerVM, jc, stopCommand); } jc.closeConnection(); coordinator.updateStatusInternalComponent(a.getName(), State.UNINSTALLED.toString(), CloudAppDeployer.class.getName()); //a.setStatus(State.CONFIGURED); } } /** * After the deletion of a relationships the configuration parameters * specific to this relationships are removed * * @param relationships list of relationships removed */ private void unconfigureRelationships(List<RelationshipInstance> relationships) { for (RelationshipInstance b : relationships) { unconfigureRelationship(b); } } private void unconfigureRelationship(RelationshipInstance b) { if (!b.getRequiredEnd().getType().isLocal()) { RequiredPortInstance client = b.getRequiredEnd(); ProvidedPortInstance server = b.getProvidedEnd(); Resource clientResource = b.getType().getClientResource(); Resource serverResource = b.getType().getServerResource(); //client resources unconfigureWithIP(clientResource, client); //server resources unconfigureWithIP(serverResource, server); } } private void unconfigureWithIP(Resource r, PortInstance<? extends Port> i) { Connector jc; if (r != null) { VMInstance ownerVM = (VMInstance) getDestination(i.getOwner().get()); //TODO: generalize to PaaS VM n = ownerVM.getType(); jc = ConnectorFactory.createIaaSConnector(n.getProvider()); //jc=new JCloudsConnector(n.getProvider().getName(), n.getProvider().getLogin(), n.getProvider().getPasswd()); //jc.execCommand(ownerVM.getId(), r.getStopCommand(), "ubuntu", n.getPrivateKey()); executeCommand(ownerVM, jc, r.getStopCommand()); jc.closeConnection(); } } /** * To initialise a deployment Model as the model of the current system if * the system is already RUNNING * * @param current the current Deployment model */ public void setCurrentModel(Deployment current) { this.currentModel = current; Connector jc; for (VMInstance vm : currentModel.getComponentInstances().onlyVMs()) { if (vm.getPublicAddress().equals("")) { jc = ConnectorFactory.createIaaSConnector(vm.getType().getProvider()); jc.updateVMMetadata(vm); } } } /** * Find the destination of an ComponentInstance * * @param a an instance of component * @return a VMInstance */ private ExternalComponentInstance findDestinationWhenNoRequiredExecutionPlatformSpecified(InternalComponentInstance a) { if (getDestination(a) != null) { return getDestination(a); } else { for (RelationshipInstance b : currentModel.getRelationshipInstances()) { if (a.getRequiredPorts().contains(b.getRequiredEnd()) && b.getRequiredEnd().getType().isLocal()) { return getDestination(b.getProvidedEnd().getOwner().get()); } if (a.getProvidedPorts().contains(b.getProvidedEnd()) && b.getProvidedEnd().getType().isLocal()) { return getDestination(b.getRequiredEnd().getOwner().get()); } } return null; } } private void prepareSetEnv(Deployment d, InternalComponentInstance c, Property p){ String value=""; if(p.getValue().startsWith("$")){ if(p.getValue().equals("${this.host.id}")){ value=c.externalHost().asVM().getId(); } if(p.getValue().equals("${this.host.name}")){ value=c.externalHost().getName(); } if(p.getValue().equals("${this.host.type.name}")){ value=c.externalHost().getType().getName(); } if(p.getValue().equals("${this.provider.id}")){ value=c.externalHost().asVM().getType().getProvider().getName(); } if(p.getValue().equals("${this.name}") || p.getValue().equals("${this.id}")){ value=c.getName(); } if(p.getValue().equals("${this.type.name}")){ value=c.getType().getName(); } }else{ try{ JXPathContext jxpc = JXPathContext.newContext(d); Object o=jxpc.getValue(p.getValue()); value=o.toString(); }catch(NullPointerException e){ journal.log(Level.INFO, ">> Environment variable cannot be defined, xpath expression not valid"); } catch(JXPathNotFoundException e){ journal.log(Level.INFO, ">> Environment variable cannot be defined, xpath expression not valid"); } } if(!value.equals("")){ setEnvVar(c.externalHost().asVM(), p.getName().split(":")[1], value); } } public void setAllEnvVarComponent(Deployment d){ Map<String, String> env = System.getenv(); String ip=""; String port=""; if(env.containsKey("MODACLOUDS_MONITORING_MANAGER_ENDPOINT_IP") && env.containsKey("MODACLOUDS_MONITORING_MANAGER_ENDPOINT_PORT")) { ip = env.get("MODACLOUDS_MONITORING_MANAGER_ENDPOINT_IP"); port = env.get("MODACLOUDS_MONITORING_MANAGER_ENDPOINT_PORT"); }else if(env.containsKey("MODACLOUDS_TOWER4CLOUDS_MANAGER_ENDPOINT_IP") && env.containsKey("MODACLOUDS_TOWER4CLOUDS_MANAGER_ENDPOINT_PORT")){ ip = env.get("MODACLOUDS_TOWER4CLOUDS_MANAGER_ENDPOINT_IP"); port = env.get("MODACLOUDS_TOWER4CLOUDS_MANAGER_ENDPOINT_PORT"); }else if(env.containsKey("MODACLOUDS_TOWER4CLOUDS_MANAGER_PUBLIC_ENDPOINT_IP") && env.containsKey("MODACLOUDS_TOWER4CLOUDS_MANAGER_PUBLIC_ENDPOINT_PORT")){ ip = env.get("MODACLOUDS_TOWER4CLOUDS_MANAGER_PUBLIC_ENDPOINT_IP"); port = env.get("MODACLOUDS_TOWER4CLOUDS_MANAGER_PUBLIC_ENDPOINT_PORT"); }else{ try { ip= InetAddress.getLocalHost().getHostAddress(); port="8170"; } catch (UnknownHostException e) { e.printStackTrace(); } } for(VMInstance c: d.getComponentInstances().onlyVMs()){ setEnvVar(c,"MODACLOUDS_TOWER4CLOUDS_MANAGER_IP",ip); setEnvVar(c,"MODACLOUDS_TOWER4CLOUDS_MANAGER_PORT",port); } for(InternalComponentInstance c: d.getComponentInstances().onlyInternals()){ for(Property p : c.getProperties()){ if(p.getName().startsWith("env:")){ if(c.getHost().asExternal().isVM()){ prepareSetEnv(d,c,p); } } } } for(InternalComponent ic: d.getComponents().onlyInternals()){ for(Property p : ic.getProperties()){ if(p.getName().contains("env:")){ for(InternalComponentInstance ici: d.getComponentInstances().ofType(ic.getName()).onlyInternals()){ prepareSetEnv(d,ici,p); } } } } } public void setEnvVar(VMInstance vmi, String varName, String value){ if (!vmi.getType().getOs().toLowerCase().contains("windows")) { //String command="echo export "+varName+"="+value+" >> ~/.bashrc"; Connector jc = ConnectorFactory.createIaaSConnector(vmi.getType().getProvider()); //jc.execCommand(vmi.getId(), command, "ubuntu", vmi.getType().getPrivateKey()); String command3="sudo sh -c 'echo export "+varName+"="+value+" >> /etc/environment'"; jc.execCommand(vmi.getId(), command3, "ubuntu", vmi.getType().getPrivateKey()); jc.closeConnection(); } else { //TODO: should we do something for Windows as well? } } public Boolean scaleOut(VMInstance vmi){ Scaler scaler = new Scaler(currentModel, coordinator, this); if(vmi.getType().getProvider().getProperties().get("MaxVMs") != null) { int max = Integer.parseInt(vmi.getType().getProvider().getProperties().valueOf("MaxVMs")); if (nbVMFromProvider(vmi.getType().getProvider()) +1 < max) { scaler.scaleOut(vmi); }else{ if (coordinator != null) { coordinator.ack("MaxVMsReached", this.getClass().getName()); } return false; } }else{ scaler.scaleOut(vmi); } return true; } public Boolean scaleOut(VMInstance vmi, int nb){ Scaler scaler = new Scaler(currentModel, coordinator, this); if(vmi.getType().getProvider().getProperties().get("MaxVMs") != null) { int max = Integer.parseInt(vmi.getType().getProvider().getProperties().valueOf("MaxVMs")); if (nbVMFromProvider(vmi.getType().getProvider()) + nb < max) { scaler.scaleOut(vmi,nb); }else{ if (coordinator != null) { coordinator.ack("MaxVMsReached", this.getClass().getName()); } return false; } }else { scaler.scaleOut(vmi, nb); } return true; } private int nbVMFromProvider(Provider p){ int n=0; for(VMInstance v: currentModel.getComponentInstances().onlyVMs()){ if(v.getType().getProvider().equals(p)) n++; } return n; } public Boolean scaleOut(VMInstance vmi,Provider provider){ Scaler scaler = new Scaler(currentModel, coordinator, this); if(provider.getProperties().get("MaxVMs") != null) { int max = Integer.parseInt(provider.getProperties().valueOf("MaxVMs")); if (nbVMFromProvider(provider) + 1 < max) { scaler.scaleOut(vmi, provider); } else { if (coordinator != null) { coordinator.ack("MaxVMsReached", this.getClass().getName()); } return false; } }else { scaler.scaleOut(vmi,provider); } return true; } public Deployment scaleOut(ExternalComponentInstance eci,Provider provider){ Scaler scaler=new Scaler(currentModel,coordinator,this); return scaler.scaleOut(eci,provider); } public void activeDebug(){ DEBUG=true; } public void stopDebug(){ DEBUG=false; } }