Beispiel #1
0
  @Override
  public boolean isValidZone(String region, String zone) throws InvalidZoneException {
    IaasProvider iaasInfo = getIaasProvider();
    if (zone == null || iaasInfo == null) {
      String msg = "Zone or IaaSProvider is null: zone: " + zone + " - IaaSProvider: " + iaasInfo;
      log.error(msg);
      throw new InvalidZoneException(msg);
    }
    ComputeServiceContext context = iaasInfo.getComputeService().getContext();
    AvailabilityZoneAndRegionApi zoneRegionApi =
        context.unwrapApi(AWSEC2Api.class).getAvailabilityZoneAndRegionApiForRegion(region).get();

    Set<AvailabilityZoneInfo> availabilityZones =
        zoneRegionApi.describeAvailabilityZonesInRegion(region);
    for (AvailabilityZoneInfo zoneInfo : availabilityZones) {
      String configuredZone = zoneInfo.getZone();
      if (zone.equalsIgnoreCase(configuredZone)) {
        if (log.isDebugEnabled()) {
          log.debug("Found a matching zone: " + zone);
        }
        return true;
      }
    }

    String msg =
        "Invalid zone: "
            + zone
            + " in the region: "
            + region
            + " and of the iaas: "
            + iaasInfo.getType();
    log.error(msg);
    throw new InvalidZoneException(msg);
  }
Beispiel #2
0
 @Override
 public void deleteVolume(String volumeId) {
   IaasProvider iaasInfo = getIaasProvider();
   ComputeServiceContext context = iaasInfo.getComputeService().getContext();
   String region = ComputeServiceBuilderUtil.extractRegion(iaasInfo);
   if (region == null) {
     log.fatal(
         "Cannot delete the volume [id]: "
             + volumeId
             + " of the [region] : "
             + region
             + " of Iaas : "
             + iaasInfo);
     return;
   }
   ElasticBlockStoreApi blockStoreApi =
       context.unwrapApi(AWSEC2Api.class).getElasticBlockStoreApiForRegion(region).get();
   blockStoreApi.deleteVolumeInRegion(region, volumeId);
   log.info(
       "Deletion of Volume [id]: "
           + volumeId
           + " was successful. [region] : "
           + region
           + " of Iaas : "
           + iaasInfo);
 }
Beispiel #3
0
 @Override
 public void setDynamicPayload(byte[] payload) {
   IaasProvider iaasProvider = getIaasProvider();
   if (iaasProvider.getTemplate() != null) {
     iaasProvider.getTemplate().getOptions().as(AWSEC2TemplateOptions.class).userData(payload);
   }
 }
Beispiel #4
0
  @Override
  public String createVolume(int sizeGB, String snapshotId) {
    IaasProvider iaasInfo = getIaasProvider();

    ComputeServiceContext context = iaasInfo.getComputeService().getContext();

    String region = ComputeServiceBuilderUtil.extractRegion(iaasInfo);
    String zone = ComputeServiceBuilderUtil.extractZone(iaasInfo);

    if (region == null || zone == null) {
      log.fatal(
          "Cannot create a new volume in the [region] : "
              + region
              + ", [zone] : "
              + zone
              + " of Iaas : "
              + iaasInfo);
      return null;
    }

    ElasticBlockStoreApi blockStoreApi =
        context.unwrapApi(AWSEC2Api.class).getElasticBlockStoreApiForRegion(region).get();

    Volume volume;
    if (StringUtils.isEmpty(snapshotId)) {
      if (log.isDebugEnabled()) {
        log.info("Creating a volume in the zone " + zone);
      }
      volume = blockStoreApi.createVolumeInAvailabilityZone(zone, sizeGB);
    } else {
      if (log.isDebugEnabled()) {
        log.info("Creating a volume in the zone " + zone + " from the shanpshot " + snapshotId);
      }
      volume = blockStoreApi.createVolumeFromSnapshotInAvailabilityZone(zone, snapshotId);
    }

    if (volume == null) {
      log.fatal(
          "Volume creation was unsuccessful. [region] : "
              + region
              + ", [zone] : "
              + zone
              + " of Iaas : "
              + iaasInfo);
      return null;
    }

    log.info(
        "Successfully created a new volume [id]: "
            + volume.getId()
            + " in [region] : "
            + region
            + ", [zone] : "
            + zone
            + " of Iaas : "
            + iaasInfo);
    return volume.getId();
  }
Beispiel #5
0
  @Override
  public synchronized void releaseAddress(String ip) {

    IaasProvider iaasInfo = getIaasProvider();

    ComputeServiceContext context = iaasInfo.getComputeService().getContext();
    ElasticIPAddressApi elasticIPAddressApi =
        context.unwrapApi(AWSEC2Api.class).getElasticIPAddressApi().get();
    String region = ComputeServiceBuilderUtil.extractRegion(iaasInfo);

    elasticIPAddressApi.disassociateAddressInRegion(region, ip);
    elasticIPAddressApi.releaseAddressInRegion(region, ip);
  }
Beispiel #6
0
  @Override
  public boolean isValidHost(String zone, String host) throws InvalidHostException {
    IaasProvider iaasInfo = getIaasProvider();

    // there's no such concept in EC2
    String msg =
        "Invalid host: "
            + host
            + " in the zone: "
            + zone
            + " and of the iaas: "
            + iaasInfo.getType();
    log.error(msg);
    throw new InvalidHostException(msg);
  }
