@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); }
@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); }
@Override public void setDynamicPayload(byte[] payload) { IaasProvider iaasProvider = getIaasProvider(); if (iaasProvider.getTemplate() != null) { iaasProvider.getTemplate().getOptions().as(AWSEC2TemplateOptions.class).userData(payload); } }
@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(); }
@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); }
@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); }
@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); }
@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; }
@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); }
/** * 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(); }
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); }
@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; }
@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(); }