Package org.nimbustools.messaging.gt4_0_elastic.v2008_05_05.rm.defaults

Source Code of org.nimbustools.messaging.gt4_0_elastic.v2008_05_05.rm.defaults.DefaultRun

/*
* Copyright 1999-2008 University of Chicago
*
* 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 org.nimbustools.messaging.gt4_0_elastic.v2008_05_05.rm.defaults;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.globus.util.Base64;
import org.nimbustools.api._repr._CreateRequest;
import org.nimbustools.api._repr._CustomizationRequest;
import org.nimbustools.api._repr.vm._NIC;
import org.nimbustools.api.brain.ModuleLocator;
import org.nimbustools.api.defaults.repr.vm.DefaultKernel;
import org.nimbustools.api.repr.Caller;
import org.nimbustools.api.repr.CannotTranslateException;
import org.nimbustools.api.repr.CreateRequest;
import org.nimbustools.api.repr.CreateResult;
import org.nimbustools.api.repr.CustomizationRequest;
import org.nimbustools.api.repr.ReprFactory;
import org.nimbustools.api.repr.vm.NIC;
import org.nimbustools.api.repr.vm.RequiredVMM;
import org.nimbustools.api.repr.vm.ResourceAllocation;
import org.nimbustools.api.repr.vm.State;
import org.nimbustools.api.repr.vm.VM;
import org.nimbustools.api.repr.vm.VMFile;
import org.nimbustools.messaging.gt4_0_elastic.generated.v2010_08_31.*;
import org.nimbustools.messaging.gt4_0_elastic.v2008_05_05.general.Networks;
import org.nimbustools.messaging.gt4_0_elastic.v2008_05_05.general.ResourceAllocations;
import org.nimbustools.messaging.gt4_0_elastic.v2008_05_05.image.Repository;
import org.nimbustools.messaging.gt4_0_elastic.v2008_05_05.rm.ContainerInterface;
import org.nimbustools.messaging.gt4_0_elastic.v2008_05_05.rm.Describe;
import org.nimbustools.messaging.gt4_0_elastic.v2008_05_05.rm.IDMappings;
import org.nimbustools.messaging.gt4_0_elastic.v2008_05_05.rm.Run;
import org.nimbustools.messaging.gt4_0_elastic.v2008_05_05.security.SSHKey;
import org.nimbustools.messaging.gt4_0_elastic.v2008_05_05.security.SSHKeys;

import java.net.URI;
import java.net.URISyntaxException;
import java.rmi.RemoteException;

public class DefaultRun implements Run {

    // -------------------------------------------------------------------------
    // STATIC VARIABLES
    // -------------------------------------------------------------------------

    private static final Log logger =
            LogFactory.getLog(DefaultRun.class.getName());
   

    // -------------------------------------------------------------------------
    // INSTANCE VARIABLES
    // -------------------------------------------------------------------------

    protected final ReprFactory repr;
    protected final ResourceAllocations RAs;
    protected final Networks networks;
    protected final Repository repository;
    protected final IDMappings ids;
    protected final ContainerInterface container;
    protected final Describe describe;
    protected final SSHKeys sshKeys;
   

    // -------------------------------------------------------------------------
    // CONSTRUCTORS
    // -------------------------------------------------------------------------

    public DefaultRun(ResourceAllocations rasImpl,
                      Networks networksImpl,
                      Repository repoImpl,
                      IDMappings idsImpl,
                      Describe describeImpl,
                      ContainerInterface containerImpl,
                      SSHKeys sshKeysImpl,
                      ModuleLocator locator) throws Exception {

        if (rasImpl == null) {
            throw new IllegalArgumentException("rasImpl may not be null");
        }
        this.RAs = rasImpl;

        if (networksImpl == null) {
            throw new IllegalArgumentException("networksImpl may not be null");
        }
        this.networks = networksImpl;

        if (repoImpl == null) {
            throw new IllegalArgumentException("repoImpl may not be null");
        }
        this.repository = repoImpl;

        if (idsImpl == null) {
            throw new IllegalArgumentException("idsImpl may not be null");
        }
        this.ids = idsImpl;

        if (describeImpl == null) {
            throw new IllegalArgumentException("describeImpl may not be null");
        }
        this.describe = describeImpl;

        if (containerImpl == null) {
            throw new IllegalArgumentException("containerImpl may not be null");
        }
        this.container = containerImpl;

        this.sshKeys = sshKeysImpl;

        if (locator == null) {
            throw new IllegalArgumentException("locator may not be null");
        }
        this.repr = locator.getReprFactory();
    }

    public DefaultRun(ResourceAllocations rasImpl,
                      Networks networksImpl,
                      Repository repoImpl,
                      IDMappings idsImpl,
                      Describe describeImpl,
                      ContainerInterface containerImpl,
                      ModuleLocator locator) throws Exception {
        this(rasImpl, networksImpl, repoImpl,
             idsImpl, describeImpl, containerImpl, null, locator);
    }

    // -------------------------------------------------------------------------
    // implements Run
    // -------------------------------------------------------------------------

    public CreateRequest translateRunInstances(RunInstancesType req,
                                               Caller caller)
            throws RemoteException, CannotTranslateException {

        final String ownerID;
        try {
            ownerID = this.container.getOwnerID(caller);
        } catch (CannotTranslateException e) {
            throw new RemoteException(e.getMessage(), e);
        }

        final String imageID = req.getImageId();
        if (imageID == null) {
            throw new RemoteException("Request is missing image ID");
        }

        // currently ignored: groupSet, placement, kernel, ramdiskid,
        // blockDeviceMapping

        final _CustomizationRequest cust;
        final String keyname = req.getKeyName();
        if (keyname != null && this.sshKeys != null) {
            cust = this.repr._newCustomizationRequest();
            final SSHKey key = this.sshKeys.findKey(ownerID, keyname);
            if (key == null) {
                throw new RemoteException("There is no key '" + keyname +
                        "' registered for you to use");
            }
            cust.setContent(key.getPubKeyValue());
            cust.setPathOnVM("/root/.ssh/authorized_keys");
        } else {
            cust = null;
        }

        final CustomizationRequest[] custRequests;
        if (cust != null) {
            custRequests = new CustomizationRequest[1];
            custRequests[0] = cust;
        } else {
            custRequests = null;
        }

        final String raType = req.getInstanceType();
        final ResourceAllocation ra = this.RAs.getMatchingRA(raType,
                                                             req.getMinCount(),
                                                             req.getMaxCount(),
                                                             false);
        final NIC[] nics = this.getNICs(ra.getPublicNetwork(), ra.getPrivateNetwork());
        final RequiredVMM reqVMM = this.RAs.getRequiredVMM();

        String userData = null;
        final UserDataType t_userData = req.getUserData();
        if (t_userData != null) {
            final String base64Encoded = t_userData.getData();
            if (base64Encoded != null) {
                // Remove newlines from the base64 string since they are not
                // supported by the Globus implementation
                final String base64EncodedNoCRLF = base64Encoded.replaceAll("[\r\n]", "");
                if (!Base64.isBase64(base64EncodedNoCRLF)) {
                    throw new RemoteException("userdata does not appear to " +
                            "be base64 encoded?");
                }
                final byte[] bytes = Base64.decode(base64EncodedNoCRLF.getBytes());
                userData = new String(bytes);
            }
        }

        final VMFile[] files =
                this.repository.constructFileRequest(imageID, ra, caller);

        final String clientToken = req.getClientToken();

        String availabilityZone = null;
        if (req.getPlacement() != null) {
            availabilityZone = req.getPlacement().getAvailabilityZone();
        }


        final _CreateRequest creq = this.repr._newCreateRequest();

        DefaultKernel kernel = null;
        String kernelRequestString = req.getKernelId();
        if (kernelRequestString != null) {
            kernel = new DefaultKernel();
            try {
                URI kernelURI = new URI("file://" + kernelRequestString);
                kernel.setKernel(kernelURI);
            } catch(URISyntaxException ueie) {
                throw new RemoteException(ueie.toString());
            }
        }

        creq.setContext(null);
        creq.setCoScheduleDone(false);
        creq.setCoScheduleID(null);
        creq.setCoScheduleMember(false);
        creq.setCustomizationRequests(custRequests);
        creq.setInitialStateRequest(State.STATE_Running);
        creq.setName(imageID);
        creq.setRequestedKernel(kernel); // todo
        creq.setRequestedNics(nics);
        creq.setRequestedRA(ra);
        creq.setRequestedSchedule(null); // ask for default
        creq.setRequiredVMM(reqVMM);
        creq.setShutdownType(CreateRequest.SHUTDOWN_TYPE_TRASH);
        creq.setVMFiles(files);
        creq.setMdUserData(userData);
        creq.setSshKeyName(keyname);
        creq.setClientToken(clientToken);
        creq.setRequestedResourcePool(availabilityZone);

        return creq;
    }

    public RunInstancesResponseType translateCreateResult(CreateResult result,
                                                     Caller caller,
                                                     String sshKeyName)
            throws Exception {

        if (result == null) {
            throw new CannotTranslateException("creation result is missing");
        }

        final VM[] vms = result.getVMs();
        if (vms == null || vms.length == 0) {
            throw new CannotTranslateException("creation result is empty?");
        }

        if (result.getCoscheduledID() != null) {
            throw new CannotTranslateException("not expecting " +
                    "coscheduling ID in any cases yet");
        }

        final String groupid = result.getGroupID();

        if (groupid == null && vms.length != 1) {
            throw new CannotTranslateException("expecting a groupID if " +
                    "more than one VM was created");
        }

        final String vmidWhenJustOne;
        final String resID;
        // these mappings may exist already, for secondary idempotent launches
        if (groupid == null) {
            vmidWhenJustOne = vms[0].getID();
            resID = this.ids.getOrNewInstanceReservationID(vmidWhenJustOne, sshKeyName);
        } else {
            vmidWhenJustOne = null;
            resID = this.ids.getOrNewGroupReservationID(groupid);
        }

        final RunningInstancesSetType rist = new RunningInstancesSetType();
        final RunningInstancesItemType[] riits =
                new RunningInstancesItemType[vms.length];

        final String msg = "New reservation ID '" + resID + "' for ";
        final StringBuffer buf = new StringBuffer(msg);
        if (vmidWhenJustOne == null) {
            buf.append("VM group '").append(groupid);
        } else {
            buf.append("single VM '").append(vmidWhenJustOne);
        }
        buf.append("'.  Members:");

        for (int i = 0; i < vms.length; i++) {
            final VM vm = vms[i];
            final String id = vm.getID();
            if (id == null) {
                throw new CannotTranslateException("VM has no ID");
            }
            final String instID;
            if (vmidWhenJustOne != null) {
                // mapping already created:
                instID = this.ids.managerInstanceToElasticInstance(vmidWhenJustOne);
            } else {
                // this mapping may exist already, for secondary idempotent launches
                instID = this.ids.getOrNewInstanceID(vm.getID(), resID, sshKeyName);
            }

            if (i != 0) {
                buf.append(",");
            }
            buf.append(" id-").append(id)
               .append("='").append(instID).append("'");

            riits[i] = this.getOneCreatedVM(vm, instID, resID, sshKeyName);
        }

        logger.info(buf.toString());

        final RunInstancesResponseType ret = new RunInstancesResponseType();
        ret.setGroupSet(getGroupStub());
        final String ownerID = this.container.getOwnerID(caller);
        if (ownerID == null) {
            throw new CannotTranslateException("Cannot find owner ID");
        }
        ret.setOwnerId(ownerID);
        ret.setReservationId(resID);
        rist.setItem(riits);
        ret.setInstancesSet(rist);
        ret.setRequesterId(ownerID);

        return ret;
    }


    // -------------------------------------------------------------------------
    // NETWORK REQUEST
    // -------------------------------------------------------------------------

    protected NIC[] getNICs(String publicNetworkName, String privateNetworkName) throws CannotTranslateException {

        // if the network mappings are the same value, that currently means
        // only make one real NIC request

        final String pubNet = this.networks.getManagerPublicNetworkName();
        final String privNet = this.networks.getManagerPrivateNetworkName();

        if (pubNet == null || privNet == null) {
            throw new CannotTranslateException("Illegal Networks " +
                    "implementation, null network mapping");
        }

        final NIC[] nics;

        /* Check that when one of public and private is set, they are both set */
        if (publicNetworkName != null && !publicNetworkName.trim().equals("")) {
            if (privateNetworkName == null || privateNetworkName.trim().equals("")) {
                throw new CannotTranslateException("Illegal Networks " +
                        "implementation, public network set but null private network mapping");
            }
        }
        if (privateNetworkName != null && !privateNetworkName.trim().equals("")) {
            if (publicNetworkName == null || publicNetworkName.trim().equals("")) {
                throw new CannotTranslateException("Illegal Networks " +
                        "implementation, private network set but null public network mapping");
            }
        }

        if (publicNetworkName != null && !publicNetworkName.trim().equals("")) {
            if (publicNetworkName.trim().equals(privateNetworkName.trim())) {
                nics = new NIC[1];
                publicNetworkName = publicNetworkName.trim();
                logger.info("Using network name " + publicNetworkName);
                nics[0] = this.oneRequestedNIC(publicNetworkName, "autoeth0");
            } else {
                nics = new NIC[2];
                publicNetworkName = publicNetworkName.trim();
                privateNetworkName = privateNetworkName.trim();
                logger.info("Using public network name " + publicNetworkName + " and private network name " + privateNetworkName);
                nics[0] = this.oneRequestedNIC(publicNetworkName, "autoeth0");
                nics[1] = this.oneRequestedNIC(privateNetworkName, "autoeth1");
            }
        }
        else if (pubNet.equals(privNet)) {
            nics = new NIC[1];
            nics[0] = this.oneRequestedNIC(pubNet, "autoeth0");
        } else {
            nics = new NIC[2];
            nics[0] = this.oneRequestedNIC(pubNet, "autoeth0");
            nics[1] = this.oneRequestedNIC(privNet, "autoeth1");
        }
        return nics;
    }

    protected NIC oneRequestedNIC(String networkName, String nicName)
            throws CannotTranslateException {
       
        if (networkName == null) {
            throw new CannotTranslateException("networkName is missing");
        }
        final _NIC nic = this.repr._newNIC();
        nic.setAcquisitionMethod(NIC.ACQUISITION_AllocateAndConfigure);
        nic.setNetworkName(networkName);
        nic.setName(nicName);
        return nic;
    }


    // -------------------------------------------------------------------------
    // RESULT
    // -------------------------------------------------------------------------

    // todo: duped code; support groups
    public static GroupSetType getGroupStub() {
        final GroupItemType[] groupItemTypes = new GroupItemType[1];
        groupItemTypes[0] = new GroupItemType("default");
        return new GroupSetType(groupItemTypes);
    }

    protected RunningInstancesItemType getOneCreatedVM(VM vm,
                                                       String instID,
                                                       String resID,
                                                       String sshKeyName)
            throws CannotTranslateException {
       
        if (instID == null) {
            throw new IllegalArgumentException("instID may not be null");
        }
        if (resID == null) {
            throw new IllegalArgumentException("resID may not be null");
        }
        if (vm == null) {
            throw new IllegalArgumentException("vm may not be null");
        }

        final RunningInstancesItemType riit = new RunningInstancesItemType();

        riit.setInstanceState(this.describe.getState(vm));
        riit.setReason(this.describe.getReason(vm));
        riit.setPlacement(this.describe.getPlacement());
        riit.setImageId(this.describe.getImageID(vm.getVMFiles()));
        riit.setInstanceType(this.describe.getInstanceType(vm));
        riit.setLaunchTime(this.describe.getLaunchTime(vm));
       

        riit.setAmiLaunchIndex("0"); // todo: could generate this here with i
        this.handleNetworking(vm, riit);
        riit.setInstanceId(instID);
        riit.setKeyName(sshKeyName);

        riit.setClientToken(vm.getClientToken());

        riit.setKernelId("default"); // todo

        riit.setMonitoring(new InstanceMonitoringStateType("disabled"));
        riit.setProductCodes(new ProductCodesSetType(new ProductCodesSetItemType[]{}));

        //riit.setRamdiskId();
        //riit.setReason();

        return riit;
    }

    protected void handleNetworking(VM vm,
                                    RunningInstancesItemType riit)
            throws CannotTranslateException {


        // ec2 only necessarily has networking information on a running
        // instance. we can loosen up requirements here.

        // this is motivated by idempotent instance support. In cases where
        // an idempotent launch maps to an already-terminated instance,
        // the VM object here will be in the terminated state and have no
        // NICs information

        final boolean isTerminated =
                vm.getState().getState().equals(State.STATE_Cancelled);

        if (isTerminated && (vm.getNics() == null || vm.getNics().length == 0)) {
            return;
        }

        final NIC[] nics = vm.getNics();
        if (nics == null || nics.length == 0) {
            // zero NICs not supported by this interface
            throw new CannotTranslateException("NICs are missing");
        }

        if (nics.length != 1 && nics.length != 2) {
            throw new CannotTranslateException("Can only handle one or two " +
                    "assigned NICs, but were given " + nics.length +
                    " for vm id-" + vm.getID());
        }

        if (nics.length == 1 && nics[0] == null) {
            throw new CannotTranslateException("NIC[] value is missing");
        }

        if (nics.length == 2 && nics[1] == null) {
            throw new CannotTranslateException("NIC[] value is missing");
        }

        final String netName = nics[0].getNetworkName();
        if (netName == null) {
            throw new CannotTranslateException("NIC in vm id-" +
                    vm.getID() + " is missing network name");
        }

        final String hostname = nics[0].getHostname();
        if (hostname == null) {
            throw new CannotTranslateException("NIC in vm id-" +
                    vm.getID() + " is missing hostname");
        }

        final String ipAddress = nics[0].getIpAddress();
        if (ipAddress == null) {
            throw new CannotTranslateException("NIC in vm id-" +
                    vm.getID() + " is missing IP address");
        }

        final String netName2;
        final String hostname2;
        final String ipAddress2;
        if (nics.length == 2) {
            netName2 = nics[1].getNetworkName();
            if (netName2 == null) {
                throw new CannotTranslateException("NIC in vm id-" +
                        vm.getID() + " is missing network name");
            }

            hostname2 = nics[1].getHostname();
            if (hostname2 == null) {
                throw new CannotTranslateException("NIC in vm id-" +
                        vm.getID() + " is missing hostname");
            }

            ipAddress2 = nics[1].getIpAddress();
            if (ipAddress2 == null) {
                throw new CannotTranslateException("NIC in vm id-" +
                        vm.getID() + " is missing IP address");
            }
        } else {
            netName2 = null;
            hostname2 = null;
            ipAddress2 = null;
        }

        String privateAssignedHostname = null;
        String publicAssignedHostname = null;
        String privateAssignedIp = null;
        String publicAssignedIp = null;

        if (netName2 != null) {
            logger.info("Using networks " + netName + " and " + netName2);
        } else {
            logger.info("Using network " + netName);
        }
        if (this.networks.isPrivateNetwork(netName)) {
            riit.setPrivateDnsName(hostname);
            riit.setPrivateIpAddress(ipAddress);
            privateAssignedHostname = hostname;
            privateAssignedIp = ipAddress;
        } else if (this.networks.isPublicNetwork(netName)) {
            riit.setDnsName(hostname);
            riit.setIpAddress(ipAddress);
            publicAssignedHostname = hostname;
            publicAssignedIp = ipAddress;
        } else {
            throw new CannotTranslateException("Unknown network was " +
                    "assigned: '" + netName + "'");
        }

        if (nics.length == 2) {
            if (this.networks.isPrivateNetwork(netName2)) {
                if (privateAssignedHostname != null) {
                    // if public and private are set to be the same, that means
                    // request ONE nic and make it appear to be two in remote
                    // interface
                    throw new CannotTranslateException("Won't support " +
                            "real NICs from duplicate networks yet");
                }
                riit.setPrivateDnsName(hostname2);
                riit.setPrivateIpAddress(ipAddress2);
                privateAssignedHostname = hostname2;
                privateAssignedIp = ipAddress2;
            } else if (this.networks.isPublicNetwork(netName2)) {
                if (publicAssignedHostname != null) {
                    // if public and private are set to be the same, that means
                    // request ONE nic and make it appear to be two in remote
                    // interface
                    throw new CannotTranslateException("Won't support " +
                            "real NICs from duplicate networks yet");
                }
                riit.setDnsName(hostname2);
                riit.setIpAddress(ipAddress2);
                publicAssignedHostname = hostname2;
                publicAssignedIp = ipAddress2;
            } else {
                throw new CannotTranslateException("Unknown network was " +
                        "assigned: '" + netName2 + "'");
            }
        }

        if (this.networks.getManagerPublicNetworkName().equals(
                this.networks.getManagerPrivateNetworkName())) {

            if (publicAssignedHostname != null && privateAssignedHostname != null) {
                // if public and private are set to be the same, that means
                // request ONE nic and make it appear to be two in remote
                // interface
                throw new CannotTranslateException("Won't support " +
                            "real NICs from duplicate networks yet");
            }

            if (publicAssignedHostname != null) {
                riit.setPrivateDnsName(publicAssignedHostname);
                riit.setPrivateIpAddress(publicAssignedIp);
            } else {
                riit.setDnsName(privateAssignedHostname);
                riit.setIpAddress(privateAssignedIp);
            }
        }
    }
}
TOP

Related Classes of org.nimbustools.messaging.gt4_0_elastic.v2008_05_05.rm.defaults.DefaultRun

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.