Beispiel #7
0
  @Override
  public void detachVolume(String instanceId, String volumeId) {
    IaasProvider iaasInfo = getIaasProvider();
    ComputeServiceContext context = iaasInfo.getComputeService().getContext();
    String region = ComputeServiceBuilderUtil.extractRegion(iaasInfo);
    if (region == null) {
      log.fatal(
          "Cannot detach the volume [id]: "
              + volumeId
              + " from the instance [id]: "
              + instanceId
              + " of the [region] : "
              + region
              + " of Iaas : "
              + iaasInfo);
      return;
    }

    ElasticBlockStoreApi blockStoreApi =
        context.unwrapApi(AWSEC2Api.class).getElasticBlockStoreApiForRegion(region).get();
    Set<Volume> volumeDescriptions = blockStoreApi.describeVolumesInRegion(region, volumeId);
    Iterator<Volume> it = volumeDescriptions.iterator();

    while (it.hasNext()) {
      Volume.Status status = it.next().getStatus();
      if (status == Volume.Status.AVAILABLE) {
        log.warn(
            String.format(
                "Volume %s is already in AVAILABLE state. Volume seems to be detached somehow",
                volumeId));
        return;
      }
    }
    blockStoreApi.detachVolumeInRegion(
        region, volumeId, true, DetachVolumeOptions.Builder.fromInstance(instanceId));

    log.info(
        "Detachment of Volume [id]: "
            + volumeId
            + " from instance [id]: "
            + instanceId
            + " was successful. [region] : "
            + region
            + " of Iaas : "
            + iaasInfo);
  }
Beispiel #8
0
 @Override
 public synchronized boolean createKeyPairFromPublicKey(
     String region, String keyPairName, String publicKey) {
   IaasProvider iaasInfo = getIaasProvider();
   String ec2Msg = " ec2. Region: " + region + " - Key Pair Name: ";
   ComputeServiceContext context = iaasInfo.getComputeService().getContext();
   AWSKeyPairApi keyPairApi =
       context.unwrapApi(AWSEC2Api.class).getKeyPairApiForRegion(region).get();
   KeyPair keyPair = keyPairApi.importKeyPairInRegion(region, keyPairName, publicKey);
   if (keyPair != null) {
     iaasInfo
         .getTemplate()
         .getOptions()
         .as(AWSEC2TemplateOptions.class)
         .keyPair(keyPair.getKeyName());
     log.info(SUCCESSFUL_LOG_LINE + ec2Msg + keyPair.getKeyName());
     return true;
   }
   log.error(FAILED_LOG_LINE + ec2Msg);
   return false;
 }
