Package org.platformlayer.service.cloud.openstack.ops.openstack

Source Code of org.platformlayer.service.cloud.openstack.ops.openstack.OpenstackCloudContext

package org.platformlayer.service.cloud.openstack.ops.openstack;

import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException;

import javax.inject.Inject;

import org.openstack.client.OpenstackException;
import org.openstack.client.OpenstackNotFoundException;
import org.openstack.client.common.OpenstackComputeClient;
import org.openstack.client.common.OpenstackImageClient;
import org.openstack.client.compute.AsyncServerOperation;
import org.openstack.model.compute.Addresses.Network.Ip;
import org.openstack.model.compute.CreateSecurityGroupRuleRequest;
import org.openstack.model.compute.Flavor;
import org.openstack.model.compute.FloatingIp;
import org.openstack.model.compute.Image;
import org.openstack.model.compute.KeyPair;
import org.openstack.model.compute.Metadata;
import org.openstack.model.compute.SecurityGroup;
import org.openstack.model.compute.SecurityGroupRule;
import org.openstack.model.compute.Server;
import org.openstack.model.compute.ServerForCreate;
import org.platformlayer.Comparisons;
import org.platformlayer.ExceptionUtils;
import org.platformlayer.TimeoutPoll;
import org.platformlayer.TimeoutPoll.PollFunction;
import org.platformlayer.core.model.Tag;
import org.platformlayer.images.model.DiskImageRecipe;
import org.platformlayer.images.model.OperatingSystemRecipe;
import org.platformlayer.ops.MachineCreationRequest;
import org.platformlayer.ops.OpsException;
import org.platformlayer.ops.helpers.SshKeys;
import org.platformlayer.ops.images.CloudImage;
import org.platformlayer.ops.images.ImageFormat;
import org.platformlayer.ops.images.ImageStore;
import org.platformlayer.ops.instances.ImageFactory;
import org.platformlayer.ops.machines.PlatformLayerHelpers;
import org.platformlayer.service.cloud.openstack.model.OpenstackCloud;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.fathomdb.TimeSpan;
import com.fathomdb.Utf8;
import com.google.common.base.Objects;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;

public class OpenstackCloudContext {
  // implements CloudContext {
  // }

  private static final Logger log = LoggerFactory.getLogger(OpenstackCloudContext.class);

  static final String SECURITY_GROUP_PREFIX = "pl__";

  // OpenstackComputeClient openstackComputeClient;

  // public void validate() throws OpsException {
  // OpenstackComputeClient openstackComputeClient = buildOpenstackClient();
  // // Dummy call to validate information
  // try {
  // openstackComputeClient.listLimits();
  // } catch (OpenstackException e) {
  // throw new OpsException("Unable to connect to OpenStack Compute API", e);
  // }
  //
  // OpsContext opsContext = OpsContext.get();
  // OpenstackImageClient openstackImageClient = opsContext.getUserInfo().getOpenstackImageClient();
  // // Dummy call to validate information
  // try {
  // // TODO: Make this call more lightweight
  // openstackImageClient.listImages(false);
  // } catch (OpenstackException e) {
  // throw new OpsException("Unable to connect to OpenStack Image API", e);
  // }
  //
  // }

  // private OpenstackComputeConfiguration getOpenstackComputeConfiguration(UserInfo userInfo) throws
  // OpsConfigException {
  // // ComputeConfiguration computeConfig = new ComputeConfiguration();
  // // computeConfig.endpoint = config.getRequiredString("compute.url");
  // //
  // // String username = config.getRequiredString("compute.username");
  // // String secret = config.getRequiredString("compute.secret");
  // //
  // // computeConfig.awsCredentials = new BasicAWSCredentials(username, secret);
  // // return computeConfig;
  //
  // OpsConfig config = userInfo.getConfig();
  //
  // String url = config.getRequiredString("compute.os.auth");
  //
  // String username = config.getRequiredString("compute.os.username");
  // String secret = config.getRequiredString("compute.os.secret");
  // return new OpenstackComputeConfiguration(url, username, secret);
  // }

