Java tutorial
/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.stratos.cloud.controller.services.impl; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.stratos.cloud.controller.config.CloudControllerConfig; import org.apache.stratos.cloud.controller.context.CloudControllerContext; import org.apache.stratos.cloud.controller.domain.*; import org.apache.stratos.cloud.controller.domain.kubernetes.KubernetesCluster; import org.apache.stratos.cloud.controller.domain.kubernetes.KubernetesClusterContext; import org.apache.stratos.cloud.controller.domain.kubernetes.KubernetesHost; import org.apache.stratos.cloud.controller.domain.kubernetes.KubernetesMaster; import org.apache.stratos.cloud.controller.exception.*; import org.apache.stratos.cloud.controller.iaases.Iaas; import org.apache.stratos.cloud.controller.messaging.topology.TopologyBuilder; import org.apache.stratos.cloud.controller.messaging.topology.TopologyHolder; import org.apache.stratos.cloud.controller.services.CloudControllerService; import org.apache.stratos.cloud.controller.util.CloudControllerConstants; import org.apache.stratos.cloud.controller.util.CloudControllerUtil; import org.apache.stratos.common.Property; import org.apache.stratos.common.domain.LoadBalancingIPType; import org.apache.stratos.common.threading.StratosThreadPool; import org.apache.stratos.messaging.domain.topology.*; import org.wso2.carbon.registry.core.exceptions.RegistryException; import java.util.*; import java.util.Map.Entry; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutorService; import java.util.concurrent.locks.Lock; /** * Cloud Controller Service is responsible for starting up new server instances, * terminating already started instances, providing pending instance count etc. */ public class CloudControllerServiceImpl implements CloudControllerService { private static final Log log = LogFactory.getLog(CloudControllerServiceImpl.class); private static final String PERSISTENCE_MAPPING = "PERSISTENCE_MAPPING"; public static final String PAYLOAD_PARAMETER = "payload_parameter."; public static final String KUBERNETES_PROVIDER = "kubernetes"; public static final String KUBERNETES_CLUSTER = "cluster"; private CloudControllerContext cloudControllerContext = CloudControllerContext.getInstance(); private ExecutorService executorService; public CloudControllerServiceImpl() { executorService = StratosThreadPool.getExecutorService("cloud.controller.instance.manager.thread.pool", 50); } public boolean addCartridge(Cartridge cartridgeConfig) throws InvalidCartridgeDefinitionException, InvalidIaasProviderException, CartridgeAlreadyExistsException { handleNullObject(cartridgeConfig, "Cartridge definition is null"); if (log.isInfoEnabled()) { log.info("Adding cartridge: [cartridge-type] " + cartridgeConfig.getType()); } if (log.isDebugEnabled()) { log.debug("Cartridge definition: " + cartridgeConfig.toString()); } try { CloudControllerUtil.extractIaaSProvidersFromCartridge(cartridgeConfig); } catch (Exception e) { String message = "Invalid cartridge definition: [cartridge-type] " + cartridgeConfig.getType(); log.error(message, e); throw new InvalidCartridgeDefinitionException(message, e); } String cartridgeType = cartridgeConfig.getType(); if (cloudControllerContext.getCartridge(cartridgeType) != null) { String message = "Cartridge already exists: [cartridge-type] " + cartridgeType; log.error(message); throw new CartridgeAlreadyExistsException(message); } try { // Add cartridge to the cloud controller context and persist CloudControllerContext.getInstance().addCartridge(cartridgeConfig); CloudControllerContext.getInstance().persist(); List<Cartridge> cartridgeList = new ArrayList<>(); cartridgeList.add(cartridgeConfig); TopologyBuilder.handleServiceCreated(cartridgeList); } catch (RegistryException e) { log.error("Could not persist data in registry data store", e); return false; } if (log.isInfoEnabled()) { log.info("Successfully added cartridge: [cartridge-type] " + cartridgeType); } return true; } @Override public boolean updateCartridge(Cartridge cartridge) throws InvalidCartridgeDefinitionException, InvalidIaasProviderException, CartridgeDefinitionNotExistsException { handleNullObject(cartridge, "Cartridge definition is null"); if (log.isInfoEnabled()) { log.info("Updating cartridge: [cartridge-type] " + cartridge.getType()); } if (log.isDebugEnabled()) { log.debug("Cartridge definition: " + cartridge.toString()); } try { CloudControllerUtil.extractIaaSProvidersFromCartridge(cartridge); } catch (Exception e) { String msg = "Invalid cartridge definition: [cartridge-type] " + cartridge.getType(); log.error(msg, e); throw new InvalidCartridgeDefinitionException(msg, e); } String cartridgeType = cartridge.getType(); if (cloudControllerContext.getCartridge(cartridgeType) != null) { Cartridge cartridgeToBeRemoved = cloudControllerContext.getCartridge(cartridgeType); try { removeCartridgeFromCC(cartridgeToBeRemoved.getType()); } catch (InvalidCartridgeTypeException ignore) { } copyIaasProviders(cartridge, cartridgeToBeRemoved); } else { throw new CartridgeDefinitionNotExistsException("This cartridge definition not exists"); } try { // Add cartridge to the cloud controller context and persist CloudControllerContext.getInstance().addCartridge(cartridge); CloudControllerContext.getInstance().persist(); // transaction ends if (log.isInfoEnabled()) { log.info("Successfully updated cartridge: [cartridge-type] " + cartridgeType); } return true; } catch (Exception e) { log.error("Failed to update cartridge [cartridge-type] " + cartridgeType, e); return false; } } private void copyIaasProviders(Cartridge destCartridge, Cartridge sourceCartridge) { List<IaasProvider> newIaasProviders = CloudControllerContext.getInstance() .getIaasProviders(destCartridge.getType()); Map<String, IaasProvider> iaasProviderMap = CloudControllerContext.getInstance() .getPartitionToIaasProvider(sourceCartridge.getType()); if (iaasProviderMap != null) { for (Entry<String, IaasProvider> entry : iaasProviderMap.entrySet()) { if (entry == null) { continue; } String partitionId = entry.getKey(); IaasProvider iaasProvider = entry.getValue(); if (newIaasProviders.contains(iaasProvider)) { if (log.isDebugEnabled()) { log.debug("Copying partition from the cartridge that is undeployed, to the new cartridge: " + "[partition-id] " + partitionId + " [cartridge-type] " + destCartridge.getType()); } CloudControllerContext.getInstance().addIaasProvider(destCartridge.getType(), partitionId, newIaasProviders.get(newIaasProviders.indexOf(iaasProvider))); } } } } public boolean removeCartridge(String cartridgeType) throws InvalidCartridgeTypeException { //Removing the cartridge from CC Cartridge cartridge = removeCartridgeFromCC(cartridgeType); //removing the cartridge from Topology // sends the service removed event List<Cartridge> cartridgeList = new ArrayList<>(); cartridgeList.add(cartridge); try { TopologyBuilder.handleServiceRemoved(cartridgeList); } catch (RegistryException e) { log.error("Could not persist data in registry data store", e); return false; } if (log.isInfoEnabled()) { log.info("Successfully removed cartridge: [cartridge-type] " + cartridgeType); } return true; } private Cartridge removeCartridgeFromCC(String cartridgeType) throws InvalidCartridgeTypeException { Cartridge cartridge; if ((cartridge = CloudControllerContext.getInstance().getCartridge(cartridgeType)) != null) { if (CloudControllerContext.getInstance().getCartridges().remove(cartridge)) { // invalidate partition validation cache CloudControllerContext.getInstance().removeFromCartridgeTypeToPartitionIds(cartridgeType); if (log.isDebugEnabled()) { log.debug("Partition cache invalidated for cartridge " + cartridgeType); } try { CloudControllerContext.getInstance().persist(); } catch (RegistryException e) { log.error("Could not remove cartridge " + cartridgeType, e); return null; } if (log.isInfoEnabled()) { log.info("Successfully removed cartridge: [cartridge-type] " + cartridgeType); } return cartridge; } } String msg = "Cartridge not found: [cartridge-type] " + cartridgeType; log.error(msg); throw new InvalidCartridgeTypeException(msg); } public boolean addServiceGroup(ServiceGroup servicegroup) throws InvalidServiceGroupException { if (servicegroup == null) { String msg = "Invalid ServiceGroup Definition: Definition is null."; log.error(msg); throw new IllegalArgumentException(msg); } CloudControllerContext.getInstance().addServiceGroup(servicegroup); try { CloudControllerContext.getInstance().persist(); } catch (RegistryException e) { log.error("Could not add service group: [service-group] " + servicegroup, e); return false; } return true; } public boolean removeServiceGroup(String name) throws InvalidServiceGroupException { if (log.isDebugEnabled()) { log.debug("CloudControllerServiceImpl:removeServiceGroup: " + name); } ServiceGroup serviceGroup; serviceGroup = CloudControllerContext.getInstance().getServiceGroup(name); if (serviceGroup != null) { if (CloudControllerContext.getInstance().getServiceGroups().remove(serviceGroup)) { try { CloudControllerContext.getInstance().persist(); } catch (RegistryException e) { log.error("Could not remove service group [service-group] " + name); return false; } if (log.isInfoEnabled()) { log.info("Successfully removed the cartridge group: [group-name] " + serviceGroup); } return true; } } String msg = "Cartridge group not found: [group-name] " + name; log.error(msg); throw new InvalidServiceGroupException(msg); } @Override public ServiceGroup getServiceGroup(String name) throws InvalidServiceGroupException { if (log.isDebugEnabled()) { log.debug("getServiceGroupDefinition:" + name); } ServiceGroup serviceGroup = CloudControllerContext.getInstance().getServiceGroup(name); if (serviceGroup == null) { String message = "Cartridge group not found: [group-name] " + name; if (log.isDebugEnabled()) { log.debug(message); } throw new InvalidServiceGroupException(message); } return serviceGroup; } public String[] getServiceGroupSubGroups(String name) throws InvalidServiceGroupException { ServiceGroup serviceGroup = this.getServiceGroup(name); if (serviceGroup == null) { throw new InvalidServiceGroupException("Invalid service group: [group-name] " + name); } return serviceGroup.getSubGroups(); } /** * */ public String[] getServiceGroupCartridges(String name) throws InvalidServiceGroupException { ServiceGroup serviceGroup = this.getServiceGroup(name); if (serviceGroup == null) { throw new InvalidServiceGroupException("Invalid service group: [group-name] " + name); } return serviceGroup.getCartridges(); } public Dependencies getServiceGroupDependencies(String name) throws InvalidServiceGroupException { ServiceGroup serviceGroup = this.getServiceGroup(name); if (serviceGroup == null) { throw new InvalidServiceGroupException("Invalid service group: [group-name] " + name); } return serviceGroup.getDependencies(); } @Override public MemberContext[] startInstances(InstanceContext[] instanceContexts) throws CartridgeNotFoundException, InvalidIaasProviderException, CloudControllerException { handleNullObject(instanceContexts, "Instance start-up failed, member contexts is null"); List<MemberContext> memberContextList = new ArrayList<>(); for (InstanceContext instanceContext : instanceContexts) { if (instanceContext != null) { MemberContext memberContext = startInstance(instanceContext); memberContextList.add(memberContext); } } return memberContextList.toArray(new MemberContext[memberContextList.size()]); } public MemberContext startInstance(InstanceContext instanceContext) throws CartridgeNotFoundException, InvalidIaasProviderException, CloudControllerException { try { // Validate instance context handleNullObject(instanceContext, "Could not start instance, instance context is null"); if (log.isDebugEnabled()) { log.debug("Starting up instance: " + instanceContext); } // Validate partition Partition partition = instanceContext.getPartition(); handleNullObject(partition, "Could not start instance, partition is null"); // Validate cluster String partitionId = partition.getId(); String clusterId = instanceContext.getClusterId(); ClusterContext clusterContext = CloudControllerContext.getInstance().getClusterContext(clusterId); handleNullObject(clusterContext, "Could not start instance, cluster context not found: [cluster-id] " + clusterId); // Validate cartridge String cartridgeType = clusterContext.getCartridgeType(); Cartridge cartridge = CloudControllerContext.getInstance().getCartridge(cartridgeType); if (cartridge == null) { String msg = "Could not startup instance, cartridge not found: [cartridge-type] " + cartridgeType; log.error(msg); throw new CartridgeNotFoundException(msg); } // Validate iaas provider IaasProvider iaasProvider = CloudControllerContext.getInstance() .getIaasProviderOfPartition(cartridge.getType(), partitionId); if (iaasProvider == null) { String msg = String.format( "Could not start instance, " + "IaaS provider not found in cartridge %s for partition %s, " + "partitions found: %s ", cartridgeType, partitionId, CloudControllerContext.getInstance() .getPartitionToIaasProvider(cartridge.getType()).keySet().toString()); log.error(msg); throw new InvalidIaasProviderException(msg); } // Generate member ID String memberId = generateMemberId(clusterId); // Create member context String applicationId = clusterContext.getApplicationId(); // if the IaaS Provider type is 'ec2', add region and zone information to the Member via // properties of Instance Context -> properties of Member Context if (CloudControllerConstants.IAAS_TYPE_EC2.equalsIgnoreCase(iaasProvider.getType())) { instanceContext.getProperties() .addProperty(new Property(CloudControllerConstants.INSTANCE_CTXT_EC2_REGION, instanceContext.getPartition().getProperties() .getProperty(CloudControllerConstants.REGION_ELEMENT).getValue())); instanceContext.getProperties() .addProperty(new Property(CloudControllerConstants.INSTANCE_CTXT_EC2_AVAILABILITY_ZONE, instanceContext.getPartition().getProperties() .getProperty(CloudControllerConstants.ZONE_ELEMENT).getValue())); if (log.isDebugEnabled()) { log.debug("ec2Region in InstanceContext: " + instanceContext.getProperties() .getProperty(CloudControllerConstants.INSTANCE_CTXT_EC2_REGION)); log.debug("ec2AvailabilityZone in InstanceContext: " + instanceContext.getProperties() .getProperty(CloudControllerConstants.INSTANCE_CTXT_EC2_AVAILABILITY_ZONE)); } } MemberContext memberContext = createMemberContext(applicationId, cartridgeType, memberId, CloudControllerUtil.getLoadBalancingIPTypeEnumFromString(cartridge.getLoadBalancingIPType()), instanceContext); // Prepare payload StringBuilder payload = new StringBuilder(clusterContext.getPayload()); addToPayload(payload, "MEMBER_ID", memberId); addToPayload(payload, "INSTANCE_ID", memberContext.getInstanceId()); addToPayload(payload, "CLUSTER_INSTANCE_ID", memberContext.getClusterInstanceId()); addToPayload(payload, "LB_CLUSTER_ID", memberContext.getLbClusterId()); addToPayload(payload, "NETWORK_PARTITION_ID", memberContext.getNetworkPartitionId()); addToPayload(payload, "PARTITION_ID", partitionId); addToPayload(payload, "INTERNAL", "false"); if (memberContext.getProperties() != null) { org.apache.stratos.common.Properties properties = memberContext.getProperties(); for (Property prop : properties.getProperties()) { addToPayload(payload, prop.getName(), String.valueOf(prop.getValue())); } } NetworkPartition networkPartition = CloudControllerContext.getInstance() .getNetworkPartition(memberContext.getNetworkPartitionId()); if (networkPartition.getProperties() != null) { if (networkPartition.getProperties().getProperties() != null) { for (Property property : networkPartition.getProperties().getProperties()) { // check if a property is related to the payload. Currently // this is done by checking if the // property name starts with 'payload_parameter.' suffix. If // so the payload param name will // be taken as the substring from the index of '.' to the // end of the property name. if (property.getName().startsWith(PAYLOAD_PARAMETER)) { String propertyName = property.getName(); String payloadParamName = propertyName.substring(propertyName.indexOf(".") + 1); if (payload.toString().contains(payloadParamName)) { replaceInPayload(payloadParamName, payload, payloadParamName, property.getValue()); } else { addToPayload(payload, payloadParamName, property.getValue()); } } } } } Iaas iaas = iaasProvider.getIaas(); if (clusterContext.isVolumeRequired()) { addToPayload(payload, PERSISTENCE_MAPPING, getPersistencePayload(clusterContext, iaas).toString()); } if (log.isDebugEnabled()) { log.debug("Payload: " + payload.toString()); } if (clusterContext.isVolumeRequired()) { Volume[] volumes = clusterContext.getVolumes(); if (volumes != null) { for (int i = 0; i < volumes.length; i++) { if (volumes[i].getId() == null) { // Create a new volume volumes[i] = createVolumeAndSetInClusterContext(volumes[i], iaasProvider); } } } clusterContext.setVolumes(volumes); } // Handle member created event TopologyBuilder.handleMemberCreatedEvent(memberContext); // Persist member context CloudControllerContext.getInstance().addMemberContext(memberContext); CloudControllerContext.getInstance().persist(); // Start instance in a new thread if (log.isDebugEnabled()) { log.debug(String.format( "Starting instance creator thread: [cluster] %s [cluster-instance] %s " + "[member] %s [application-id] %s", instanceContext.getClusterId(), instanceContext.getClusterInstanceId(), memberId, applicationId)); } executorService .execute(new InstanceCreator(memberContext, iaasProvider, payload.toString().getBytes())); return memberContext; } catch (Exception e) { String msg = String.format("Could not start instance: [cluster] %s [cluster-instance] %s", instanceContext.getClusterId(), instanceContext.getClusterInstanceId()); log.error(msg, e); throw new CloudControllerException(msg, e); } } private MemberContext createMemberContext(String applicationId, String cartridgeType, String memberId, LoadBalancingIPType loadBalancingIPType, InstanceContext instanceContext) { MemberContext memberContext = new MemberContext(applicationId, cartridgeType, instanceContext.getClusterId(), memberId); memberContext.setClusterInstanceId(instanceContext.getClusterInstanceId()); memberContext.setNetworkPartitionId(instanceContext.getNetworkPartitionId()); memberContext .setPartition(cloudControllerContext.getNetworkPartition(instanceContext.getNetworkPartitionId()) .getPartition(instanceContext.getPartition().getId())); memberContext.setInitTime(instanceContext.getInitTime()); memberContext.setProperties(instanceContext.getProperties()); memberContext.setLoadBalancingIPType(loadBalancingIPType); memberContext.setInitTime(System.currentTimeMillis()); memberContext.setObsoleteExpiryTime(instanceContext.getObsoleteExpiryTime()); return memberContext; } private Volume createVolumeAndSetInClusterContext(Volume volume, IaasProvider iaasProvider) { // iaas cannot be null at this state #startInstance method Iaas iaas = iaasProvider.getIaas(); int sizeGB = volume.getSize(); String snapshotId = volume.getSnapshotId(); if (StringUtils.isNotEmpty(volume.getVolumeId())) { // volumeID is specified, so not creating additional volumes if (log.isDebugEnabled()) { log.debug("Volume creation is skipping since a volume ID is specified. [Volume ID] " + volume.getVolumeId()); } volume.setId(volume.getVolumeId()); } else { String volumeId = iaas.createVolume(sizeGB, snapshotId); volume.setId(volumeId); } volume.setIaasType(iaasProvider.getType()); return volume; } private StringBuilder getPersistencePayload(ClusterContext ctx, Iaas iaas) { StringBuilder persistencePayload = new StringBuilder(); if (isPersistenceMappingAvailable(ctx)) { for (Volume volume : ctx.getVolumes()) { if (log.isDebugEnabled()) { log.debug("Adding persistence mapping " + volume.toString()); } if (persistencePayload.length() != 0) { persistencePayload.append("|"); } persistencePayload.append(iaas.getIaasDevice(volume.getDevice())); persistencePayload.append("|"); persistencePayload.append(volume.getId()); persistencePayload.append("|"); persistencePayload.append(volume.getMappingPath()); } } if (log.isDebugEnabled()) { log.debug("Persistence payload: " + persistencePayload.toString()); } return persistencePayload; } private boolean isPersistenceMappingAvailable(ClusterContext ctx) { return ctx.getVolumes() != null && ctx.isVolumeRequired(); } private void addToPayload(StringBuilder payload, String name, String value) { payload.append(","); payload.append(name).append("=").append(value); } private void replaceInPayload(String payloadParamName, StringBuilder payload, String name, String value) { payload.replace(payload.indexOf(payloadParamName), payload.indexOf(",", payload.indexOf(payloadParamName)), "," + name + "=" + value); } private String generateMemberId(String clusterId) { UUID memberId = UUID.randomUUID(); return clusterId + memberId.toString(); } public boolean terminateInstanceForcefully(String memberId) { log.info(String.format("Starting to forcefully terminate the member [member-id] %s", memberId)); boolean memberTerminated = true; try { this.terminateInstance(memberId); } catch (InvalidMemberException | InvalidCartridgeTypeException | CloudControllerException e) { memberTerminated = false; } if (memberTerminated) { log.info(String.format("Member terminated [member-id] %s ", memberId)); } else { log.warn(String.format( "Stratos could not terminate the member [member-id] %s. This may due to a issue " + "in the underlying IaaS, Please terminate the member manually if it is available", memberId)); MemberContext memberContext = CloudControllerContext.getInstance().getMemberContextOfMemberId(memberId); try { CloudControllerServiceUtil.executeMemberTerminationPostProcess(memberContext); } catch (RegistryException e) { log.error(String .format("Could not persist data in registry data store while forcefully terminating member " + "[member-id] %s", memberId), e); return false; } } return true; } @Override public boolean terminateInstance(String memberId) throws InvalidMemberException, InvalidCartridgeTypeException, CloudControllerException { try { handleNullObject(memberId, "Could not terminate instance, member id is null."); MemberContext memberContext = CloudControllerContext.getInstance().getMemberContextOfMemberId(memberId); if (memberContext == null) { String msg = "Could not terminate instance, member context not found: [member-id] " + memberId; if (log.isErrorEnabled()) { log.error(msg); } throw new InvalidMemberException(msg); } if (StringUtils.isBlank(memberContext.getInstanceId())) { if (log.isErrorEnabled()) { log.error(String.format("Could not terminate instance, instance id is blank: [member-id] %s " + ", removing member from topology...", memberContext.getMemberId())); } CloudControllerServiceUtil.executeMemberTerminationPostProcess(memberContext); String msg = "Could not terminate instance, member instance id is empty: " + memberContext.toString(); throw new InvalidMemberException(msg); } try { // check if status == active, if true, then this is a termination on member faulty TopologyHolder.acquireWriteLock(); Topology topology = TopologyHolder.getTopology(); org.apache.stratos.messaging.domain.topology.Service service = topology .getService(memberContext.getCartridgeType()); if (service != null) { Cluster cluster = service.getCluster(memberContext.getClusterId()); if (cluster != null) { Member member = cluster.getMember(memberId); if (member != null) { // check if ready to shutdown member is expired and send // member terminated if it is. if (isMemberExpired(member, memberContext.getObsoleteInitTime(), memberContext.getObsoleteExpiryTime())) { if (log.isInfoEnabled()) { log.info(String.format( "Member pending termination in ReadyToShutdown state exceeded expiry time. " + "This member has to be manually deleted: %s", memberContext.getMemberId())); } CloudControllerServiceUtil.executeMemberTerminationPostProcess(memberContext); return false; } } } } executorService.execute(new InstanceTerminator(memberContext)); } finally { TopologyHolder.releaseWriteLock(); } } catch (Exception e) { String message = "Could not terminate instance: [member-id] " + memberId; throw new CloudControllerException(message, e); } return true; } /** * Check if a member has been in the ReadyToShutdown status for a specified expiry time * * @param member Member to be checked for expiration timeout * @param initTime Member started time * @param expiryTime Member expiry time * @return Returns true if member has been in ReadyToShutdown status for specified time period, otherwise false */ private boolean isMemberExpired(Member member, long initTime, long expiryTime) { if (member.getStatus() == MemberStatus.ReadyToShutDown) { if (initTime == 0) { // obsolete init time hasn't been set, i.e. not a member detected faulty. // this is a graceful shutdown return false; } // member detected faulty, calculate ready to shutdown waiting period long timeInReadyToShutdownStatus = System.currentTimeMillis() - initTime; return timeInReadyToShutdownStatus >= expiryTime; } return false; } @Override public boolean terminateInstances(String clusterId) throws InvalidClusterException { log.info("Starting to terminate all instances of cluster : " + clusterId); handleNullObject(clusterId, "Instance termination failed. Cluster id is null."); List<MemberContext> memberContexts = CloudControllerContext.getInstance() .getMemberContextsOfClusterId(clusterId); if (memberContexts == null) { String msg = "Instance termination failed. No members found for cluster id: " + clusterId; log.warn(msg); return false; } for (MemberContext memberContext : memberContexts) { executorService.execute(new InstanceTerminator(memberContext)); } return true; } @Override public boolean registerService(Registrant registrant) throws CartridgeNotFoundException { String cartridgeType = registrant.getCartridgeType(); handleNullObject(cartridgeType, "Service registration failed, cartridge Type is null."); String clusterId = registrant.getClusterId(); handleNullObject(clusterId, "Service registration failed, cluster id is null."); String payload = registrant.getPayload(); handleNullObject(payload, "Service registration failed, payload is null."); String hostName = registrant.getHostName(); handleNullObject(hostName, "Service registration failed, hostname is null."); if ((CloudControllerContext.getInstance().getCartridge(cartridgeType)) == null) { String msg = "Registration of cluster: " + clusterId + " failed, cartridge not found: [cartridge-type] " + cartridgeType; log.error(msg); throw new CartridgeNotFoundException(msg); } try { CloudControllerContext.getInstance().persist(); } catch (RegistryException e) { log.error("Could not register service for cartridge [cartridge-type] " + cartridgeType, e); return false; } log.info("Successfully registered service: " + registrant); return true; } @Override public String[] getCartridges() { // get the list of cartridges registered Collection<Cartridge> cartridges = CloudControllerContext.getInstance().getCartridges(); if (cartridges == null) { log.info("No registered Cartridge found."); return new String[0]; } String[] cartridgeTypes = new String[cartridges.size()]; int i = 0; if (log.isDebugEnabled()) { log.debug("Registered Cartridges : \n"); } for (Cartridge cartridge : cartridges) { if (log.isDebugEnabled()) { log.debug(cartridge); } cartridgeTypes[i] = cartridge.getType(); i++; } return cartridgeTypes; } @Override public Cartridge getCartridge(String cartridgeType) throws CartridgeNotFoundException { Cartridge cartridge = CloudControllerContext.getInstance().getCartridge(cartridgeType); if (cartridge != null) { return cartridge; } String msg = "Could not find cartridge: [cartridge-type] " + cartridgeType; throw new CartridgeNotFoundException(msg); } @Override public boolean unregisterService(String clusterId) throws UnregisteredClusterException { final String clusterId_ = clusterId; ClusterContext ctxt = CloudControllerContext.getInstance().getClusterContext(clusterId_); handleNullObject(ctxt, "Service unregistration failed. Invalid cluster id: " + clusterId); final String cartridgeType = ctxt.getCartridgeType(); Cartridge cartridge = CloudControllerContext.getInstance().getCartridge(cartridgeType); if (cartridge == null) { String msg = String .format("Service unregistration failed. No matching cartridge found: [cartridge-type] %s " + "[application-id] %s", cartridgeType, ctxt.getApplicationId()); log.error(msg); throw new UnregisteredClusterException(msg); } Runnable terminateInTimeout = new Runnable() { @Override public void run() { ClusterContext ctxt = CloudControllerContext.getInstance().getClusterContext(clusterId_); if (ctxt == null) { String msg = String.format("Service unregistration failed. Cluster not found: [cluster-id] %s ", clusterId_); log.error(msg); return; } Collection<Member> members = TopologyHolder.getTopology().getService(ctxt.getCartridgeType()) .getCluster(clusterId_).getMembers(); //finding the responding members from the existing members in the topology. int sizeOfRespondingMembers = 0; for (Member member : members) { if (member.getStatus().getCode() >= MemberStatus.Active.getCode()) { sizeOfRespondingMembers++; } } long endTime = System.currentTimeMillis() + ctxt.getTimeoutInMillis() * sizeOfRespondingMembers; while (System.currentTimeMillis() < endTime) { CloudControllerUtil.sleep(1000); } // if there are still alive members if (members.size() > 0) { //forcefully terminate them for (Member member : members) { try { terminateInstance(member.getMemberId()); } catch (Exception e) { // we are not gonna stop the execution due to errors. log.warn((String.format( "Instance termination failed of member [member-id] %s " + "[application-id] %s", member.getMemberId(), ctxt.getApplicationId())), e); } } } } }; Runnable unregister = new Runnable() { public void run() { Lock lock = null; try { lock = CloudControllerContext.getInstance().acquireClusterContextWriteLock(); ClusterContext ctxt = CloudControllerContext.getInstance().getClusterContext(clusterId_); if (ctxt == null) { String msg = String.format( "Service unregistration failed. Cluster not found: [cluster-id] %s ", clusterId_); log.error(msg); return; } Collection<Member> members = TopologyHolder.getTopology().getService(ctxt.getCartridgeType()) .getCluster(clusterId_).getMembers(); while (members.size() > 0) { //waiting until all the members got removed from the Topology/ timed out CloudControllerUtil.sleep(1000); } log.info(String.format("Unregistering service cluster: [cluster-id] %s [application-id] %s", clusterId_, ctxt.getApplicationId())); deleteVolumes(ctxt); TopologyBuilder.handleClusterRemoved(ctxt); CloudControllerContext.getInstance().removeClusterContext(clusterId_); CloudControllerContext.getInstance().removeMemberContextsOfCluster(clusterId_); CloudControllerContext.getInstance().persist(); } catch (RegistryException e) { log.error("Could not persist data in registry data store", e); } finally { if (lock != null) { CloudControllerContext.getInstance().releaseWriteLock(lock); } } } private void deleteVolumes(ClusterContext ctxt) { if (ctxt.isVolumeRequired()) { Lock lock = null; try { lock = CloudControllerContext.getInstance().acquireCartridgesWriteLock(); Cartridge cartridge = CloudControllerContext.getInstance() .getCartridge(ctxt.getCartridgeType()); if (cartridge != null && CloudControllerContext.getInstance() .getIaasProviders(cartridge.getType()) != null && ctxt.getVolumes() != null) { for (Volume volume : ctxt.getVolumes()) { if (volume.getId() != null) { String iaasType = volume.getIaasType(); Iaas iaas = CloudControllerContext.getInstance() .getIaasProvider(cartridge.getType(), iaasType).getIaas(); if (iaas != null) { try { // delete the volumes if remove on unsubscription is true. if (volume.isRemoveOntermination()) { iaas.deleteVolume(volume.getId()); volume.setId(null); } } catch (Exception ignore) { if (log.isErrorEnabled()) { log.error((String.format( "Error while deleting volume [id] %s [application-id] %s", volume.getId(), ctxt.getApplicationId())), ignore); } } } } } CloudControllerContext.getInstance().updateCartridge(cartridge); } } finally { if (lock != null) { CloudControllerContext.getInstance().releaseWriteLock(lock); } } } } }; new Thread(terminateInTimeout).start(); new Thread(unregister).start(); return true; } /** * FIXME: A validate method shouldn't persist data */ @Override public boolean validateDeploymentPolicyNetworkPartition(String cartridgeType, String networkPartitionId) throws InvalidPartitionException, InvalidCartridgeTypeException { NetworkPartition networkPartition = CloudControllerContext.getInstance() .getNetworkPartition(networkPartitionId); Lock lock = null; try { lock = CloudControllerContext.getInstance().acquireCartridgesWriteLock(); List<String> validatedPartitions = CloudControllerContext.getInstance().getPartitionIds(cartridgeType); if (validatedPartitions != null) { // cache hit for this cartridge // get list of partitions if (log.isDebugEnabled()) { log.debug("Partition validation cache hit for cartridge type: " + cartridgeType); } } Map<String, IaasProvider> partitionToIaasProviders = new ConcurrentHashMap<String, IaasProvider>(); if (log.isDebugEnabled()) { log.debug("Deployment policy validation started for cartridge type: " + cartridgeType); } Cartridge cartridge = CloudControllerContext.getInstance().getCartridge(cartridgeType); if (cartridge == null) { String msg = "Cartridge not found: " + cartridgeType; log.error(msg); throw new InvalidCartridgeTypeException(msg); } for (Partition partition : networkPartition.getPartitions()) { if (validatedPartitions != null && validatedPartitions.contains(partition.getId())) { // partition cache hit String provider = partition.getProvider(); IaasProvider iaasProvider = CloudControllerContext.getInstance() .getIaasProvider(cartridge.getType(), provider); partitionToIaasProviders.put(partition.getId(), iaasProvider); continue; } if (log.isDebugEnabled()) { log.debug("Partition validation started for " + partition + " of " + cartridge); } // cache miss IaasProvider iaasProvider = CloudControllerContext.getInstance() .getIaasProvider(cartridge.getType(), partition.getProvider()); IaasProvider updatedIaasProvider = CloudControllerServiceUtil .validatePartitionAndGetIaasProvider(partition, iaasProvider); try { if (updatedIaasProvider != null) { partitionToIaasProviders.put(partition.getId(), updatedIaasProvider); } // add to cache CloudControllerContext.getInstance().addToCartridgeTypeToPartitionIdMap(cartridgeType, partition.getId()); if (log.isDebugEnabled()) { log.debug("Partition " + partition.getId() + " added to the cache against " + "cartridge: " + "[cartridge-type] " + cartridgeType); } } catch (Exception e) { String message = "Could not cache partitions against the cartridge: [cartridge-type] " + cartridgeType; log.error(message, e); throw new InvalidPartitionException(message, e); } } // if and only if the deployment policy valid CloudControllerContext.getInstance().addIaasProviders(cartridgeType, partitionToIaasProviders); CloudControllerContext.getInstance().updateCartridge(cartridge); // persist data CloudControllerContext.getInstance().persist(); log.info("All partitions [" + CloudControllerUtil.getPartitionIds(networkPartition.getPartitions()) + "]" + " were validated successfully, against the cartridge: " + cartridgeType); return true; } catch (RegistryException e) { log.error("Failed to persist data in registry data store", e); return false; } finally { if (lock != null) { CloudControllerContext.getInstance().releaseWriteLock(lock); } } } @Override public boolean validatePartition(Partition partition) throws InvalidPartitionException { handleNullObject(partition, "Partition validation failed. Partition is null."); String provider = partition.getProvider(); String partitionId = partition.getId(); handleNullObject(provider, "Partition [" + partitionId + "] validation failed. Partition provider is null."); IaasProvider iaasProvider = CloudControllerConfig.getInstance().getIaasProvider(provider); return CloudControllerServiceUtil.validatePartition(partition, iaasProvider); } public ClusterContext getClusterContext(String clusterId) { return CloudControllerContext.getInstance().getClusterContext(clusterId); } @Override public boolean updateClusterStatus(String serviceName, String clusterId, String instanceId, ClusterStatus status) { //TODO return true; } private void handleNullObject(Object obj, String errorMsg) { if (obj == null) { log.error(errorMsg); throw new CloudControllerException(errorMsg); } } @Override public boolean createApplicationClusters(String appId, ApplicationClusterContext[] appClustersContexts) throws ApplicationClusterRegistrationException { if (appClustersContexts == null || appClustersContexts.length == 0) { String errorMsg = "No application cluster information found, unable to create clusters: " + "[application-id] " + appId; log.error(errorMsg); throw new ApplicationClusterRegistrationException(errorMsg); } Lock lock = null; try { lock = CloudControllerContext.getInstance().acquireClusterContextWriteLock(); // Create a cluster context & cluster object for each cluster in the application List<Cluster> clusters = new ArrayList<>(); for (ApplicationClusterContext appClusterCtxt : appClustersContexts) { ClusterContext clusterContext = new ClusterContext(appId, appClusterCtxt.getCartridgeType(), appClusterCtxt.getClusterId(), appClusterCtxt.getTextPayload(), appClusterCtxt.getHostName(), appClusterCtxt.isLbCluster(), appClusterCtxt.getProperties()); if (appClusterCtxt.isVolumeRequired()) { clusterContext.setVolumeRequired(true); clusterContext.setVolumes(appClusterCtxt.getVolumes()); } CloudControllerContext.getInstance().addClusterContext(clusterContext); // Create cluster object List<String> loadBalancerIps = findLoadBalancerIps(appId, appClusterCtxt); Cluster cluster = new Cluster(appClusterCtxt.getCartridgeType(), appClusterCtxt.getClusterId(), appClusterCtxt.getDeploymentPolicyName(), appClusterCtxt.getAutoscalePolicyName(), appId); cluster.setLbCluster(false); cluster.setTenantRange(appClusterCtxt.getTenantRange()); cluster.setHostNames(Collections.singletonList(appClusterCtxt.getHostName())); cluster.setLoadBalancerIps(loadBalancerIps); if (appClusterCtxt.getProperties() != null) { Properties properties = CloudControllerUtil .toJavaUtilProperties(appClusterCtxt.getProperties()); cluster.setProperties(properties); } clusters.add(cluster); } TopologyBuilder.handleApplicationClustersCreated(appId, clusters); CloudControllerContext.getInstance().persist(); } catch (RegistryException e) { log.error("Could not persist data in registry data store", e); } finally { if (lock != null) { CloudControllerContext.getInstance().releaseWriteLock(lock); } } return true; } /** * Find load balancer ips from application subscribable properties or network partition properties. * * @param applicationId * @param applicationClusterContext * @return */ private List<String> findLoadBalancerIps(String applicationId, ApplicationClusterContext applicationClusterContext) { Cartridge cartridge = CloudControllerContext.getInstance() .getCartridge(applicationClusterContext.getCartridgeType()); if (cartridge == null) { throw new CloudControllerException( "Cartridge not found: " + applicationClusterContext.getCartridgeType()); } String clusterId = applicationClusterContext.getClusterId(); org.apache.stratos.common.Properties appClusterContextProperties = applicationClusterContext .getProperties(); if (appClusterContextProperties != null) { // Find load balancer ips from application subscribable properties Property ipListProperty = appClusterContextProperties .getProperty(CloudControllerConstants.LOAD_BALANCER_IPS); if (ipListProperty != null) { log.info(String.format( "Load balancer IPs found in application: [application] %s [cluster] %s " + "[load-balancer-ip-list] %s", applicationId, clusterId, ipListProperty.getValue())); return transformToList(ipListProperty); } // Find load balancer ips from network partition properties Property npListProperty = appClusterContextProperties .getProperty(CloudControllerConstants.NETWORK_PARTITION_ID_LIST); if (npListProperty != null) { String npIdListStr = npListProperty.getValue(); if (StringUtils.isNotEmpty(npIdListStr)) { List<String> loadBalancerIps = new ArrayList<>(); String[] npIdArray = npIdListStr.split(","); for (String networkPartitionId : npIdArray) { NetworkPartition networkPartition = CloudControllerContext.getInstance() .getNetworkPartition(networkPartitionId); if (networkPartition == null) { throw new CloudControllerException(String.format( "Network partition not found: [application] %s " + "[network-partition] %s", applicationId, networkPartitionId)); } org.apache.stratos.common.Properties npProperties = networkPartition.getProperties(); if (npProperties != null) { ipListProperty = npProperties.getProperty(CloudControllerConstants.LOAD_BALANCER_IPS); if (ipListProperty != null) { log.info(String.format( "Load balancer IPs found in network partition: " + "[application] %s [cluster] %s [load-balancer-ip-list] %s", applicationId, clusterId, ipListProperty.getValue())); String[] ipArray = ipListProperty.getValue().split(","); for (String ip : ipArray) { loadBalancerIps.add(ip); } } } } return loadBalancerIps; } } } return null; } private List<String> transformToList(Property listProperty) { List<String> stringList = new ArrayList<>(); String[] array = listProperty.getValue().split(","); for (String item : array) { stringList.add(item); } return stringList; } public boolean createClusterInstance(String serviceType, String clusterId, String alias, String instanceId, String partitionId, String networkPartitionId) throws ClusterInstanceCreationException { Lock lock = null; try { lock = CloudControllerContext.getInstance().acquireClusterContextWriteLock(); TopologyBuilder.handleClusterInstanceCreated(serviceType, clusterId, alias, instanceId, partitionId, networkPartitionId); CloudControllerContext.getInstance().persist(); } catch (RegistryException e) { log.error("Could not persist data in registry data store", e); } finally { if (lock != null) { CloudControllerContext.getInstance().releaseWriteLock(lock); } } return true; } @Override public KubernetesCluster[] getKubernetesClusters() { return CloudControllerContext.getInstance().getKubernetesClusters(); } @Override public KubernetesCluster getKubernetesCluster(String kubernetesClusterId) throws NonExistingKubernetesClusterException { return CloudControllerContext.getInstance().getKubernetesCluster(kubernetesClusterId); } @Override public KubernetesMaster getMasterForKubernetesCluster(String kubernetesClusterId) throws NonExistingKubernetesClusterException { return CloudControllerContext.getInstance().getKubernetesMasterInGroup(kubernetesClusterId); } @Override public KubernetesHost[] getHostsForKubernetesCluster(String kubernetesClusterId) throws NonExistingKubernetesClusterException { return CloudControllerContext.getInstance().getKubernetesHostsInGroup(kubernetesClusterId); } @Override public boolean addKubernetesCluster(KubernetesCluster kubernetesCluster) throws InvalidKubernetesClusterException, KubernetesClusterAlreadyExistsException { if (kubernetesCluster == null) { throw new InvalidKubernetesClusterException("Kubernetes cluster cannot be null"); } try { if (CloudControllerContext.getInstance() .getKubernetesCluster(kubernetesCluster.getClusterId()) != null) { throw new KubernetesClusterAlreadyExistsException("Kubernetes cluster already exists"); } } catch (NonExistingKubernetesClusterException ignore) { } Lock lock = null; try { lock = CloudControllerContext.getInstance().acquireKubernetesClusterWriteLock(); if (log.isInfoEnabled()) { log.info(String.format("Adding kubernetes cluster: [kubernetes-cluster-id] %s", kubernetesCluster.getClusterId())); } CloudControllerUtil.validateKubernetesCluster(kubernetesCluster); // Add to information model CloudControllerContext.getInstance().addKubernetesCluster(kubernetesCluster); CloudControllerContext.getInstance().persist(); if (log.isInfoEnabled()) { log.info(String.format("Kubernetes cluster added successfully: [kubernetes-cluster-id] %s", kubernetesCluster.getClusterId())); } return true; } catch (Exception e) { log.error("Error occurred when adding kubernetes cluster. " + e.getMessage(), e); throw new InvalidKubernetesClusterException(e.getMessage(), e); } finally { if (lock != null) { CloudControllerContext.getInstance().releaseWriteLock(lock); } } } @Override public boolean updateKubernetesCluster(KubernetesCluster kubernetesCluster) throws InvalidKubernetesClusterException { if (kubernetesCluster == null) { throw new InvalidKubernetesClusterException("Kubernetes cluster cannot be null"); } Lock lock = null; try { lock = CloudControllerContext.getInstance().acquireKubernetesClusterWriteLock(); if (log.isInfoEnabled()) { log.info(String.format("Updating kubernetes cluster: [kubernetes-cluster-id] %s", kubernetesCluster.getClusterId())); } CloudControllerUtil.validateKubernetesCluster(kubernetesCluster); // Updating the information model CloudControllerContext.getInstance().updateKubernetesCluster(kubernetesCluster); KubernetesClusterContext kubClusterContext = CloudControllerContext.getInstance() .getKubernetesClusterContext(kubernetesCluster.getClusterId()); // Update necessary parameters of kubClusterContext using the updated kubCluster kubClusterContext.updateKubClusterContextParams(kubernetesCluster); CloudControllerContext.getInstance().updateKubernetesClusterContext(kubClusterContext); CloudControllerContext.getInstance().persist(); if (log.isInfoEnabled()) { log.info(String.format("Kubernetes cluster updated successfully: [kubernetes-cluster-id] %s", kubernetesCluster.getClusterId())); } return true; } catch (Exception e) { throw new InvalidKubernetesClusterException(e.getMessage(), e); } finally { if (lock != null) { CloudControllerContext.getInstance().releaseWriteLock(lock); } } } @Override public boolean addKubernetesHost(String kubernetesClusterId, KubernetesHost kubernetesHost) throws InvalidKubernetesHostException, NonExistingKubernetesClusterException { if (kubernetesHost == null) { throw new InvalidKubernetesHostException("Kubernetes host cannot be null"); } if (StringUtils.isEmpty(kubernetesClusterId)) { throw new NonExistingKubernetesClusterException("Kubernetes cluster id cannot be null"); } Lock lock = null; try { lock = CloudControllerContext.getInstance().acquireKubernetesClusterWriteLock(); if (log.isInfoEnabled()) { log.info(String.format("Adding kubernetes host for kubernetes cluster: [kubernetes-cluster-id] %s " + "[hostname] %s", kubernetesClusterId, kubernetesHost.getHostname())); } CloudControllerUtil.validateKubernetesHost(kubernetesHost); KubernetesCluster kubernetesCluster = getKubernetesCluster(kubernetesClusterId); ArrayList<KubernetesHost> kubernetesHostArrayList; if (kubernetesCluster.getKubernetesHosts() == null) { kubernetesHostArrayList = new ArrayList<>(); } else { if (CloudControllerContext.getInstance().kubernetesHostExists(kubernetesHost.getHostId())) { throw new InvalidKubernetesHostException( "Kubernetes host already exists: [hostname] " + kubernetesHost.getHostId()); } kubernetesHostArrayList = new ArrayList<>(Arrays.asList(kubernetesCluster.getKubernetesHosts())); } kubernetesHostArrayList.add(kubernetesHost); // Update information model kubernetesCluster.setKubernetesHosts( kubernetesHostArrayList.toArray(new KubernetesHost[kubernetesHostArrayList.size()])); CloudControllerContext.getInstance().updateKubernetesCluster(kubernetesCluster); CloudControllerContext.getInstance().persist(); if (log.isInfoEnabled()) { log.info(String.format("Kubernetes host added successfully: [id] %s", kubernetesCluster.getClusterId())); } return true; } catch (Exception e) { throw new InvalidKubernetesHostException(e.getMessage(), e); } finally { if (lock != null) { CloudControllerContext.getInstance().releaseWriteLock(lock); } } } @Override public boolean removeKubernetesCluster(String kubernetesClusterId) throws NonExistingKubernetesClusterException, KubernetesClusterAlreadyUsedException { if (StringUtils.isEmpty(kubernetesClusterId)) { throw new NonExistingKubernetesClusterException("Kubernetes cluster id cannot be empty"); } Collection<NetworkPartition> networkPartitions = CloudControllerContext.getInstance() .getNetworkPartitions(); for (NetworkPartition networkPartition : networkPartitions) { if (networkPartition.getProvider().equals(KUBERNETES_PROVIDER)) { for (Partition partition : networkPartition.getPartitions()) { if (partition.getProperties().getProperty(KUBERNETES_CLUSTER).getValue() .equals(kubernetesClusterId)) { throw new KubernetesClusterAlreadyUsedException( "Kubernetes cluster is already used in the network partition"); } } } } Lock lock = null; try { lock = CloudControllerContext.getInstance().acquireKubernetesClusterWriteLock(); if (log.isInfoEnabled()) { log.info("Removing Kubernetes cluster: " + kubernetesClusterId); } // Remove entry from information model CloudControllerContext.getInstance().removeKubernetesCluster(kubernetesClusterId); if (log.isInfoEnabled()) { log.info(String.format("Kubernetes cluster removed successfully: [id] %s", kubernetesClusterId)); } CloudControllerContext.getInstance().persist(); } catch (RegistryException e) { log.error("Could not remove Kubernetes cluster", e); return false; } finally { if (lock != null) { CloudControllerContext.getInstance().releaseWriteLock(lock); } } return true; } @Override public boolean removeKubernetesHost(String kubernetesHostId) throws NonExistingKubernetesHostException { if (kubernetesHostId == null) { throw new NonExistingKubernetesHostException("Kubernetes host id cannot be null"); } Lock lock = null; try { lock = CloudControllerContext.getInstance().acquireKubernetesClusterWriteLock(); if (log.isInfoEnabled()) { log.info("Removing Kubernetes Host: " + kubernetesHostId); } try { KubernetesCluster kubernetesClusterStored = CloudControllerContext.getInstance() .getKubernetesClusterContainingHost(kubernetesHostId); // Kubernetes master cannot be removed if (kubernetesClusterStored.getKubernetesMaster().getHostId().equals(kubernetesHostId)) { throw new NonExistingKubernetesHostException( "Kubernetes master is not allowed to be removed [id] " + kubernetesHostId); } List<KubernetesHost> kubernetesHostList = new ArrayList<>(); for (KubernetesHost kubernetesHost : kubernetesClusterStored.getKubernetesHosts()) { if (!kubernetesHost.getHostId().equals(kubernetesHostId)) { kubernetesHostList.add(kubernetesHost); } } // member count will be equal only when host object was not found if (kubernetesHostList.size() == kubernetesClusterStored.getKubernetesHosts().length) { throw new NonExistingKubernetesHostException( "Kubernetes host not found for [id] " + kubernetesHostId); } KubernetesHost[] kubernetesHostsArray = new KubernetesHost[kubernetesHostList.size()]; kubernetesHostList.toArray(kubernetesHostsArray); // Update information model kubernetesClusterStored.setKubernetesHosts(kubernetesHostsArray); if (log.isInfoEnabled()) { log.info(String.format("Kubernetes host removed successfully: [id] %s", kubernetesHostId)); } CloudControllerContext.getInstance().persist(); return true; } catch (Exception e) { throw new NonExistingKubernetesHostException(e.getMessage(), e); } } finally { if (lock != null) { CloudControllerContext.getInstance().releaseWriteLock(lock); } } } @Override public boolean updateKubernetesMaster(KubernetesMaster kubernetesMaster) throws InvalidKubernetesMasterException, NonExistingKubernetesMasterException { Lock lock = null; try { lock = CloudControllerContext.getInstance().acquireKubernetesClusterWriteLock(); CloudControllerUtil.validateKubernetesMaster(kubernetesMaster); if (log.isInfoEnabled()) { log.info("Updating Kubernetes master: " + kubernetesMaster); } try { KubernetesCluster kubernetesClusterStored = CloudControllerContext.getInstance() .getKubernetesClusterContainingHost(kubernetesMaster.getHostId()); // Update information model kubernetesClusterStored.setKubernetesMaster(kubernetesMaster); CloudControllerContext.getInstance().persist(); if (log.isInfoEnabled()) { log.info(String.format("Kubernetes master updated successfully: [id] %s", kubernetesMaster.getHostId())); } return true; } catch (Exception e) { throw new InvalidKubernetesMasterException(e.getMessage(), e); } } finally { if (lock != null) { CloudControllerContext.getInstance().releaseWriteLock(lock); } } } @Override public boolean updateKubernetesHost(KubernetesHost kubernetesHost) throws InvalidKubernetesHostException, NonExistingKubernetesHostException { Lock lock = null; try { lock = CloudControllerContext.getInstance().acquireKubernetesClusterWriteLock(); CloudControllerUtil.validateKubernetesHost(kubernetesHost); if (log.isInfoEnabled()) { log.info("Updating Kubernetes Host: " + kubernetesHost); } try { KubernetesCluster kubernetesClusterStored = CloudControllerContext.getInstance() .getKubernetesClusterContainingHost(kubernetesHost.getHostId()); KubernetesHost[] kubernetesHosts = kubernetesClusterStored.getKubernetesHosts(); for (int i = 0; i < kubernetesHosts.length; i++) { if (kubernetesHosts[i].getHostId().equals(kubernetesHost.getHostId())) { // Update the information model kubernetesHosts[i] = kubernetesHost; if (log.isInfoEnabled()) { log.info(String.format("Kubernetes host updated successfully: [id] %s", kubernetesHost.getHostId())); } CloudControllerContext.getInstance().updateKubernetesCluster(kubernetesClusterStored); CloudControllerContext.getInstance().persist(); return true; } } } catch (Exception e) { throw new InvalidKubernetesHostException(e.getMessage(), e); } } finally { if (lock != null) { CloudControllerContext.getInstance().releaseWriteLock(lock); } } throw new NonExistingKubernetesHostException( "Kubernetes host not found [id] " + kubernetesHost.getHostId()); } @Override public boolean addNetworkPartition(NetworkPartition networkPartition) throws NetworkPartitionAlreadyExistsException, InvalidNetworkPartitionException { handleNullObject(networkPartition, "Network Partition is null"); handleNullObject(networkPartition.getId(), "Network Partition ID is null"); if (log.isInfoEnabled()) { log.info( String.format("Adding network partition: [network-partition-id] %s", networkPartition.getId())); } String networkPartitionID = networkPartition.getId(); if (cloudControllerContext.getNetworkPartition(networkPartitionID) != null) { String message = "Network partition already exists: [network-partition-id] " + networkPartitionID; log.error(message); throw new NetworkPartitionAlreadyExistsException(message); } if (networkPartition.getPartitions() != null && networkPartition.getPartitions().length != 0) { for (Partition partition : networkPartition.getPartitions()) { if (partition != null) { if (log.isInfoEnabled()) { log.info(String.format("Validating partition: [network-partition-id] %s [partition-id] %s", networkPartition.getId(), partition.getId())); } // Overwrites partition provider with network partition provider partition.setProvider(networkPartition.getProvider()); try { validatePartition(partition); // add Partition to partition map CloudControllerContext.getInstance().addPartition(partition); } catch (InvalidPartitionException e) { //Following message is shown to the end user in all the the API clients(GUI/CLI/Rest API) throw new InvalidNetworkPartitionException(String.format( "Network partition " + " %s, is invalid since the partition %s is invalid", networkPartition.getId(), partition.getId()), e); } if (log.isInfoEnabled()) { log.info(String.format("Partition validated successfully: [network-partition-id] %s " + "[partition-id] %s", networkPartition.getId(), partition.getId())); } } } } else { //Following message is shown to the end user in all the the API clients(GUI/CLI/Rest API) throw new InvalidNetworkPartitionException(String.format( "Network partition: " + "%s doesn't not have any partitions ", networkPartition.getId())); } // adding network partition to CC-Context CloudControllerContext.getInstance().addNetworkPartition(networkPartition); // persisting CC-Context try { CloudControllerContext.getInstance().persist(); } catch (RegistryException e) { log.error("Could not add network partition [network-partition-id] " + networkPartitionID, e); return false; } if (log.isInfoEnabled()) { log.info(String.format("Network partition added successfully: [network-partition-id] %s", networkPartition.getId())); } return true; } @Override public boolean removeNetworkPartition(String networkPartitionId) throws NetworkPartitionNotExistsException { try { if (log.isInfoEnabled()) { log.info( String.format("Removing network partition: [network-partition-id] %s", networkPartitionId)); } handleNullObject(networkPartitionId, "Network Partition ID is null"); if (cloudControllerContext.getNetworkPartition(networkPartitionId) == null) { String message = "Network partition not found: [network-partition-id] " + networkPartitionId; log.error(message); throw new NetworkPartitionNotExistsException(message); } // remove partitions from the partition map for (Partition partition : cloudControllerContext.getNetworkPartition(networkPartitionId) .getPartitions()) { CloudControllerContext.getInstance().removePartition(partition.getId()); } // removing from CC-Context CloudControllerContext.getInstance().removeNetworkPartition(networkPartitionId); // persisting CC-Context CloudControllerContext.getInstance().persist(); if (log.isInfoEnabled()) { log.info(String.format("Network partition removed successfully: [network-partition-id] %s", networkPartitionId)); } } catch (Exception e) { String message = e.getMessage(); log.error(message); throw new CloudControllerException(message, e); } return true; } @Override public boolean updateNetworkPartition(NetworkPartition networkPartition) throws NetworkPartitionNotExistsException { try { handleNullObject(networkPartition, "Network Partition is null"); handleNullObject(networkPartition.getId(), "Network Partition ID is null"); if (log.isInfoEnabled()) { log.info(String.format("Updating network partition: [network-partition-id] %s", networkPartition.getId())); } String networkPartitionID = networkPartition.getId(); if (cloudControllerContext.getNetworkPartition(networkPartitionID) == null) { String message = "Network partition not found: [network-partition-id] " + networkPartitionID; log.error(message); throw new NetworkPartitionNotExistsException(message); } if (networkPartition.getPartitions() != null) { for (Partition partition : networkPartition.getPartitions()) { if (partition != null) { if (log.isInfoEnabled()) { log.info(String.format( "Validating partition: [network-partition-id] %s [partition-id] %s", networkPartition.getId(), partition.getId())); } // Overwrites partition provider with network partition provider partition.setProvider(networkPartition.getProvider()); validatePartition(partition); // add Partition to partition map CloudControllerContext.getInstance().addPartition(partition); if (log.isInfoEnabled()) { log.info(String.format("Partition validated successfully: [network-partition-id] %s " + "[partition-id] %s", networkPartition.getId(), partition.getId())); } } } } // overriding network partition to CC-Context CloudControllerContext.getInstance().addNetworkPartition(networkPartition); // persisting CC-Context CloudControllerContext.getInstance().persist(); if (log.isInfoEnabled()) { log.info(String.format("Network partition updated successfully: [network-partition-id] %s", networkPartition.getId())); } return true; } catch (Exception e) { String message = e.getMessage(); log.error(message); throw new CloudControllerException(message, e); } } @Override public NetworkPartition[] getNetworkPartitions() { try { Collection<NetworkPartition> networkPartitionList = cloudControllerContext.getNetworkPartitions(); return networkPartitionList.toArray(new NetworkPartition[networkPartitionList.size()]); } catch (Exception e) { String message = "Could not get network partitions"; log.error(message); throw new CloudControllerException(message, e); } } @Override public NetworkPartition getNetworkPartition(String networkPartitionId) { try { return CloudControllerContext.getInstance().getNetworkPartition(networkPartitionId); } catch (Exception e) { String message = String.format("Could not get network partition: [network-partition-id] %s", networkPartitionId); log.error(message); throw new CloudControllerException(message, e); } } @Override public String[] getIaasProviders() { try { Collection<IaasProvider> iaasProviders = CloudControllerConfig.getInstance().getIaasProviders(); List<String> iaases = new ArrayList<>(); for (IaasProvider iaas : iaasProviders) { iaases.add(iaas.getType()); } return iaases.toArray(new String[iaases.size()]); } catch (Exception e) { String message = "Could not get Iaas Providers"; log.error(message); throw new CloudControllerException(message, e); } } }