Beispiel #9
0
  @Override
  public boolean isValidRegion(String region) throws InvalidRegionException {
    IaasProvider iaasInfo = getIaasProvider();
    if (region == null || iaasInfo == null) {
      String msg =
          "Region or IaaSProvider is null: region: " + region + " - IaaSProvider: " + iaasInfo;
      log.error(msg);
      throw new InvalidRegionException(msg);
    }

    ComputeServiceContext context = iaasInfo.getComputeService().getContext();
    Set<String> regions = context.unwrapApi(AWSEC2Api.class).getConfiguredRegions();
    for (String configuredRegion : regions) {
      if (region.equalsIgnoreCase(configuredRegion)) {
        if (log.isDebugEnabled()) {
          log.debug("Found a matching region: " + region);
        }
        return true;
      }
    }
    String msg = "Invalid region: " + region + " in the iaas: " + iaasInfo.getType();
    log.error(msg);
    throw new InvalidRegionException(msg);
  }
  @Override
  public void releaseAddress(String ip) {

    ComputeServiceContext context = iaasProvider.getComputeService().getContext();
    String region = ComputeServiceBuilderUtil.extractRegion(iaasProvider);

    NovaApi novaApi = context.unwrapApi(NovaApi.class);
    FloatingIPApi floatingIPApi = novaApi.getFloatingIPExtensionForZone(region).get();

    for (FloatingIP floatingIP : floatingIPApi.list()) {
      if (floatingIP.getIp().equals(ip)) {
        floatingIPApi.delete(floatingIP.getId());
        break;
      }
    }
  }
  private void buildNeutronApi() {

    String iaasProviderNullMsg = "IaasProvider is null. Unable to build neutron API";
    assertNotNull(iaasProvider, iaasProviderNullMsg);

    String region = ComputeServiceBuilderUtil.extractRegion(iaasProvider);
    String regionNullOrEmptyErrorMsg =
        String.format(
            "Region is not set. Unable to build neutron API for the iaas provider %s",
            iaasProvider.getProvider());
    assertNotNullAndNotEmpty(region, regionNullOrEmptyErrorMsg);

    String endpoint = iaasProvider.getProperty(CloudControllerConstants.JCLOUDS_ENDPOINT);
    String endpointNullOrEmptyErrorMsg =
        String.format(
            "Endpoint is not set. Unable to build neutorn API for the iaas provider %s",
            iaasProvider.getProvider());
    assertNotNullAndNotEmpty(endpoint, endpointNullOrEmptyErrorMsg);

    Iterable<Module> modules = ImmutableSet.<Module>of(new SLF4JLoggingModule());

    try {
      this.neutronApi =
          ContextBuilder.newBuilder(provider)
              .credentials(iaasProvider.getIdentity(), iaasProvider.getCredential())
              .endpoint(endpoint)
              .modules(modules)
              .buildApi(NeutronApi.class);
    } catch (Exception e) {
      String msg =
          String.format(
              "Unable to build neutron API for [provider=%s, identity=%s, credential=%s, endpoint=%s]",
              provider, iaasProvider.getIdentity(), iaasProvider.getCredential(), endpoint);
      log.error(msg, e);
      throw new CloudControllerException(msg, e);
    }

    this.portApi = neutronApi.getPortApi(region);
    String portApiNullOrEmptyErrorMessage =
        String.format("Unable to get port Api from neutron Api for region ", region);
    assertNotNull(portApi, portApiNullOrEmptyErrorMessage);

    this.floatingIPApi = neutronApi.getFloatingIPApi(region).get();
    String floatingIPApiNullOrEmptyErrorMessage =
        String.format("Unable to get floatingIP Api from neutron Api for region ", region);
    assertNotNull(floatingIPApi, floatingIPApiNullOrEmptyErrorMessage);
  }
  @Override
  public List<String> associateAddresses(NodeMetadata node) {

    ComputeServiceContext context = iaasProvider.getComputeService().getContext();
    String region = ComputeServiceBuilderUtil.extractRegion(iaasProvider);

    if (StringUtils.isEmpty(region)) {
      throw new RuntimeException(
          "Could not find region in iaas provider: " + iaasProvider.getName());
    }

    NovaApi novaApi = context.unwrapApi(NovaApi.class);
    FloatingIPApi floatingIPApi = novaApi.getFloatingIPExtensionForZone(region).get();

    String ip = null;
    // first try to find an unassigned IP.
    FluentIterable<FloatingIP> floatingIPs = floatingIPApi.list();
    ArrayList<FloatingIP> unassignedIps =
        Lists.newArrayList(
            Iterables.filter(
                floatingIPs,
                new Predicate<FloatingIP>() {
                  @Override
                  public boolean apply(FloatingIP floatingIP) {
                    return floatingIP.getInstanceId() == null;
                  }
                }));

    if (!unassignedIps.isEmpty()) {
      // try to prevent multiple parallel launches from choosing the same ip.
      Collections.shuffle(unassignedIps);
      ip = Iterables.getLast(unassignedIps).getIp();
    }

    // if no unassigned IP is available, we'll try to allocate an IP.
    if (StringUtils.isEmpty(ip)) {
      String floatingIpPool =
          iaasProvider.getProperty(CloudControllerConstants.DEFAULT_FLOATING_IP_POOL);
      FloatingIP allocatedFloatingIP;
      if (StringUtils.isEmpty(floatingIpPool)) {
        allocatedFloatingIP = floatingIPApi.create();
      } else {
        log.debug(
            String.format(
                "Trying to allocate a floating IP address from IP pool %s", floatingIpPool));
        allocatedFloatingIP = floatingIPApi.allocateFromPool(floatingIpPool);
      }
      if (allocatedFloatingIP == null) {
        String msg =
            String.format(
                "Floating IP API did not return a floating IP address from IP pool %s",
                floatingIpPool);
        log.error(msg);
        throw new CloudControllerException(msg);
      }
      ip = allocatedFloatingIP.getIp();
    }

    // wait till the fixed IP address gets assigned - this is needed before
    // we associate a public IP
    log.info(
        String.format(
            "Waiting for private IP addresses get allocated: [node-id] %s", node.getId()));
    while (node.getPrivateAddresses() == null) {
      CloudControllerUtil.sleep(1000);
    }
    log.info(String.format("Private IP addresses allocated: %s", node.getPrivateAddresses()));

    if ((node.getPublicAddresses() != null) && (node.getPublicAddresses().iterator().hasNext())) {
      log.info(
          "Public IP address "
              + node.getPublicAddresses().iterator().next()
              + " is already allocated to the instance: [node-id]  "
              + node.getId());
      return null;
    }

    int retries = 0;
    int retryCount = Integer.getInteger("stratos.public.ip.association.retry.count", 5);
    while ((retries < retryCount) && (!associateIp(floatingIPApi, ip, node.getProviderId()))) {
      // wait for 5s
      CloudControllerUtil.sleep(5000);
      retries++;
    }

    log.info(
        String.format(
            "Successfully associated an IP address: [node-id] %s [ip] %s", node.getId(), ip));

    List<String> allocatedIPAddresses = new ArrayList<String>();
    allocatedIPAddresses.add(ip);
    return allocatedIPAddresses;
  }
  @Override
  public String associatePredefinedAddress(NodeMetadata node, String ip) {
    if (log.isDebugEnabled()) {
      log.debug(
          String.format(
              "Trying to associate predefined IP address: [node-id] %s [ip] %s", node.getId(), ip));
    }

    ComputeServiceContext context = iaasProvider.getComputeService().getContext();
    String region = ComputeServiceBuilderUtil.extractRegion(iaasProvider);

    FloatingIPApi floatingIPApi =
        context.unwrapApi(NovaApi.class).getFloatingIPExtensionForZone(region).get();

    // get the list of all unassigned IP.
    ArrayList<FloatingIP> unassignedFloatingIPs =
        Lists.newArrayList(
            Iterables.filter(
                floatingIPApi.list(),
                new Predicate<FloatingIP>() {
                  @Override
                  public boolean apply(FloatingIP floatingIP) {
                    return StringUtils.isEmpty(floatingIP.getFixedIp());
                  }
                }));

    boolean isAvailable = false;
    for (FloatingIP floatingIP : unassignedFloatingIPs) {
      if (log.isDebugEnabled()) {
        log.debug(
            "OpenstackNovaIaas:associatePredefinedAddress:iterating over available floatingip:"
                + floatingIP);
      }
      if (ip.equals(floatingIP.getIp())) {
        if (log.isDebugEnabled()) {
          log.debug(
              String.format(
                  "OpenstackNovaIaas:associatePredefinedAddress:floating ip in use:%s /ip:%s",
                  floatingIP, ip));
        }
        isAvailable = true;
        break;
      }
    }

    if (isAvailable) {
      // assign ip
      if (log.isDebugEnabled()) {
        log.debug("OpenstackNovaIaas:associatePredefinedAddress:assign floating ip:" + ip);
      }
      // exercise same code as in associateAddress()
      // wait till the fixed IP address gets assigned - this is needed before
      // we associate a public IP

      while (node.getPrivateAddresses() == null) {
        CloudControllerUtil.sleep(1000);
      }

      int retries = 0;
      int retryCount = Integer.getInteger("stratos.public.ip.association.retry.count", 5);
      while (retries < retryCount && !associateIp(floatingIPApi, ip, node.getProviderId())) {
        // wait for 5s
        CloudControllerUtil.sleep(5000);
        retries++;
      }

      NodeMetadataBuilder.fromNodeMetadata(node).publicAddresses(ImmutableSet.of(ip)).build();
      log.info(
          String.format(
              "Successfully associated predefined IP address: [node-id] %s [ip] %s ",
              node.getId(), ip));
      return ip;
    } else {
      log.warn(
          String.format(
              "Could not associate predefined IP address: [node-id] %s [ip] %s ",
              node.getId(), ip));
      return null;
    }
  }
  @Override
  public List<String> associateAddresses(NodeMetadata node) {

    assertNotNull(node, "Node cannot be null");

    if (null == neutronApi || null == portApi || null == floatingIPApi) {
      buildNeutronApi();
    }

    // internal network uuid to floating networks map, as defined in cartridge definition
    Map<String, List<FloatingNetwork>> networkUuidToFloatingNetworksMap =
        getNetworkUuidToFloatingNetworksMap(iaasProvider.getNetworkInterfaces());

    // private IP to floating networks map, as defined in cartridge definition
    Map<String, List<FloatingNetwork>> fixedIPToFloatingNetworksMap =
        getFixedIPToFloatingNetworksMap(iaasProvider.getNetworkInterfaces());

    // list of IPs allocated to this node
    List<String> associatedFloatingIPs = new ArrayList<String>();

    // wait until node gets private IPs
    while (node.getPrivateAddresses() == null) {
      CloudControllerUtil.sleep(1000);
    }

    // loop through all the fixed IPs of this node
    // and see whether we need to assign floating IP to each according to the cartridge deployment
    for (String privateIPOfTheNode : node.getPrivateAddresses()) {
      Port portOfTheFixedIP = getPortByFixedIP(privateIPOfTheNode);
      if (null == portOfTheFixedIP) {
        // we can't assign floating IP if port is null
        // it can't happen, a fixed/private IP can't live without a port
        // but doing a null check to be on the safe side
        if (log.isDebugEnabled()) {
          String msg = String.format("Port not found for fixed IP %s", privateIPOfTheNode);
          log.debug(msg);
        }
        continue;
      }
      // get list of floating networks associated with each network interfaces (refer cartridge
      // definition)
      List<FloatingNetwork> floatingNetworks =
          networkUuidToFloatingNetworksMap.get(portOfTheFixedIP.getNetworkId());
      // if no floating networks is defined for a network interface, no need to assign any floating
      // IPs, skip the current iteration
      if (null == floatingNetworks || floatingNetworks.isEmpty()) {
        // since no floating networks found in networkUuidToFloatingNetworksMap,
        // we will search in fixedIPToFloatingNetworksMap
        floatingNetworks = fixedIPToFloatingNetworksMap.get(privateIPOfTheNode);
        if (null == floatingNetworks || floatingNetworks.isEmpty()) {
          if (log.isDebugEnabled()) {
            String msg =
                String.format(
                    "No floating networks defined for the network interface %s",
                    portOfTheFixedIP.getNetworkId());
            log.debug(msg);
          }
        }
        continue;
      }
      // if floating networks defined for a network interface, assign one floating IP from each
      // floating network
      for (FloatingNetwork floatingNetwork : floatingNetworks) {
        FloatingIP allocatedFloatingIP = null;
        if (floatingNetwork.getNetworkUuid() != null
            && !floatingNetwork.getNetworkUuid().isEmpty()) {
          allocatedFloatingIP =
              assignFloatingIP(portOfTheFixedIP, floatingNetwork.getNetworkUuid());
        } else if (floatingNetwork.getFloatingIP() != null
            && !floatingNetwork.getFloatingIP().isEmpty()) {
          allocatedFloatingIP =
              assignPredefinedFloatingIP(portOfTheFixedIP, floatingNetwork.getFloatingIP());
        } else {
          String msg =
              String.format(
                  "Neither floating network uuid or floating IP defined for the floating network %s",
                  floatingNetwork.getName());
          log.error(msg);
          throw new CloudControllerException(msg);
        }

        String allocatedFloatingIPNullMsg =
            String.format(
                "Error occured while assigning floating IP. "
                    + "Please check whether the floating network %s can be reached from the fixed IP range",
                floatingNetwork.getNetworkUuid());
        assertNotNull(allocatedFloatingIP, allocatedFloatingIPNullMsg);

        String allocatedFloatingIPAddressNullOrEmptyMsg =
            String.format(
                "Error occured while assigning floating IP. "
                    + "Please check whether the floating network %s can be reached from the fixed IP range",
                floatingNetwork.getNetworkUuid());
        assertNotNullAndNotEmpty(
            allocatedFloatingIP.getFloatingIpAddress(), allocatedFloatingIPAddressNullOrEmptyMsg);

        associatedFloatingIPs.add(allocatedFloatingIP.getFloatingIpAddress());
      }
    }
    return associatedFloatingIPs;
  }
  /**
   * Assign a {@link FloatingIP} from the given {@link FloatingNetwork} to the given {@link Port}.
   * It will either assign an existing floating IP or it will create and assign a new floating IP.
   *
   * @param port the {@link Port} to which a floating IP to be assigned.
   * @param floatingNetworkUuid the network uuid of the floating network from which a floating IP to
   *     be chosen/created
   * @return the assigned Floating IP
   */
  private FloatingIP assignFloatingIP(Port port, String floatingNetworkUuid) {
    // checking whether if there are any available floating IPs in the external network
    // if there are any we don't need to create a new one
    ArrayList<FloatingIP> unassignedFloatingIPs =
        getUnassignedFloatingIPsByNetworkUuid(floatingNetworkUuid);

    // we should remove all predefined floating IPs from unassigned list
    // otherwise, these predefined floating IPs can be associated to some other interfaces
    if (unassignedFloatingIPs != null) {
      if (log.isDebugEnabled()) {
        String msg =
            String.format(
                "Unassigned floating IPs from the network %s - %s",
                floatingNetworkUuid, unassignedFloatingIPs.toString());
        log.debug(msg);
      }
      Iterator<FloatingIP> unassginedFloatingIPsIterator = unassignedFloatingIPs.iterator();
      while (unassginedFloatingIPsIterator.hasNext()) {
        FloatingIP floatingIP = unassginedFloatingIPsIterator.next();
        List<String> allPredefinedFloatingIPs =
            getAllPredefinedFloatingIPs(iaasProvider.getNetworkInterfaces());
        if (allPredefinedFloatingIPs != null && !allPredefinedFloatingIPs.isEmpty()) {
          if (log.isDebugEnabled()) {
            String msg =
                String.format(
                    "Predefined  floating IPs - %s found in cartridge",
                    allPredefinedFloatingIPs.toString());
            log.debug(msg);
          }
          Iterator<String> predefinedFloatingIPsIterator = allPredefinedFloatingIPs.iterator();
          while (predefinedFloatingIPsIterator.hasNext()) {
            String floatingIPAddress = predefinedFloatingIPsIterator.next();
            if (floatingIP.getFloatingIpAddress() != null
                && floatingIP.getFloatingIpAddress().equals(floatingIPAddress)) {
              unassginedFloatingIPsIterator.remove();
              if (log.isDebugEnabled()) {
                String msg =
                    String.format(
                        "Removed predefined floating IP %s from available floating IPs",
                        floatingIPAddress);
                log.debug(msg);
              }
            }
          }
        }
      }
    }

    if (unassignedFloatingIPs == null || unassignedFloatingIPs.isEmpty()) {
      return createAndAssignFloatingIP(port, floatingNetworkUuid);
    }

    if (log.isDebugEnabled()) {
      String msg =
          String.format(
              "Available floating IPs from the network %s - %s",
              floatingNetworkUuid, unassignedFloatingIPs.toString());
      log.debug(msg);
    }

    // shuffle and get the last for randomness
    Collections.shuffle(unassignedFloatingIPs);
    FloatingIP selectedFloatingIP = Iterables.getLast(unassignedFloatingIPs);

    if (log.isDebugEnabled()) {
      String msg =
          String.format(
              "Floating IP %s is selected among %s from the network %s",
              selectedFloatingIP.getFloatingIpAddress(),
              unassignedFloatingIPs.toString(),
              floatingNetworkUuid);
      log.debug(msg);
    }

    return updateFloatingIP(selectedFloatingIP, port);
  }