  // private OpenstackImageClient openstackImageClient;

  // public OpenstackAuthenticationClient getOpenstackAuthenticationClient(OpenstackCloud cloud) throws OpsException {
  // try {
  // OpenstackClient openstackClient = getOpenstackClient(cloud);
  // return OpenstackAuthenticationClient.loginUsingConfiguration(openstackClient);
  // } catch (OpenstackException e) {
  // throw new OpsException("Error connecting to OpenStack authentication API", e);
  // }
  // }

  public OpenstackComputeClient getComputeClient(OpenstackCloud cloud) throws OpsException {
    // OpsContext opsContext = OpsContext.get();
    //
    // OpenstackComputeClient computeClient = getOpenstackComputeClient(opsContext.getUserInfo());

    OpenstackCloudHelpers helpers = new OpenstackCloudHelpers();
    OpenstackComputeClient computeClient = helpers.buildOpenstackComputeClient(cloud);

    return computeClient;
  }

  // private AmazonEC2Client buildEc2Client() throws OpsException {
  // OpsContext opsContext = OpsContext.get();
  //
  // AmazonEC2Client amazonEC2Client = opsContext.getUserInfo().buildEc2Client();
  //
  // return amazonEC2Client;
  // }
  //
  // // // sshKeyPair = cloud.generateSshKeyPair(sshKeyName);
  // // public KeyPair generateSshKeyPair(String sshKeyName) throws OpsException {
  // // KeyPair sshKeyPair;
  // //
  // // try {
  // // // OpenStack EC2 api does not support import
  // // // // We create a new keypair each time... we don't want the user
  // // // logging in
  // // // KeyPair sshKeyPair = generateKeyPair("RSA", null);
  // //
  // // // ImportKeyPairRequest importKeyPairRequest = new
  // // // ImportKeyPairRequest();
  // // // importKeyPairRequest.setPublicKeyMaterial(publicKeyMaterial);
  // // // ImportKeyPairResult importKeyPairResult =
  // // // computeClient.importKeyPair(importKeyPairRequest);
  // // // sshKeyName = importKeyPairResult.getKeyName();
  // // AmazonEC2Client ec2Api = buildEc2Client();
  // //
  // // CreateKeyPairRequest createKeyPairRequest = new CreateKeyPairRequest(sshKeyName);
  // // CreateKeyPairResult createKeyPairResult = ec2Api.createKeyPair(createKeyPairRequest);
  // //
  // // sshKeyPair = extractKeyPair(createKeyPairResult);
  // //
  // // return sshKeyPair;
  // // } catch (AmazonClientException e) {
  // // throw new OpsException("Error building server", e);
  // // }
  // // }
  //

  public Server findServerById(OpenstackCloud cloud, String serverId) throws OpsException {
    OpenstackComputeClient computeClient = getComputeClient(cloud);

    try {
      log.info("Getting server info for: " + serverId);
      Server server = computeClient.root().servers().server(serverId).show();
      return server;
    } catch (OpenstackNotFoundException e) {
      return null;
    } catch (OpenstackException e) {
      throw new OpsException("Error getting server", e);
    }
  }

