protected List<ServiceInstanceData> populateTargetInstancesData( Map<Long, List<ServiceInstanceData>> servicesTargetInstances, Map<Long, List<ServiceDnsEntryData>> clientServiceIdToServiceData, Service targetService) { List<ServiceInstanceData> targetInstancesData = new ArrayList<>(); if (targetService .getKind() .equalsIgnoreCase(ServiceDiscoveryConstants.KIND.DNSSERVICE.name())) { List<ServiceDnsEntryData> behindAlias = clientServiceIdToServiceData.get(targetService.getId()); if (behindAlias != null) { for (ServiceDnsEntryData behindAliasEntry : behindAlias) { List<ServiceInstanceData> toAdd = servicesTargetInstances.get(behindAliasEntry.getTargetService().getId()); if (toAdd != null) { targetInstancesData.addAll(toAdd); } } } } else { List<ServiceInstanceData> toAdd = servicesTargetInstances.get(targetService.getId()); if (toAdd != null) { targetInstancesData.addAll(toAdd); } } return targetInstancesData; }
@Override public List<Integer> getServiceInstanceUsedOrderIds(Service service, String launchConfigName) { Environment env = objectManager.findOne(Environment.class, ENVIRONMENT.ID, service.getEnvironmentId()); // get all existing instances to check if the name is in use by the instance of the same service List<Integer> usedIds = new ArrayList<>(); // list all the instances List<? extends ServiceExposeMap> instanceServiceMaps = exposeMapDao.getNonRemovedServiceInstanceMap(service.getId()); for (ServiceExposeMap instanceServiceMap : instanceServiceMaps) { Instance instance = objectManager.loadResource(Instance.class, instanceServiceMap.getInstanceId()); if (ServiceDiscoveryUtil.isServiceGeneratedName(env, service, instance)) { String configName = launchConfigName == null || launchConfigName.equals(ServiceDiscoveryConstants.PRIMARY_LAUNCH_CONFIG_NAME) ? "" : launchConfigName + "_"; String id = instance .getName() .replace( String.format("%s_%s_%s", env.getName(), service.getName(), configName), ""); if (id.matches("\\d+")) { usedIds.add(Integer.valueOf(id)); } } } return usedIds; }
protected List<DnsEntryData> convertToDnsEntryData( final boolean isVIPProvider, List<ServiceDnsEntryData> serviceDnsData, long accountId, long vnetId) { final Map<Long, IpAddress> instanceIdToHostIpMap = getInstanceWithHostNetworkingToIpMap(accountId); Map<Long, List<ServiceInstanceData>> servicesClientInstances = getServiceInstancesData(accountId, true, vnetId); Map<Long, List<ServiceInstanceData>> servicesTargetInstances = getServiceInstancesData(accountId, false, vnetId); Map<Long, List<ServiceDnsEntryData>> clientServiceIdToServiceData = new HashMap<>(); for (ServiceDnsEntryData data : serviceDnsData) { Long clientServiceId = data.getClientService().getId(); List<ServiceDnsEntryData> existingData = clientServiceIdToServiceData.get(clientServiceId); if (existingData == null) { existingData = new ArrayList<>(); } existingData.add(data); clientServiceIdToServiceData.put(clientServiceId, existingData); } List<DnsEntryData> returnData = new ArrayList<>(); for (ServiceDnsEntryData serviceData : serviceDnsData) { Service clientService = serviceData.getClientService(); Map<String, Map<String, String>> resolve = new HashMap<>(); Map<String, String> resolveCname = new HashMap<>(); Service targetService = serviceData.getTargetService(); List<ServiceInstanceData> targetInstancesData = populateTargetInstancesData( servicesTargetInstances, clientServiceIdToServiceData, targetService); for (ServiceInstanceData targetInstance : targetInstancesData) { populateResolveInfo( isVIPProvider, instanceIdToHostIpMap, serviceData, clientService, resolve, resolveCname, targetService, targetInstance); } if (servicesClientInstances.containsKey(clientService.getId())) { for (ServiceInstanceData clientInstance : servicesClientInstances.get(clientService.getId())) { DnsEntryData data = new DnsEntryData(); String clientIp = getIpAddress(clientInstance, true, instanceIdToHostIpMap); data.setSourceIpAddress(clientIp); data.setResolveServicesAndContainers(resolve); data.setInstance(clientInstance.getInstance()); data.setResolveCname(resolveCname); returnData.add(data); } } } return returnData; }
protected Map<String, Object> populateLBData( Service service, String lbName, LoadBalancerConfig lbConfig, Map<String, Object> launchConfigData, List<? extends Long> certIds, Long defaultCertId) { Map<String, Object> data = new HashMap<>(); data.put("name", lbName); data.put(LoadBalancerConstants.FIELD_LB_CONFIG_ID, lbConfig.getId()); data.put(LoadBalancerConstants.FIELD_LB_SERVICE_ID, service.getId()); data.put(LoadBalancerConstants.FIELD_LB_NETWORK_ID, getServiceNetworkId(service)); data.put( LoadBalancerConstants.FIELD_LB_INSTANCE_IMAGE_UUID, launchConfigData.get(InstanceConstants.FIELD_IMAGE_UUID)); data.put( LoadBalancerConstants.FIELD_LB_INSTANCE_URI_PREDICATE, DataAccessor.fields(service) .withKey(LoadBalancerConstants.FIELD_LB_INSTANCE_URI_PREDICATE) .withDefault("delegate:///") .as(String.class)); data.put("accountId", service.getAccountId()); if (defaultCertId != null) { data.put(LoadBalancerConstants.FIELD_LB_DEFAULT_CERTIFICATE_ID, defaultCertId); } if (certIds != null) { data.put(LoadBalancerConstants.FIELD_LB_CERTIFICATE_IDS, certIds); } return data; }
@SuppressWarnings("unchecked") private Map<String, Object> createComposeData( List<? extends Service> servicesToExport, boolean forDockerCompose) { Map<String, Object> data = new HashMap<String, Object>(); Collection<Long> servicesToExportIds = CollectionUtils.collect(servicesToExport, TransformerUtils.invokerTransformer("getId")); for (Service service : servicesToExport) { List<String> launchConfigNames = ServiceDiscoveryUtil.getServiceLaunchConfigNames(service); for (String launchConfigName : launchConfigNames) { boolean isPrimaryConfig = launchConfigName.equals(ServiceDiscoveryConstants.PRIMARY_LAUNCH_CONFIG_NAME); Map<String, Object> cattleServiceData = ServiceDiscoveryUtil.getServiceDataAsMap(service, launchConfigName, allocatorService); Map<String, Object> composeServiceData = new HashMap<>(); for (String cattleService : cattleServiceData.keySet()) { translateRancherToCompose( forDockerCompose, cattleServiceData, composeServiceData, cattleService, service); } if (forDockerCompose) { populateLinksForService(service, servicesToExportIds, composeServiceData); populateNetworkForService(service, launchConfigName, composeServiceData); populateVolumesForService(service, launchConfigName, composeServiceData); addExtraComposeParameters(service, launchConfigName, composeServiceData); populateSidekickLabels(service, composeServiceData, isPrimaryConfig); populateLoadBalancerServiceLabels(service, launchConfigName, composeServiceData); } if (!composeServiceData.isEmpty()) { data.put(isPrimaryConfig ? service.getName() : launchConfigName, composeServiceData); } } } return data; }
protected void populateResolveInfo( final boolean isVIPProvider, final Map<Long, IpAddress> instanceIdToHostIpMap, ServiceDnsEntryData serviceData, Service clientService, Map<String, Map<String, String>> resolve, Map<String, String> resolveCname, Service targetService, ServiceInstanceData targetInstance) { String targetInstanceName = targetInstance.getInstance() == null ? null : targetInstance.getInstance().getName(); boolean self = clientService.getId().equals(targetService.getId()); String dnsName = getDnsName(targetService, serviceData.getConsumeMap(), targetInstance.getExposeMap(), self); String targetIp = isVIPProvider ? clientService.getVip() : getIpAddress(targetInstance, false, instanceIdToHostIpMap); if (targetIp != null) { Map<String, String> ips = resolve.get(dnsName); if (ips == null) { ips = new HashMap<>(); } ips.put(targetIp, targetInstanceName); resolve.put(dnsName, ips); } else { String cname = targetInstance.getExposeMap().getHostName(); if (cname != null) { resolveCname.put(dnsName, cname); } } }
@Override public void reconcileServices(Collection<? extends Service> services) { for (Service service : services) { ConfigUpdateRequest request = ConfigUpdateRequest.forResource(Service.class, service.getId()); request.addItem(RECONCILE); request.withDeferredTrigger(true); itemManager.updateConfig(request); } }
@Override public void setVIP(Service service) { String requestedVip = service.getVip(); String vip = getServiceVIP(service, requestedVip); if (vip != null || requestedVip != null) { service.setVip(vip); objectManager.persist(service); } }
private boolean needToReconcile(List<Service> services, ServiceDeploymentPlanner planner) { for (Service service : services) { if (service.getState().equals(CommonStatesConstants.INACTIVE)) { return true; } } return planner.needToReconcileDeployment(); }
// TODO: Fix repeated DB call even if DB's cache no longer hits the disk private Set<String> getServiceNamesInStack(long stackId) { Set<String> servicesInEnv = new HashSet<String>(); List<? extends Service> services = objectManager.find(Service.class, SERVICE.STACK_ID, stackId, SERVICE.REMOVED, null); for (Service service : services) { servicesInEnv.add(service.getName().toLowerCase()); } return servicesInEnv; }
// TODO: Fix repeated DB call even if DB's cache no longer hits the disk private Set<String> getServiceNamesInStack(long environmentId) { Set<String> servicesInEnv = new HashSet<String>(); List<? extends Service> services = objectManager.find( Service.class, SERVICE.ENVIRONMENT_ID, environmentId, SERVICE.REMOVED, null); for (Service service : services) { servicesInEnv.add(service.getName()); } return servicesInEnv; }
private Map<Long, DeploymentUnitInstanceIdGenerator> populateUsedNames(List<Service> services) { Map<Long, DeploymentUnitInstanceIdGenerator> generator = new HashMap<>(); for (Service service : services) { Map<String, List<Integer>> launchConfigUsedIds = new HashMap<>(); for (String launchConfigName : ServiceDiscoveryUtil.getServiceLaunchConfigNames(service)) { List<Integer> usedIds = sdSvc.getServiceInstanceUsedSuffixes(service, launchConfigName); launchConfigUsedIds.put(launchConfigName, usedIds); } generator.put( service.getId(), new DeploymentUnitInstanceIdGeneratorImpl(launchConfigUsedIds)); } return generator; }
protected void validateLinks(final Map<String, ServiceLink> newServiceLinks) { for (ServiceLink link : newServiceLinks.values()) { Service targetService = objMgr.loadResource(Service.class, link.getServiceId()); if (targetService == null || targetService.getRemoved() != null || targetService.getState().equalsIgnoreCase(CommonStatesConstants.REMOVING)) { Object obfuscatedId = idFormatter.formatId("service", link.getServiceId()); String obfuscatedIdStr = obfuscatedId != null ? obfuscatedId.toString() : null; String svcName = targetService != null ? targetService.getName() : obfuscatedIdStr; ValidationErrorCodes.throwValidationError( ValidationErrorCodes.INVALID_REFERENCE, "Service " + svcName + " is removed"); } } }
protected void createListener( Service service, Map<Integer, LoadBalancerListener> listeners, LoadBalancerListenerPort port) { LoadBalancerListener listenerObj = objectManager.findOne( LoadBalancerListener.class, LOAD_BALANCER_LISTENER.SERVICE_ID, service.getId(), LOAD_BALANCER_LISTENER.SOURCE_PORT, port.getSourcePort(), LOAD_BALANCER_LISTENER.PRIVATE_PORT, port.getPrivatePort(), LOAD_BALANCER_LISTENER.TARGET_PORT, port.getTargetPort(), LOAD_BALANCER_LISTENER.REMOVED, null, LOAD_BALANCER_LISTENER.ACCOUNT_ID, service.getAccountId()); if (listenerObj == null) { listenerObj = objectManager.create( LoadBalancerListener.class, LOAD_BALANCER_LISTENER.NAME, getLoadBalancerName(service) + "_" + port.getPrivatePort(), LOAD_BALANCER_LISTENER.ACCOUNT_ID, service.getAccountId(), LOAD_BALANCER_LISTENER.SOURCE_PORT, port.getSourcePort(), LOAD_BALANCER_LISTENER.PRIVATE_PORT, port.getPrivatePort(), LOAD_BALANCER_LISTENER.TARGET_PORT, port.getTargetPort(), LOAD_BALANCER_LISTENER.SOURCE_PROTOCOL, port.getProtocol(), LOAD_BALANCER_LISTENER.TARGET_PROTOCOL, port.getProtocol(), LoadBalancerConstants.FIELD_LB_LISTENER_ALGORITHM, "roundrobin", LOAD_BALANCER_LISTENER.ACCOUNT_ID, service.getAccountId(), LOAD_BALANCER_LISTENER.SERVICE_ID, service.getId()); } objectProcessManager.executeProcess( LoadBalancerConstants.PROCESS_LB_LISTENER_CREATE, listenerObj, null); listeners.put(listenerObj.getPrivatePort(), listenerObj); }
@Override public void removeServiceMaps(Service service) { // 1. remove all maps to the services consumed by service specified for (ServiceConsumeMap map : consumeMapDao.findConsumedMapsToRemove(service.getId())) { objectProcessManager.scheduleProcessInstance( ServiceDiscoveryConstants.PROCESS_SERVICE_CONSUME_MAP_REMOVE, map, null); } // 2. remove all maps to the services consuming service specified for (ServiceConsumeMap map : consumeMapDao.findConsumingMapsToRemove(service.getId())) { objectProcessManager.scheduleProcessInstance( ServiceDiscoveryConstants.PROCESS_SERVICE_CONSUME_MAP_REMOVE, map, null); } }
@Override public void updateLoadBalancerService( Service service, List<? extends Long> certIds, Long defaultCertId) { LoadBalancer lb = objectManager.findOne( LoadBalancer.class, LOAD_BALANCER.SERVICE_ID, service.getId(), LOAD_BALANCER.REMOVED, null); if (lb != null) { Map<String, Object> data = new HashMap<>(); if (certIds == null) { certIds = DataAccessor.fields(service) .withKey(LoadBalancerConstants.FIELD_LB_CERTIFICATE_IDS) .asList(jsonMapper, Long.class); } if (defaultCertId == null) { defaultCertId = DataAccessor.fieldLong(service, LoadBalancerConstants.FIELD_LB_DEFAULT_CERTIFICATE_ID); } data.put(LoadBalancerConstants.FIELD_LB_CERTIFICATE_IDS, certIds); data.put(LoadBalancerConstants.FIELD_LB_DEFAULT_CERTIFICATE_ID, defaultCertId); DataUtils.getWritableFields(lb).putAll(data); objectManager.persist(lb); objectProcessManager.scheduleStandardProcess(StandardProcess.UPDATE, lb, data); } }
protected String getServiceVIP(Service service, String requestedVip) { if (service.getKind().equalsIgnoreCase(KIND.LOADBALANCERSERVICE.name()) || service.getKind().equalsIgnoreCase(KIND.SERVICE.name()) || service.getKind().equalsIgnoreCase(KIND.DNSSERVICE.name())) { Subnet vipSubnet = getServiceVipSubnet(service); PooledResourceOptions options = new PooledResourceOptions(); if (requestedVip != null) { options.setRequestedItem(requestedVip); } PooledResource resource = poolManager.allocateOneResource(vipSubnet, service, options); if (resource != null) { return resource.getName(); } } return null; }
private void addExtraComposeParameters( Service service, String launchConfigName, Map<String, Object> composeServiceData) { if (service.getKind().equalsIgnoreCase(ServiceDiscoveryConstants.KIND.DNSSERVICE.name())) { composeServiceData.put( ServiceDiscoveryConfigItem.IMAGE.getDockerName(), "rancher/dns-service"); } else if (service .getKind() .equalsIgnoreCase(ServiceDiscoveryConstants.KIND.LOADBALANCERSERVICE.name())) { composeServiceData.put( ServiceDiscoveryConfigItem.IMAGE.getDockerName(), "rancher/load-balancer-service"); } else if (service .getKind() .equalsIgnoreCase(ServiceDiscoveryConstants.KIND.EXTERNALSERVICE.name())) { composeServiceData.put( ServiceDiscoveryConfigItem.IMAGE.getDockerName(), "rancher/external-service"); } }
private void activateServices(final Service initialService, final List<Service> services) { /* * Trigger activate for all the services */ try { for (Service service : services) { if (service.getState().equalsIgnoreCase(CommonStatesConstants.INACTIVE)) { objectProcessMgr.scheduleStandardProcess(StandardProcess.ACTIVATE, service, null); } else if (service.getState().equalsIgnoreCase(CommonStatesConstants.ACTIVE)) { objectProcessMgr.scheduleStandardProcess(StandardProcess.UPDATE, service, null); } } } catch (IdempotentRetryException ex) { // if not caught, the process will keep on spinning forever // figure out better solution } }
protected long getServiceNetworkId(Service service) { Network network = ntwkDao.getNetworkForObject(service, NetworkConstants.KIND_HOSTONLY); if (network == null) { throw new RuntimeException( "Unable to find a network to activate a service " + service.getId()); } long networkId = network.getId(); return networkId; }
@Override public boolean isActiveService(Service service) { List<String> validStates = Arrays.asList( CommonStatesConstants.ACTIVATING, CommonStatesConstants.ACTIVE, CommonStatesConstants.UPDATING_ACTIVE, ServiceDiscoveryConstants.STATE_UPGRADING); return (validStates.contains(service.getState())); }
@Override public void addLoadBalancerServiceLink(Service service, LoadBalancerServiceLink serviceLink) { if (!service .getKind() .equalsIgnoreCase(ServiceDiscoveryConstants.KIND.LOADBALANCERSERVICE.name())) { return; } consumeMapDao.createServiceLink(service, serviceLink); }
@Override public void removeServiceLink(Service service, ServiceLink serviceLink) { ServiceConsumeMap map = consumeMapDao.findMapToRemove(service.getId(), serviceLink.getServiceId()); if (map != null) { objectProcessManager.scheduleProcessInstance( ServiceDiscoveryConstants.PROCESS_SERVICE_CONSUME_MAP_REMOVE, map, null); } }
@Override public void releaseVip(Service service) { String vip = service.getVip(); if (vip == null) { return; } List<Subnet> subnets = objectManager.find( Subnet.class, SUBNET.ACCOUNT_ID, service.getAccountId(), SUBNET.KIND, SubnetConstants.KIND_VIP_SUBNET); if (subnets.isEmpty()) { return; } Subnet subnet = subnets.get(0); poolManager.releaseResource(subnet, service); }
@Override public void upgrade( Service service, io.cattle.platform.core.addon.ServiceUpgradeStrategy strategy) { /* * TODO: move this and all downstream methods to a UpgradeManager with pluggable * strategies */ if (strategy instanceof ToServiceUpgradeStrategy) { ToServiceUpgradeStrategy toServiceStrategy = (ToServiceUpgradeStrategy) strategy; Service toService = objectManager.loadResource(Service.class, toServiceStrategy.getToServiceId()); if (toService == null || toService.getRemoved() != null) { return; } updateLinks(service, toServiceStrategy); } while (!doUpgrade(service, strategy)) { sleep(service, strategy); } }
@Override public void cloneConsumingServices(Service fromService, Service toService) { List<ServiceLink> linksToCreate = new ArrayList<>(); for (ServiceConsumeMap map : consumeMapDao.findConsumingServices(fromService.getId())) { ServiceLink link; List<String> ports = DataAccessor.fieldStringList(map, LoadBalancerConstants.FIELD_LB_TARGET_PORTS); if (ports == null) { link = new ServiceLink(toService.getId(), map.getName()); } else { link = new LoadBalancerServiceLink(toService.getId(), map.getName(), ports); } link.setConsumingServiceId(map.getServiceId()); linksToCreate.add(link); } consumeMapDao.createServiceLinks(linksToCreate); }
/** * @param fromService * @param strategy * @return true if the upgrade is done */ protected boolean doToServiceUpgrade(Service fromService, ToServiceUpgradeStrategy strategy) { Service toService = objectManager.loadResource(Service.class, strategy.getToServiceId()); if (toService == null || toService.getRemoved() != null) { return true; } try { deploymentMgr.activate(toService); if (!deploymentMgr.isHealthy(toService)) { return false; } deploymentMgr.activate(fromService); fromService = objectManager.reload(fromService); toService = objectManager.reload(toService); long batchSize = strategy.getBatchSize(); long finalScale = strategy.getFinalScale(); long toScale = getScale(toService); long totalScale = getScale(fromService) + toScale; if (totalScale > finalScale) { fromService = changeScale(fromService, 0 - Math.min(batchSize, totalScale - finalScale)); } else if (toScale < finalScale) { long max = Math.min(batchSize, finalScale - toScale); toService = changeScale(toService, Math.min(max, finalScale + batchSize - totalScale)); } if (getScale(fromService) == 0 && getScale(toService) != finalScale) { changeScale(toService, finalScale - getScale(toService)); } return getScale(fromService) == 0 && getScale(toService) == finalScale; } catch (TimeoutException e) { return false; } }
protected Service reload(Service service) { service = objectManager.reload(service); List<String> states = Arrays.asList( ServiceDiscoveryConstants.STATE_UPGRADING, ServiceDiscoveryConstants.STATE_ROLLINGBACK, ServiceDiscoveryConstants.STATE_RESTARTING); if (!states.contains(service.getState())) { throw new ProcessExecutionExitException(ExitReason.STATE_CHANGED); } return service; }
@Override public void addToLoadBalancerService(Service lbSvc, ServiceExposeMap instanceToRegister) { if (!lbSvc .getKind() .equalsIgnoreCase(ServiceDiscoveryConstants.KIND.LOADBALANCERSERVICE.name())) { return; } if (!isActiveService(lbSvc)) { return; } if (!exposeMapDao.isActiveMap(instanceToRegister)) { return; } LoadBalancer lb = objectManager.findOne( LoadBalancer.class, LOAD_BALANCER.SERVICE_ID, lbSvc.getId(), LOAD_BALANCER.REMOVED, null); if (lb == null) { return; } ServiceConsumeMap map = consumeMapDao.findNonRemovedMap(lbSvc.getId(), instanceToRegister.getServiceId(), null); if (map == null) { return; } LoadBalancerTargetInput target = new LoadBalancerTargetInput(instanceToRegister, map, jsonMapper); lbService.addTargetToLoadBalancer(lb, target); }
private void createNewServiceMaps(Service service, Map<Long, String> newServiceLinks) { for (Long consumedServiceId : newServiceLinks.keySet()) { String linkName = newServiceLinks.get(consumedServiceId); ServiceConsumeMap map = consumeMapDao.findNonRemovedMap(service.getId(), consumedServiceId, linkName); if (map == null) { map = objectManager.create( ServiceConsumeMap.class, SERVICE_CONSUME_MAP.SERVICE_ID, service.getId(), SERVICE_CONSUME_MAP.CONSUMED_SERVICE_ID, consumedServiceId, SERVICE_CONSUME_MAP.ACCOUNT_ID, service.getAccountId(), SERVICE_CONSUME_MAP.NAME, linkName); } if (map.getState().equalsIgnoreCase(CommonStatesConstants.REQUESTED)) { objectProcessManager.scheduleProcessInstanceAsync( ServiceDiscoveryConstants.PROCESS_SERVICE_CONSUME_MAP_CREATE, map, null); } } }