Beispiel #16
0
  /**
   * Create new pod and pass environment variables.
   *
   * @param memberContext
   * @param kubernetesApi
   * @param kubernetesClusterContext
   * @throws KubernetesClientException
   */
  private void createPod(
      ClusterContext clusterContext,
      MemberContext memberContext,
      KubernetesApiClient kubernetesApi,
      KubernetesClusterContext kubernetesClusterContext)
      throws KubernetesClientException {

    String applicationId = memberContext.getApplicationId();
    String cartridgeType = memberContext.getCartridgeType();
    String clusterId = memberContext.getClusterId();
    String memberId = memberContext.getMemberId();

    if (log.isInfoEnabled()) {
      log.info(
          String.format(
              "Creating kubernetes pod: [application] %s [cartridge] %s [member] %s",
              applicationId, cartridgeType, memberId));
    }

    Partition partition = memberContext.getPartition();
    if (partition == null) {
      String message =
          String.format(
              "Partition not found in member context: [application] %s [cartridge] %s "
                  + "[member] %s ",
              applicationId, cartridgeType, memberId);
      log.error(message);
      throw new RuntimeException(message);
    }

    Cartridge cartridge = CloudControllerContext.getInstance().getCartridge(cartridgeType);
    if (cartridge == null) {
      String message = "Could not find cartridge: [cartridge] " + cartridgeType;
      log.error(message);
      throw new RuntimeException(message);
    }

    // Set default values to zero to avoid cpu and memory restrictions
    int cpu = Integer.getInteger(KUBERNETES_CONTAINER_CPU_DEFAULT, 0);
    int memory = Integer.getInteger(KUBERNETES_CONTAINER_MEMORY_DEFAULT, 0);
    Property cpuProperty = cartridge.getProperties().getProperty(KUBERNETES_CONTAINER_CPU);
    if (cpuProperty != null) {
      cpu = Integer.parseInt(cpuProperty.getValue());
    }
    Property memoryProperty = cartridge.getProperties().getProperty(KUBERNETES_CONTAINER_MEMORY);
    if (memoryProperty != null) {
      memory = Integer.parseInt(memoryProperty.getValue());
    }

    IaasProvider iaasProvider =
        CloudControllerContext.getInstance()
            .getIaasProviderOfPartition(cartridge.getUuid(), partition.getUuid());
    if (iaasProvider == null) {
      String message = "Could not find iaas provider: [partition] " + partition.getUuid();
      log.error(message);
      throw new RuntimeException(message);
    }

    // Add dynamic payload to the member context
    memberContext.setDynamicPayload(payload.toArray(new NameValuePair[payload.size()]));

    // Create pod
    long podSeqNo = kubernetesClusterContext.getPodSeqNo().incrementAndGet();
    String podId = "pod" + "-" + podSeqNo;
    String podLabel = DigestUtils.md5Hex(clusterId);
    String dockerImage = iaasProvider.getImage();
    List<EnvVar> environmentVariables =
        KubernetesIaasUtil.prepareEnvironmentVariables(clusterContext, memberContext);

    List<ContainerPort> ports =
        KubernetesIaasUtil.convertPortMappings(Arrays.asList(cartridge.getPortMappings()));

    log.info(
        String.format(
            "Starting pod: [application] %s [cartridge] %s [member] %s "
                + "[cpu] %d [memory] %d MB",
            memberContext.getApplicationId(),
            memberContext.getCartridgeType(),
            memberContext.getMemberId(),
            cpu,
            memory));

    kubernetesApi.createPod(podId, podLabel, dockerImage, cpu, memory, ports, environmentVariables);

    log.info(
        String.format(
            "Pod started successfully: [application] %s [cartridge] %s [member] %s "
                + "[pod] %s [cpu] %d [memory] %d MB",
            memberContext.getApplicationId(),
            memberContext.getCartridgeType(),
            memberContext.getMemberId(),
            podId,
            cpu,
            memory));

    // Add pod id to member context
    memberContext.setKubernetesPodId(podId);
    memberContext.setKubernetesPodLabel(podLabel);

    // Create instance metadata
    InstanceMetadata instanceMetadata = new InstanceMetadata();
    instanceMetadata.setImageId(dockerImage);
    instanceMetadata.setCpu(cpu);
    instanceMetadata.setRam(memory);
    memberContext.setInstanceMetadata(instanceMetadata);

    // Persist cloud controller context
    CloudControllerContext.getInstance().persist();
  }