  // public OpenstackComputeMachine findMachineByInstanceKey(String instanceId) throws OpsException {
  // OpenstackComputeClient osApi = buildOpenstackClient();
  //
  // try {
  // Server server = osApi.getServerDetails(instanceId);
  // return new OpenstackComputeMachine(getSshIpAddress(server), this, server.getId());
  // } catch (OpenstackException e) {
  // throw new OpsException("Error listing servers", e);
  // }
  // }
  //
  // private String getSshIpAddress(Server server) {
  // Addresses addresses = server.getAddresses();
  // if (addresses != null) {
  // for (Network network : addresses.getNetwork()) {
  // List<Ip> ips = network.getIp();
  // if (ips == null)
  // continue;
  // for (Ip ip : ips) {
  // return ip.getAddr();
  // }
  // }
  // }
  // throw new IllegalArgumentException("Cannot determine ip address for server: " + server.getId());
  // }
  //
  // public OpenstackComputeMachine findMachine(Tag tag) throws OpsException {
  // OpenstackComputeClient osApi = buildOpenstackClient();
  //
  // try {
  // Servers servers = osApi.listServers(true);
  // for (Server server : servers.getServer()) {
  // Metadata metadata = server.getMetadata();
  // if (metadata != null) {
  // for (Meta meta : metadata.getMeta()) {
  // if (Objects.equal(tag.getKey(), meta.getKey())) {
  // if (Objects.equal(tag.getValue(), meta.getContent())) {
  // return new OpenstackComputeMachine(getSshIpAddress(server), this, server.getId());
  // }
  // }
  // }
  // }
  // }
  // return null;
  // } catch (OpenstackException e) {
  // throw new OpsException("Error listing servers", e);
  // }
  // }

  @Inject
  ImageFactory imageFactory;

  @Inject
  PlatformLayerHelpers platformLayerClient;

