/** * Update the {@link #partitionActiveNetworkTags} map by removing any {@code key} values which * no longer have a corresponding service registration. * * @throws PersistenceException */ private void removeStalePartitions() throws PersistenceException { Set<String> partitions = Sets.newHashSet(); for (ServiceConfiguration cc : ServiceConfigurations.list(ClusterController.class)) { partitions.add(cc.getPartition()); } for (String stalePartition : Sets.difference(this.activeTagsByPartition.keySet(), partitions)) { this.activeTagsByPartition.removeAll(stalePartition); } }
@Override public void fireDisable(final ServiceConfiguration config) { if (config.isVmLocal() && noOtherEnabled(config)) try { WorkflowClientManager.stop(); } catch (Exception e) { logger.error("Error stopping workflow client", e); } }
@Override public void fireEnable(final ServiceConfiguration config) throws ServiceRegistrationException { if (config.isVmLocal() && noOtherEnabled(config)) try { WorkflowClientManager.start(); } catch (Exception e) { throw new ServiceRegistrationException("Error creating workflow client", e); } }
@Override public void fireEnable(ServiceConfiguration config) throws ServiceRegistrationException { if (!config.isVmLocal()) { for (Host h : Hosts.list()) { if (h.getHostAddresses().contains(config.getInetAddress())) { EventRecord.here( EucalyptusBuilder.class, EventType.COMPONENT_SERVICE_ENABLED, config.toString()) .info(); return; } } throw Faults.failure( config, Exceptions.error( "There is no host in the system (yet) for the given cloud controller configuration: " + config.getFullName() + ".\nHosts are: " + Hosts.list())); } else if (config.isVmLocal() && !Hosts.isCoordinator()) { throw Faults.failure( config, Exceptions.error( "This cloud controller " + config.getFullName() + " is not currently the coordinator " + Hosts.list())); } }
@Override public boolean apply(ServiceConfiguration config) { if (config.isVmLocal()) { if (!Databases.isSynchronized()) { throw Faults.failure( config, Exceptions.error( config.getFullName() + ":fireCheck(): eucalyptus service " + config.getFullName() + " is currently synchronizing: " + Hosts.getCoordinator())); } else if (Topology.isEnabledLocally(Eucalyptus.class)) { throw Faults.failure( config, Exceptions.error( config.getFullName() + ":fireCheck(): eucalyptus service " + config.getFullName() + " cant be enabled when it is not the coordinator: " + Hosts.getCoordinator())); } else { LOG.debug( config.getFullName() + ":fireCheck() completed with coordinator currently: " + Hosts.getCoordinator()); } } return true; }
public static DestroyServiceResponseType destroyService(final DestroyServiceType request) throws Exception { DestroyServiceResponseType reply = request.getReply(); for (final ServiceId serviceInfo : request.getServices()) { try { final ServiceConfiguration service = TypeMappers.transform(serviceInfo, ServiceConfiguration.class); if (service.isVmLocal()) { try { Topology.destroy(service).get(); } catch (final IllegalStateException ex) { LOG.error(ex, ex); } } reply.getServices().add(serviceInfo); } catch (final Exception ex) { LOG.error(ex); Logs.extreme().debug(ex, ex); } } return reply; }
public static DisableServiceResponseType disableService(final DisableServiceType request) throws Exception { final DisableServiceResponseType reply = request.getReply(); for (final ServiceId serviceInfo : request.getServices()) { try { final Component comp = Components.lookup(serviceInfo.getType()); final ServiceConfiguration service = TypeMappers.transform(serviceInfo, ServiceConfiguration.class); if (service.isVmLocal()) { try { Topology.disable(service).get(); reply.getServices().add(serviceInfo); } catch (final IllegalStateException ex) { LOG.error(ex, ex); throw ex; } } } catch (final NoSuchElementException ex) { LOG.error(ex, ex); throw ex; } } return reply; }
@Override public void fireCheck(ServiceConfiguration config) throws ServiceRegistrationException { Host coordinator = Hosts.getCoordinator(); if (coordinator == null) { throw Faults.failure( config, Exceptions.error( config.getFullName() + ":fireCheck(): failed to lookup coordinator (" + coordinator + ").")); } else if (coordinator.isLocalHost()) { Check.COORDINATOR.apply(config); } else if (!coordinator.isLocalHost()) { Check.SECONDARY.apply(config); } }
private void convertImages(final List<ImageInfo> images) { for (final ImageInfo image : images) { if (!(image instanceof MachineImageInfo)) continue; try { final MachineImageInfo machineImage = (MachineImageInfo) image; final String kernelId = machineImage.getKernelId(); final String ramdiskId = machineImage.getRamdiskId(); if (kernelId == null || ramdiskId == null) { LOG.warn( String.format( "Kernel and ramdisk are not found for the image %s", image.getDisplayName())); continue; } final KernelImageInfo kernel = Images.lookupKernel(kernelId); final RamdiskImageInfo ramdisk = Images.lookupRamdisk(ramdiskId); final ServiceConfiguration osg = Topology.lookup(ObjectStorage.class); final URI osgUri = osg.getUri(); final String osgPrefix = String.format( "%s://%s:%d%s", osgUri.getScheme(), osgUri.getHost(), osgUri.getPort(), osgUri.getPath()); final String kernelManifest = String.format("%s/%s", osgPrefix, kernel.getManifestLocation()); final String ramdiskManifest = String.format("%s/%s", osgPrefix, ramdisk.getManifestLocation()); final String machineManifest = String.format("%s/%s", osgPrefix, machineImage.getManifestLocation()); final String[] tokens = machineImage.getRunManifestLocation().split("/"); final String bucket = tokens[0]; final String prefix = tokens[1].replace(".manifest.xml", ""); String taskId = null; try { final ImportImageBuilder builder = new ImportImageBuilder(); final ImportImageTask task = new ImportImageTask( builder .withArchitecture(machineImage.getArchitecture().name()) .withBucket(bucket) .withPrefix(prefix) .withKernel( kernel.getDisplayName(), kernelManifest, kernel.getImageSizeBytes()) .withRamdisk( ramdisk.getDisplayName(), ramdiskManifest, ramdisk.getImageSizeBytes()) .withMachineImage( machineImage.getDisplayName(), machineManifest, machineImage.getImageSizeBytes()) .withBucketUploadPolicy(bucket, prefix)); final CheckedListenableFuture<Boolean> result = task.dispatch(); if (result.get()) { taskId = task.getTaskId(); } } catch (final Exception ex) { throw ex; } if (taskId == null) throw new Exception("ImportImage Task id is null"); Images.setConversionTaskId(machineImage.getDisplayName(), taskId); } catch (final Exception ex) { LOG.error("Failed to convert the image: " + image.getDisplayName(), ex); try { this.cleanupBuckets(Lists.newArrayList(image), false); resetImagePendingAvailable(image.getDisplayName(), "Failed to request conversion"); } catch (final Exception ex2) { LOG.error( "Failed to cleanup the image's system bucket; setting image state failed: " + image.getDisplayName()); try { Images.setImageState(image.getDisplayName(), ImageMetadata.State.failed); } catch (final Exception ex3) {; } } } } }
@Override public void fireEvent(final Hertz event) { final long defaultPollIntervalSeconds = TimeUnit.MINUTES.toSeconds(DEFAULT_POLL_INTERVAL_MINS); if (!Bootstrap.isOperational() || !BootstrapArgs.isCloudController() || !event.isAsserted(defaultPollIntervalSeconds)) { return; } else { if (DEFAULT_POLL_INTERVAL_MINS >= 1) { COLLECTION_INTERVAL_TIME_MS = ((int) TimeUnit.MINUTES.toMillis(DEFAULT_POLL_INTERVAL_MINS) / 2); } else { COLLECTION_INTERVAL_TIME_MS = 0; } if (COLLECTION_INTERVAL_TIME_MS == 0 || HISTORY_SIZE > 15 || HISTORY_SIZE < 1) { LOG.debug("The instance usage report is disabled"); } else if (COLLECTION_INTERVAL_TIME_MS <= MAX_WRITE_INTERVAL_MS) { try { if (event.isAsserted(defaultPollIntervalSeconds)) { if (Bootstrap.isFinished() && Hosts.isCoordinator()) { CloudWatchHelper.DefaultInstanceInfoProvider.refresh(); for (final ServiceConfiguration ccConfig : Topology.enabledServices(ClusterController.class)) { final String ccHost = ccConfig.getHostName(); if (busyHosts.replace(ccHost, false, true) || busyHosts.putIfAbsent(ccHost, true) == null) { Threads.lookup(Reporting.class, DescribeSensorsListener.class) .submit( new Callable<Object>() { @Override public Object call() throws Exception { final ExecutorService executorService = Threads.lookup( Reporting.class, DescribeSensorsListener.class, "response-processing") .limitTo(4); final long startTime = System.currentTimeMillis(); try { final List<String> allInstanceIds = VmInstances.listWithProjection( VmInstances.instanceIdProjection(), VmInstance.criterion(VmState.RUNNING), VmInstance.zoneCriterion(ccConfig.getPartition()), VmInstance.nonNullNodeCriterion()); final Iterable<List<String>> processInts = Iterables.partition(allInstanceIds, SENSOR_QUERY_BATCH_SIZE); for (final List<String> instIds : processInts) { final ArrayList<String> instanceIds = Lists.newArrayList(instIds); /** * Here this is hijacking the sensor callback in order to control * the thread of execution used when firing */ final DescribeSensorCallback msgCallback = new DescribeSensorCallback( HISTORY_SIZE, COLLECTION_INTERVAL_TIME_MS, instanceIds) { @Override public void fireException(Throwable e) {} @Override public void fire(DescribeSensorsResponse msg) {} }; /** * Here we actually get the future reference to the result and on * a response processing thread, invoke .fire(). */ final DescribeSensorsResponse response = AsyncRequests.newRequest(msgCallback) .dispatch(ccConfig) .get(); executorService.submit( new Runnable() { @Override public void run() { try { new DescribeSensorCallback( HISTORY_SIZE, COLLECTION_INTERVAL_TIME_MS, instanceIds) .fire(response); } catch (Exception e) { Exceptions.maybeInterrupted(e); } } }); } } finally { /** Only and finally set the busy bit back to false. */ busyHosts.put(ccHost, false); LOG.debug( "Sensor polling for " + ccHost + " took " + (System.currentTimeMillis() - startTime) + "ms"); } return null; } }); } else { LOG.warn( "Skipping sensors polling for " + ccHost + ", previous poll not complete."); } } } } } catch (Exception ex) { LOG.error("Unable to listen for describe sensors events", ex); } } else { LOG.error( "DEFAULT_POLL_INTERVAL_MINS : " + DEFAULT_POLL_INTERVAL_MINS + " must be less than 1440 minutes"); } } }
public DetachVolumeResponseType detach(DetachVolumeType request) throws EucalyptusCloudException { DetachVolumeResponseType reply = (DetachVolumeResponseType) request.getReply(); Context ctx = Contexts.lookup(); Volume vol; try { vol = Volumes.lookup(ctx.getUserFullName().asAccountFullName(), request.getVolumeId()); } catch (Exception ex1) { throw new EucalyptusCloudException("Volume does not exist: " + request.getVolumeId()); } if (!RestrictedTypes.filterPrivileged().apply(vol)) { throw new EucalyptusCloudException( "Not authorized to detach volume " + request.getVolumeId() + " by " + ctx.getUser().getName()); } VmInstance vm = null; AttachedVolume volume = null; try { VmVolumeAttachment vmVolAttach = VmInstances.lookupVolumeAttachment(request.getVolumeId()); volume = VmVolumeAttachment.asAttachedVolume(vmVolAttach.getVmInstance()).apply(vmVolAttach); vm = vmVolAttach.getVmInstance(); } catch (NoSuchElementException ex) { /** no such attachment * */ } if (volume == null) { throw new EucalyptusCloudException("Volume is not attached: " + request.getVolumeId()); } if (!RestrictedTypes.filterPrivileged().apply(vm)) { throw new EucalyptusCloudException( "Not authorized to detach volume from instance " + request.getInstanceId() + " by " + ctx.getUser().getName()); } if (!vm.getInstanceId().equals(request.getInstanceId()) && request.getInstanceId() != null && !request.getInstanceId().equals("")) { throw new EucalyptusCloudException( "Volume is not attached to instance: " + request.getInstanceId()); } if (request.getDevice() != null && !request.getDevice().equals("") && !volume.getDevice().equals(request.getDevice())) { throw new EucalyptusCloudException( "Volume is not attached to device: " + request.getDevice()); } Cluster cluster = null; ServiceConfiguration ccConfig = null; try { ccConfig = Topology.lookup(ClusterController.class, vm.lookupPartition()); cluster = Clusters.lookup(ccConfig); } catch (NoSuchElementException e) { LOG.debug(e, e); throw new EucalyptusCloudException( "Cluster does not exist in partition: " + vm.getPartition()); } ServiceConfiguration scVm; try { scVm = Topology.lookup(Storage.class, vm.lookupPartition()); } catch (Exception ex) { LOG.error(ex, ex); throw new EucalyptusCloudException( "Failed to lookup SC for partition: " + vm.getPartition(), ex); } request.setVolumeId(volume.getVolumeId()); request.setRemoteDevice(volume.getRemoteDevice()); request.setDevice(volume.getDevice().replaceAll("unknown,requested:", "")); request.setInstanceId(vm.getInstanceId()); VolumeDetachCallback ncDetach = new VolumeDetachCallback(request); try { AsyncRequests.sendSync(scVm, new DetachStorageVolumeType(volume.getVolumeId())); } catch (Exception e) { LOG.debug(e); Logs.extreme().debug(e, e); // GRZE: attach is idempotent, failure here is ok. throw new EucalyptusCloudException( // e.getMessage( ) ); } AsyncRequests.newRequest(ncDetach).dispatch(cluster.getConfiguration()); EventRecord.here(VolumeManager.class, EventClass.VOLUME, EventType.VOLUME_DETACH) .withDetails(vm.getOwner().toString(), volume.getVolumeId(), "instance", vm.getInstanceId()) .withDetails("cluster", ccConfig.getFullName().toString()) .info(); volume.setStatus("detaching"); reply.setDetachedVolume(volume); return reply; }
public AttachVolumeResponseType AttachVolume(AttachVolumeType request) throws EucalyptusCloudException { AttachVolumeResponseType reply = (AttachVolumeResponseType) request.getReply(); final String deviceName = request.getDevice(); final String volumeId = request.getVolumeId(); final Context ctx = Contexts.lookup(); if (request.getDevice() == null || request.getDevice().endsWith("sda") || request.getDevice().endsWith("sdb")) { throw new EucalyptusCloudException("Invalid device name specified: " + request.getDevice()); } VmInstance vm = null; try { vm = RestrictedTypes.doPrivileged(request.getInstanceId(), VmInstance.class); } catch (NoSuchElementException ex) { LOG.debug(ex, ex); throw new EucalyptusCloudException("Instance does not exist: " + request.getInstanceId(), ex); } catch (Exception ex) { LOG.debug(ex, ex); throw new EucalyptusCloudException(ex.getMessage(), ex); } AccountFullName ownerFullName = ctx.getUserFullName().asAccountFullName(); Volume volume = Volumes.lookup(ownerFullName, volumeId); if (!RestrictedTypes.filterPrivileged().apply(volume)) { throw new EucalyptusCloudException( "Not authorized to attach volume " + request.getVolumeId() + " by " + ctx.getUser().getName()); } try { vm.lookupVolumeAttachmentByDevice(deviceName); throw new EucalyptusCloudException( "Already have a device attached to: " + request.getDevice()); } catch (NoSuchElementException ex1) { /** no attachment * */ } try { VmInstances.lookupVolumeAttachment(volumeId); throw new EucalyptusCloudException("Volume already attached: " + request.getVolumeId()); } catch (NoSuchElementException ex1) { /** no attachment * */ } Partition volPartition = Partitions.lookupByName(volume.getPartition()); ServiceConfiguration sc = Topology.lookup(Storage.class, volPartition); ServiceConfiguration scVm = Topology.lookup(Storage.class, vm.lookupPartition()); if (!sc.equals(scVm)) { throw new EucalyptusCloudException( "Can only attach volumes in the same zone: " + request.getVolumeId()); } ServiceConfiguration ccConfig = Topology.lookup(ClusterController.class, vm.lookupPartition()); AttachStorageVolumeResponseType scAttachResponse; try { AttachStorageVolumeType req = new AttachStorageVolumeType(Nodes.lookupIqn(vm), volume.getDisplayName()); scAttachResponse = AsyncRequests.sendSync(sc, req); } catch (Exception e) { LOG.debug(e, e); throw new EucalyptusCloudException(e.getMessage(), e); } request.setRemoteDevice(scAttachResponse.getRemoteDeviceString()); AttachedVolume attachVol = new AttachedVolume( volume.getDisplayName(), vm.getInstanceId(), request.getDevice(), request.getRemoteDevice()); vm.addTransientVolume(deviceName, scAttachResponse.getRemoteDeviceString(), volume); AsyncRequests.newRequest(new VolumeAttachCallback(request)).dispatch(ccConfig); EventRecord.here(VolumeManager.class, EventClass.VOLUME, EventType.VOLUME_ATTACH) .withDetails( volume.getOwner().toString(), volume.getDisplayName(), "instance", vm.getInstanceId()) .withDetails("partition", vm.getPartition().toString()) .info(); reply.setAttachedVolume(attachVol); return reply; }
/** * Update the cache of currently active network tags based on the most recent reported value. * * @param cluster * @param activeNetworks */ private void update(ServiceConfiguration cluster, List<NetworkInfoType> activeNetworks) { removeStalePartitions(); Set<Integer> activeTags = Sets.newHashSet(Lists.transform(activeNetworks, ActiveTags.INSTANCE)); this.activeTagsByPartition.replaceValues(cluster.getPartition(), activeTags); }