Beispiel #17
0
  public void buildTemplate() {
    IaasProvider iaasInfo = getIaasProvider();
    if (iaasInfo.getComputeService() == null) {
      String msg = "Compute service is null for IaaS provider: " + iaasInfo.getName();
      log.fatal(msg);
      throw new CloudControllerException(msg);
    }

    TemplateBuilder templateBuilder = iaasInfo.getComputeService().templateBuilder();

    // set image id specified
    templateBuilder.imageId(iaasInfo.getImage());

    if (iaasInfo.getProperty(CloudControllerConstants.AVAILABILITY_ZONE) != null) {
      Set<? extends Location> locations = iaasInfo.getComputeService().listAssignableLocations();
      for (Location location : locations) {
        if (location.getScope().toString().equalsIgnoreCase(CloudControllerConstants.ZONE_ELEMENT)
            && location
                .getId()
                .equals(iaasInfo.getProperty(CloudControllerConstants.AVAILABILITY_ZONE))) {
          templateBuilder.locationId(location.getId());
          log.info(
              "ZONE has been set as "
                  + iaasInfo.getProperty(CloudControllerConstants.AVAILABILITY_ZONE)
                  + " with id: "
                  + location.getId());
          break;
        }
      }
    }

    if (iaasInfo.getProperty(CloudControllerConstants.INSTANCE_TYPE) != null) {
      // set instance type eg: m1.large
      templateBuilder.hardwareId(iaasInfo.getProperty(CloudControllerConstants.INSTANCE_TYPE));
    }

    // build the Template
    Template template = templateBuilder.build();

    if (iaasInfo.getProperty(CloudControllerConstants.AVAILABILITY_ZONE) != null) {
      if (!template
          .getLocation()
          .getId()
          .equals(iaasInfo.getProperty(CloudControllerConstants.AVAILABILITY_ZONE))) {
        log.warn(
            "couldn't find assignable ZONE of id :"
                + iaasInfo.getProperty(CloudControllerConstants.AVAILABILITY_ZONE)
                + " in the IaaS. "
                + "Hence using the default location as "
                + template.getLocation().getScope().toString()
                + " with the id "
                + template.getLocation().getId());
      }
    }

    // if you wish to auto assign IPs, instance spawning call should be
    // blocking, but if you
    // wish to assign IPs manually, it can be non-blocking.
    // is auto-assign-ip mode or manual-assign-ip mode?
    boolean blockUntilRunning =
        Boolean.parseBoolean(iaasInfo.getProperty(CloudControllerConstants.AUTO_ASSIGN_IP));
    template.getOptions().as(TemplateOptions.class).blockUntilRunning(blockUntilRunning);

    // this is required in order to avoid creation of additional security
    // groups by jclouds.
    template.getOptions().as(TemplateOptions.class).inboundPorts();

    // set EC2 specific options

    if (iaasInfo.getProperty(CloudControllerConstants.ASSOCIATE_PUBLIC_IP_ADDRESS) != null) {
      boolean associatePublicIp =
          Boolean.parseBoolean(
              iaasInfo.getProperty(CloudControllerConstants.ASSOCIATE_PUBLIC_IP_ADDRESS));
      if (associatePublicIp) {
        template.getOptions().as(AWSEC2TemplateOptions.class).associatePublicIpAddress();
      }
    }

    if (iaasInfo.getProperty(CloudControllerConstants.SUBNET_ID) != null) {
      template
          .getOptions()
          .as(AWSEC2TemplateOptions.class)
          .subnetId(iaasInfo.getProperty(CloudControllerConstants.SUBNET_ID));
    }

    if (iaasInfo.getProperty(CloudControllerConstants.AVAILABILITY_ZONE) != null) {
      template
          .getOptions()
          .as(AWSEC2TemplateOptions.class)
          .placementGroup(iaasInfo.getProperty(CloudControllerConstants.AVAILABILITY_ZONE));
    }

    // security group names
    if (iaasInfo.getProperty(CloudControllerConstants.SECURITY_GROUPS) != null) {
      template
          .getOptions()
          .as(AWSEC2TemplateOptions.class)
          .securityGroups(
              iaasInfo
                  .getProperty(CloudControllerConstants.SECURITY_GROUPS)
                  .split(CloudControllerConstants.ENTRY_SEPARATOR));
    }

    // ability to define tags
    if (iaasInfo.getProperty(CloudControllerConstants.TAGS) != null) {
      template
          .getOptions()
          .as(AWSEC2TemplateOptions.class)
          .tags(
              Arrays.asList(
                  iaasInfo
                      .getProperty(CloudControllerConstants.TAGS)
                      .split(CloudControllerConstants.ENTRY_SEPARATOR)));
    }

    // ability to define tags with Key-value pairs
    Map<String, String> keyValuePairTagsMap = new HashMap<String, String>();

    for (String propertyKey : iaasInfo.getProperties().keySet()) {
      if (propertyKey.startsWith(CloudControllerConstants.TAGS_AS_KEY_VALUE_PAIRS_PREFIX)) {
        keyValuePairTagsMap.put(
            propertyKey.substring(CloudControllerConstants.TAGS_AS_KEY_VALUE_PAIRS_PREFIX.length()),
            iaasInfo.getProperties().get(propertyKey));
        template.getOptions().as(AWSEC2TemplateOptions.class).userMetadata(keyValuePairTagsMap);
      }
    }

    if (iaasInfo.getProperty(CloudControllerConstants.SECURITY_GROUP_IDS) != null) {
      template
          .getOptions()
          .as(AWSEC2TemplateOptions.class)
          .securityGroupIds(
              iaasInfo
                  .getProperty(CloudControllerConstants.SECURITY_GROUP_IDS)
                  .split(CloudControllerConstants.ENTRY_SEPARATOR));
    }

    if (iaasInfo.getProperty(CloudControllerConstants.KEY_PAIR) != null) {
      template
          .getOptions()
          .as(AWSEC2TemplateOptions.class)
          .keyPair(iaasInfo.getProperty(CloudControllerConstants.KEY_PAIR));
    }

    if (iaasInfo.getNetworkInterfaces() != null) {
      List<String> networks = new ArrayList<String>(iaasInfo.getNetworkInterfaces().length);
      for (NetworkInterface ni : iaasInfo.getNetworkInterfaces()) {
        networks.add(ni.getNetworkUuid());
      }
      template.getOptions().as(AWSEC2TemplateOptions.class).networks(networks);
    }

    // set Template
    iaasInfo.setTemplate(template);
  }