  public Server createInstance(OpenstackCloud cloud, String serverName, MachineCreationRequest request)
      throws OpsException {
    OpenstackComputeClient computeClient = getComputeClient(cloud);

    try {
      Image foundImage = null;

      CloudBehaviours cloudBehaviours = new CloudBehaviours(cloud);
      if (!cloudBehaviours.canUploadImages()) {
        // For now, we presume this is the HP cloud and hard-code the name
        // if (!cloudBehaviours.isHpCloud()) {
        // throw new UnsupportedOperationException();
        // }

        DiskImageRecipe recipe = null;
        if (request.recipeId != null) {
          recipe = platformLayerClient.getItem(request.recipeId, DiskImageRecipe.class);
        }

        OperatingSystemRecipe operatingSystem = null;
        if (recipe != null) {
          operatingSystem = recipe.getOperatingSystem();
        }

        log.info("Listing images to pick best image");
        Iterable<Image> images = computeClient.root().images().list();
        if (cloudBehaviours.isHpCloud()) {
          // TODO: We need a better solution here!!
          Set<String> imageNames = Sets.newHashSet("Debian Squeeze 6.0.3 Server 64-bit 20120123");
          log.warn("Hard coding image name (presuming HP cloud)");

          // TODO: Match OS
          for (Image image : images) {
            if (imageNames.contains(image.getName())) {
              foundImage = image;
              break;
            }
          }
        } else if (cloudBehaviours.isRackspaceCloud()) {
          if (operatingSystem == null) {
            operatingSystem = new OperatingSystemRecipe();
            operatingSystem.setDistribution("debian");
            operatingSystem.setVersion("squeeze");
          }

          for (Image image : images) {
            boolean matchesDistribution = false;
            boolean matchesVersion = false;

            for (Image.ImageMetadata.ImageMetadataItem item : image.getMetadata()) {
              // if (item.getKey().equals("platformlayer.org__type")) {
              // if (item.getValue().equals("base")) {
              // isMatch = true;
              // }
              // }

              if (item.getKey().equals("os_distro")) {
                if (operatingSystem != null && operatingSystem.getDistribution() != null) {
                  if (Comparisons
                      .equalsIgnoreCase(operatingSystem.getDistribution(), item.getValue())) {
                    matchesDistribution = true;
                  }
                }
              }

              if (item.getKey().equals("os_version")) {
                if (operatingSystem != null && operatingSystem.getVersion() != null) {
                  if (Comparisons.equalsIgnoreCase(operatingSystem.getVersion(), item.getValue())) {
                    matchesVersion = true;
                  } else if (Comparisons
                      .equalsIgnoreCase(operatingSystem.getDistribution(), "debian")) {

                    // Lenny is no longer getting security updates
                    // if (Strings.equalsIgnoreCase(operatingSystem.getVersion(), "lenny") &&
                    // Strings.equalsIgnoreCase(item.getValue(), "5")) {
                    // matchesVersion = true;
                    // } else

                    if (Comparisons.equalsIgnoreCase(operatingSystem.getVersion(), "squeeze")
                        && Comparisons.equalsIgnoreCase(item.getValue(), "6")) {
                      matchesVersion = true;
                    } else {
                      matchesVersion = false;
                    }
                  } else if (Comparisons
                      .equalsIgnoreCase(operatingSystem.getDistribution(), "ubuntu")) {
                    if (Comparisons.equalsIgnoreCase(operatingSystem.getVersion(), "lucid")
                        && Comparisons.equalsIgnoreCase(item.getValue(), "10.04LTS")) {
                      matchesVersion = true;
                    } else {
                      matchesVersion = false;
                    }
                  } else {
                    matchesVersion = false;
                  }
                }
              }
            }

            if (matchesDistribution && matchesVersion) {
              foundImage = image;
              break;
            }
          }
        } else {
          for (Image image : images) {
            boolean isMatch = false;

            for (Image.ImageMetadata.ImageMetadataItem item : image.getMetadata()) {
              // if (item.getKey().equals(Tag.IMAGE_TYPE)) {
              // if (item.getValue().equals("base")) {
              // isMatch = true;
              // }
              // }

              if (item.getKey().equals(Tag.IMAGE_OS_DISTRIBUTION)) {
                if (operatingSystem != null && operatingSystem.getDistribution() != null) {
                  if (!Comparisons.equalsIgnoreCase(operatingSystem.getDistribution(),
                      item.getValue())) {
                    isMatch = false;
                  }
                }
              }

              if (item.getKey().equals(Tag.IMAGE_OS_VERSION)) {
                if (operatingSystem != null && operatingSystem.getVersion() != null) {
                  if (!Comparisons.equalsIgnoreCase(operatingSystem.getVersion(), item.getValue())) {
                    isMatch = false;
                  }
                }
              }
            }

            if (isMatch) {
              foundImage = image;
              break;
            }
          }
        }

        if (foundImage == null) {
          throw new IllegalArgumentException("Could not find image");
        }
      } else {
        List<ImageFormat> formats = Collections.singletonList(ImageFormat.DiskQcow2);
        CloudImage image = imageFactory.getOrCreateImageId(cloud, formats, request.recipeId);

        String imageId = image.getId();
        log.info("Getting image details for image: " + imageId);
        foundImage = computeClient.root().images().image(imageId).show();
        if (foundImage == null) {
          throw new IllegalArgumentException("Could not find image: " + imageId);
        }
      }

      SecurityGroup createdSecurityGroup = null;
      if (cloudBehaviours.supportsSecurityGroups()) {
        SecurityGroup createTemplate = new SecurityGroup();
        createTemplate.setName(SECURITY_GROUP_PREFIX + serverName);
        createTemplate.setDescription("Security group for instance: " + serverName);
        try {
          log.info("Creating security group: " + createTemplate.getName());
          createdSecurityGroup = computeClient.root().securityGroups().create(createTemplate);
        } catch (OpenstackException e) {
          for (SecurityGroup candidate : computeClient.root().securityGroups().list()) {
            if (Objects.equal(candidate.getName(), createTemplate.getName())) {
              createdSecurityGroup = candidate;
              break;
            }
          }

          if (createdSecurityGroup != null) {
            // Ignore
            log.warn("Ignoring 'security group already exists' error: " + e.getMessage());
          } else {
            throw new OpsException("Error creating security group", e);
          }
        }
        {
          CreateSecurityGroupRuleRequest newRule = new CreateSecurityGroupRuleRequest();
          newRule.setCidr("0.0.0.0/0");
          newRule.setFromPort(22);
          newRule.setToPort(22);
          newRule.setIpProtocol("tcp");
          newRule.setParentGroupId(createdSecurityGroup.getId());

          try {
            log.info("Creating security group rule for port: " + newRule.getToPort());
            SecurityGroupRule createdRule = computeClient.root().securityGroupRules().create(newRule);
          } catch (OpenstackException e) {
            String message = e.getMessage();
            if (message != null && message.contains("This rule already exists")) {
              log.warn("Ignoring 'rule already exists': " + e.getMessage());
            } else {
              throw new OpsException("Error creating security group access", e);
            }
          }
        }
      }

      AsyncServerOperation createServerOperation;
      {
        ServerForCreate create = new ServerForCreate();

        create.setName(serverName);

        if (request.sshPublicKey != null) {
          if (cloudBehaviours.supportsPublicKeys()) {
            OpenstackCloudHelpers cloudHelpers = new OpenstackCloudHelpers();
            KeyPair keyPair = cloudHelpers.ensurePublicKeyUploaded(computeClient, request.sshPublicKeyName,
                request.sshPublicKey);
            create.setKeyName(keyPair.getName());
          } else if (cloudBehaviours.supportsFileInjection()) {
            String fileContents = SshKeys.serialize(request.sshPublicKey);
            create.addUploadFile("/root/.ssh/authorized_keys", Utf8.getBytes(fileContents));
          } else {
            throw new OpsException("No supported SSH key mechanism on cloud");
          }
        }

        create.setImageRef(foundImage.getId());

        Flavor flavor = getClosestInstanceType(computeClient, request);
        if (flavor == null) {
          throw new OpsException("Cannot determine instance type for request");
        }
        create.setFlavorRef(flavor.getId());

        if (request.securityGroups != null) {
          // TODO: Reimplement if needed
          throw new UnsupportedOperationException();
        }

        if (createdSecurityGroup != null) {
          ServerForCreate.SecurityGroup serverSecurityGroup = new ServerForCreate.SecurityGroup();
          serverSecurityGroup.setName(createdSecurityGroup.getName());
          create.getSecurityGroups().add(serverSecurityGroup);
        }

        create.setConfigDrive(cloudBehaviours.useConfigDrive());

        log.info("Launching new server: " + create.getName());
        createServerOperation = computeClient.createServer(create);
      }

      log.info("Waiting for server to be ready");
      Server server = createServerOperation.waitComplete();
      Server instanceInfo = null;
      String stateName = null;
      while (true) {
        instanceInfo = getInstanceInfo(computeClient, server.getId());

        stateName = instanceInfo.getStatus();
        log.info("Instance state: " + stateName);

        // if (stateName.equals("scheduling")) {
        // continue;
        // }
        //
        if (stateName.equals("BUILD")) {
          break;
        }

        // if (stateName.equals("shutdown")) {
        // break;
        // }

        if (stateName.equals("ACTIVE")) {
          break;
        }

        Thread.sleep(1000);
      }

      // OpenstackComputeMachine machine = new OpenstackComputeMachine(instanceInfo.getAccessIPv4(), this,
      // server.getId());

      // Even if the machine is in 'error' state, we still want to associate it with us
      if (request.tags != null) {
        Server newServerInfo = new Server();
        Metadata metadata = new Metadata();
        for (Tag tag : request.tags) {
          Metadata.Item meta = new Metadata.Item();
          meta.setKey(tag.getKey());
          meta.setValue(tag.getValue());
          metadata.getItems().add(meta);
        }

        newServerInfo.setMetadata(metadata);
        log.info("Tagging server: " + server.getId());
        computeClient.root().servers().server(server.getId()).update(newServerInfo);
      }

      return server;
    } catch (InterruptedException e) {
      ExceptionUtils.handleInterrupted(e);
      throw new OpsException("Error building server", e);
    } catch (OpenstackException e) {
      throw new OpsException("Error building server", e);
    }
  }