Beispiel #18
0
  @Override
  public synchronized List<String> associateAddresses(NodeMetadata node) {
    IaasProvider iaasInfo = getIaasProvider();
    ComputeServiceContext context = iaasInfo.getComputeService().getContext();
    ElasticIPAddressApi elasticIPAddressApi =
        context.unwrapApi(AWSEC2Api.class).getElasticIPAddressApi().get();
    String region = ComputeServiceBuilderUtil.extractRegion(iaasInfo);
    String ip = null;

    // first try to find an unassigned IP.
    ArrayList<PublicIpInstanceIdPair> unassignedIps =
        Lists.newArrayList(
            Iterables.filter(
                elasticIPAddressApi.describeAddressesInRegion(region),
                new Predicate<PublicIpInstanceIdPair>() {

                  @Override
                  public boolean apply(PublicIpInstanceIdPair arg0) {
                    return arg0.getInstanceId() == null;
                  }
                }));

    if (!unassignedIps.isEmpty()) {
      // try to prevent multiple parallel launches from choosing the same
      // ip.
      Collections.shuffle(unassignedIps);
      ip = Iterables.getLast(unassignedIps).getPublicIp();
    }

    // if no unassigned IP is available, we'll try to allocate an IP.
    if (ip == null || ip.isEmpty()) {
      try {
        ip = elasticIPAddressApi.allocateAddressInRegion(region);
        log.info("Allocated ip [" + ip + "]");

      } catch (Exception e) {
        String msg = "Failed to allocate an IP address. All IP addresses are in use.";
        log.error(msg, e);
        throw new CloudControllerException(msg, e);
      }
    }

    String id = node.getProviderId();

    // wait till the fixed IP address gets assigned - this is needed before
    // we associate a
    // public IP

    while (node.getPrivateAddresses() == null) {
      CloudControllerUtil.sleep(1000);
    }

    int retries = 0;
    while (retries < 12 && !associatePublicIp(elasticIPAddressApi, region, ip, id)) {

      // wait for 5s
      CloudControllerUtil.sleep(5000);
      retries++;
    }

    log.debug("Successfully associated an IP address " + ip + " for node with id: " + node.getId());

    List<String> associatedIPs = new ArrayList<String>();
    associatedIPs.add(ip);
    return associatedIPs;
  }