  private Flavor getClosestInstanceType(OpenstackComputeClient computeClient, MachineCreationRequest request)
      throws OpenstackException {
    log.info("Listing image sizes to find best size");

    Iterable<Flavor> flavors = computeClient.root().flavors().list();
    List<Flavor> candidates = Lists.newArrayList();
    for (Flavor flavor : flavors) {
      int instanceMemoryMB = flavor.getRam();
      if (request.minimumMemoryMB > instanceMemoryMB) {
        continue;
      }

      candidates.add(flavor);
    }

    Flavor bestFlavor = findCheapest(candidates);
    if (bestFlavor == null) {
      return null;
    }

    return bestFlavor;
  }

  private Flavor findCheapest(List<Flavor> candidates) {
    Flavor bestFlavor = null;
    float bestPrice = Float.MAX_VALUE;

    for (Flavor candidate : candidates) {
      float price = computePrice(candidate);
      if (price < bestPrice) {
        bestFlavor = candidate;
        bestPrice = price;
      }
    }
    return bestFlavor;
  }

  private float computePrice(Flavor flavor) {
    // We compute a synthetic per-hour price so we can choose the smallest/cheapest instance size

    float price = 0;

    // RAM is $0.10 / hour / GB
    int ram = flavor.getRam();
    price += (0.10 / 1024.0) * ram;

    // Disk is $0.10 / hour / TB
    int disk = flavor.getDisk();
    price += (0.10 / 1024.0) * disk;

    // CPUs are $0.10 / hour / vCPU
    int cpus = flavor.getVcpus();
    price += 0.10 * cpus;

    return price;
  }

  // public void ensureCreatedSecurityGroups(List<String> securityGroups) throws OpsException {
  // for (String securityGroup : securityGroups) {
  // ensureCreatedSecurityGroup(securityGroup);
  // }
  // }
  //
  // public void ensureCreatedSecurityGroup(String securityGroup) throws OpsException {
  // AmazonEC2Client ec2Api = buildEc2Client();
  //
  // CreateSecurityGroupRequest createSecurityGroupRequest = new CreateSecurityGroupRequest();
  // createSecurityGroupRequest.setGroupName(securityGroup);
  // createSecurityGroupRequest.setDescription(securityGroup);
  // try {
  // ec2Api.createSecurityGroup(createSecurityGroupRequest);
  // } catch (AmazonClientException e) {
  // String message = getEc2ErrorMessage(e);
  //
  // if (message != null && message.endsWith("already exists")) {
  // log.info("Security group already exists: " + securityGroup);
  // return;
  // }
  //
  // throw new OpsException("Error creating security group", e);
  // }
  // }
  //
  // public void ensurePortOpen(String securityGroup, String protocol, int destPort) throws OpsException {
  // AmazonEC2Client ec2Api = buildEc2Client();
  //
  // List<IpPermission> ipPermissions = Lists.newArrayList();
  //
  // IpPermission ipPermission = new IpPermission();
  // ipPermission.setFromPort(destPort);
  // ipPermission.setToPort(destPort);
  // ipPermission.setIpProtocol(protocol);
  // List<String> ipRanges = Lists.newArrayList();
  // ipRanges.add("0.0.0.0/0");
  // ipPermission.setIpRanges(ipRanges);
  //
  // ipPermissions.add(ipPermission);
  // AuthorizeSecurityGroupIngressRequest request = new AuthorizeSecurityGroupIngressRequest(securityGroup,
  // ipPermissions);
  // try {
  // ec2Api.authorizeSecurityGroupIngress(request);
  // } catch (AmazonClientException e) {
  // String message = getEc2ErrorMessage(e);
  //
  // if (message != null && message.endsWith("rule already exists in group")) {
  // log.info("Firewall rule already exists: " + securityGroup);
  // return;
  // }
  //
  // throw new OpsException("Error creating firewall rule", e);
  // }
  // }
  //
  // private String getEc2ErrorMessage(AmazonClientException e) {
  // if (e instanceof AmazonServiceException) {
  // AmazonServiceException amazonServiceException = (AmazonServiceException) e;
  // String message = amazonServiceException.getMessage();
  // if (message != null) {
  // message = message.trim();
  // return message;
  // }
  // }
  // return null;
  // }
  //
  // private String getOpenstackInstanceId(Instance instanceInfo) {
  // String ec2InstanceId = instanceInfo.getInstanceId();
  // if (!ec2InstanceId.startsWith("i-")) {
  // throw new IllegalArgumentException("Invalid instance id: " + ec2InstanceId);
  // }
  // ec2InstanceId = ec2InstanceId.substring(2);
  // Long osInstanceId = Long.parseLong(ec2InstanceId, 16);
  // return osInstanceId.toString();
  // }
  //
  // private com.amazonaws.services.ec2.model.Image mapToEc2Image(OpenstackComputeClient osApi, AmazonEC2Client
  // ec2Api, Image osImage) {
  // DescribeImagesResult ec2Images = ec2Api.describeImages();
  //
  // // String imageId = String.format("ami-%08X", Long.parseLong(osImage.getId()));
  // // for (com.amazonaws.services.ec2.model.Image ec2Image : ec2Images.getImages()) {
  // // if (imageId.equalsIgnoreCase(ec2Image.getImageId())) {
  // // return ec2Image;
  // // }
  // // }
  //
  // String imageName = "None (" + osImage.getName() + ")";
  // for (com.amazonaws.services.ec2.model.Image ec2Image : ec2Images.getImages()) {
  // if (imageName.equalsIgnoreCase(ec2Image.getImageLocation())) {
  // return ec2Image;
  // }
  // }
  //
  // return null;
  // }
  //
  // private KeyPair extractKeyPair(CreateKeyPairResult createKeyPairResult) throws OpsException {
  // String pemKeyMaterial = createKeyPairResult.getKeyPair().getKeyMaterial();
  // PEMReader r = new PEMReader(new StringReader(pemKeyMaterial));
  // try {
  // return (KeyPair) r.readObject();
  // } catch (IOException ex) {
  // throw new OpsException("Error decoding generated SSH key", ex);
  // } finally {
  // IoUtils.safeClose(r);
  // }
  // }
  //
  // private static Instance getInstanceInfo(AmazonEC2Client client, String instanceId) throws AmazonServiceException,
  // AmazonClientException {
  // DescribeInstancesRequest describeInstancesRequest = new DescribeInstancesRequest();
  // describeInstancesRequest.setInstanceIds(Collections.singleton(instanceId));
  // DescribeInstancesResult describeInstancesResult = client.describeInstances(describeInstancesRequest);
  // Instance instanceInfo = describeInstancesResult.getReservations().get(0).getInstances().get(0);
  // return instanceInfo;
  // }