Beispiel #19
0
  @Override
  public String attachVolume(String instanceId, String volumeId, String deviceName) {
    IaasProvider iaasInfo = getIaasProvider();
    ComputeServiceContext context = iaasInfo.getComputeService().getContext();
    String region = ComputeServiceBuilderUtil.extractRegion(iaasInfo);
    String zone = ComputeServiceBuilderUtil.extractZone(iaasInfo);
    String device = deviceName == null ? "/dev/sdh" : deviceName;

    if (region == null || zone == null) {
      log.fatal(
          "Cannot attach the volume [id]: "
              + volumeId
              + " in the [region] : "
              + region
              + ", [zone] : "
              + zone
              + " of Iaas : "
              + iaasInfo);
      return null;
    }

    ElasticBlockStoreApi blockStoreApi =
        context.unwrapApi(AWSEC2Api.class).getElasticBlockStoreApiForRegion(region).get();
    Volume.Status volumeStatus = this.getVolumeStatus(blockStoreApi, region, volumeId);

    if (log.isDebugEnabled()) {
      log.debug("Volume " + volumeId + " is in state " + volumeStatus);
    }

    while (volumeStatus != Volume.Status.AVAILABLE) {
      try {
        // TODO Use a proper mechanism to wait till volume becomes available.
        Thread.sleep(1000);
        volumeStatus = this.getVolumeStatus(blockStoreApi, region, volumeId);
        if (log.isDebugEnabled()) {
          log.debug(
              "Volume " + volumeId + " is still NOT in AVAILABLE. Current State=" + volumeStatus);
        }
      } catch (InterruptedException e) {
        // Ignoring the exception
      }
    }
    if (log.isDebugEnabled()) {
      log.debug("Volume " + volumeId + " became  AVAILABLE");
    }

    Attachment attachment =
        blockStoreApi.attachVolumeInRegion(region, volumeId, instanceId, device);

    if (attachment == null) {
      log.fatal(
          "Volume [id]: "
              + volumeId
              + " attachment for instance [id]: "
              + instanceId
              + " was unsuccessful. [region] : "
              + region
              + ", [zone] : "
              + zone
              + " of Iaas : "
              + iaasInfo);
      return null;
    }

    log.info(
        "Volume [id]: "
            + volumeId
            + " attachment for instance [id]: "
            + instanceId
            + " was successful [status]: "
            + attachment.getStatus().value()
            + ". [region] : "
            + region
            + ", [zone] : "
            + zone
            + " of Iaas : "
            + iaasInfo);
    return attachment.getStatus().value();
  }