  private static Server getInstanceInfo(OpenstackComputeClient computeClient, String serverId)
      throws OpenstackException {
    Server serverDetails = computeClient.root().servers().server(serverId).show();
    return serverDetails;
  }

  public void terminateInstance(OpenstackComputeMachine machine) throws OpsException {
    terminateInstance(machine.getCloud(), machine.getOpenstackServerId());
  }

  public AsyncServerOperation terminateInstance(OpenstackCloud cloud, String instanceId) throws OpsException {
    try {
      OpenstackComputeClient computeClient = getComputeClient(cloud);

      log.info("Terminating server: " + instanceId);
      AsyncServerOperation deleteOperation = computeClient.deleteServer(instanceId);
      return deleteOperation;
    } catch (OpenstackNotFoundException e) {
      log.info("Could not find instance to be terminated, assuming already terminated: " + instanceId);
      return null;
    } catch (OpenstackException e) {
      throw new OpsException("Error terminating server", e);
    }
  }

  public ImageStore getImageStore(OpenstackCloud cloud) throws OpsException {
    OpenstackCloudHelpers helpers = new OpenstackCloudHelpers();
    OpenstackImageClient openstackImageClient = helpers.buildOpenstackImageClient(cloud);

    return new GlanceImageStore(openstackImageClient);
  }

  public Server ensureHasPublicIp(final OpenstackCloud cloud, Server server) throws OpsException {
    final OpenstackCloudHelpers helpers = new OpenstackCloudHelpers();

    List<Ip> publicIps = helpers.findPublicIps(cloud, server);

    if (!publicIps.isEmpty()) {
      return server;
    }

    final OpenstackComputeClient compute = getComputeClient(cloud);

    log.info("Creating floating IP");
    FloatingIp floatingIp = compute.root().floatingIps().create();

    // TODO: Don't abandon the IP e.g. if the attach fails
    log.info("Attching floating IP " + floatingIp.getIp() + " to " + server.getId());
    compute.root().servers().server(server.getId()).addFloatingIp(floatingIp.getIp());

    final String serverId = server.getId();

    try {
      server = TimeoutPoll.poll(TimeSpan.FIVE_MINUTES, TimeSpan.TEN_SECONDS, new PollFunction<Server>() {
        @Override
        public Server call() throws Exception {
          log.info("Waiting for floating IP attach; polling server: " + serverId);
          Server server = compute.root().servers().server(serverId).show();

          List<Ip> publicIps = helpers.findPublicIps(cloud, server);
          if (publicIps.isEmpty()) {
            return null;
          }
          return server;
        }
      });
    } catch (TimeoutException e) {
      throw new OpsException("Timeout while waiting for attached public IP to show up", e);
    } catch (ExecutionException e) {
      throw new OpsException("Error while waiting for attached public IP to show up", e);
    }

    return server;
  }

  public AsyncServerOperation ensurePoweredOn(OpenstackCloud cloud, Server server) throws OpsException {
    String status = server.getStatus();
    if (Objects.equal(status, "SHUTOFF")) {
      try {
        OpenstackComputeClient computeClient = getComputeClient(cloud);

        String serverId = server.getId();
        log.info("Starting SHUTOFF server: " + serverId);

        AsyncServerOperation powerOnOperation = computeClient.powerServerOn(serverId);
        return powerOnOperation;
      } catch (OpenstackException e) {
        throw new OpsException("Error powering server on", e);
      }
    }

    return null;
  }

  // @Override
  // public Machine refreshMachine(Machine machine) throws OpsException {
  // throw new UnsupportedOperationException();
  // }
  //
  // // public String getState(String instanceId) throws OpsException {
  // // OpenstackComputeClient osApi = buildOpenstackClient();
  // // Server server;
  // // try {
  // // server = osApi.getServerDetails(instanceId);
  // // } catch (OpenstackException e) {
  // // throw new OpsException("Error getting instance info", e);
  // // }
  // // if (server == null)
  // // throw new OpsException("Instance not found: " + instanceId);
  // // return server.getStatus();
  // // }
  //
  // // public DescribeInstancesResult describeInstances() throws OpsException {
  // // DescribeInstancesRequest request = new DescribeInstancesRequest();
  // // try {
  // // return buildOpenstackClient().describeInstances(request);
  // // } catch (AmazonClientException e) {
  // // throw new OpsException("Error terminating server", e);
  // // }
  // // }
  //

  public static AsyncServerOperation wrapServerCreate(OpenstackComputeClient client, Server server)
      throws OpenstackException {
    return new AsyncServerOperation(client, server, server.getId(), Lists.newArrayList("BUILD"),
        Lists.newArrayList("ACTIVE"));
  }

}
TOP

Related Classes of org.platformlayer.service.cloud.openstack.ops.openstack.OpenstackCloudContext

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.