/** * Stop and release the {@link MachineLocation} the entity is provisioned at. * * <p>Can run synchronously or not, caller will submit/queue as needed, and will block on any * submitted tasks. */ protected StopMachineDetails<Integer> stopAnyProvisionedMachines() { @SuppressWarnings("unchecked") MachineProvisioningLocation<MachineLocation> provisioner = entity().getAttribute(SoftwareProcess.PROVISIONING_LOCATION); if (Iterables.isEmpty(entity().getLocations())) { log.debug("No machine decommissioning necessary for " + entity() + " - no locations"); return new StopMachineDetails<Integer>( "No machine decommissioning necessary - no locations", 0); } // Only release this machine if we ourselves provisioned it (e.g. it might be running other // services) if (provisioner == null) { log.debug("No machine decommissioning necessary for " + entity() + " - did not provision"); return new StopMachineDetails<Integer>( "No machine decommissioning necessary - did not provision", 0); } Location machine = getLocation(null); if (!(machine instanceof MachineLocation)) { log.debug( "No decommissioning necessary for " + entity() + " - not a machine location (" + machine + ")"); return new StopMachineDetails<Integer>( "No machine decommissioning necessary - not a machine (" + machine + ")", 0); } entity() .sensors() .set(AttributesInternal.INTERNAL_TERMINATION_TASK_STATE, ProvisioningTaskState.RUNNING); try { clearEntityLocationAttributes(machine); provisioner.release((MachineLocation) machine); } finally { // TODO On exception, should we add the machine back to the entity (because it might not // really be terminated)? // Do we need a better exception hierarchy for that? entity().sensors().remove(AttributesInternal.INTERNAL_TERMINATION_TASK_STATE); } return new StopMachineDetails<Integer>("Decommissioned " + machine, 1); }
/** * Suspend the {@link MachineLocation} the entity is provisioned at. * * <p>Expects the entity's {@link SoftwareProcess#PROVISIONING_LOCATION provisioner} to be capable * of {@link SuspendsMachines suspending machines}. * * @throws java.lang.UnsupportedOperationException if the entity's provisioner cannot suspend * machines. * @see MachineManagementMixins.SuspendsMachines */ protected StopMachineDetails<Integer> suspendAnyProvisionedMachines() { @SuppressWarnings("unchecked") MachineProvisioningLocation<MachineLocation> provisioner = entity().getAttribute(SoftwareProcess.PROVISIONING_LOCATION); if (Iterables.isEmpty(entity().getLocations())) { log.debug("No machine decommissioning necessary for " + entity() + " - no locations"); return new StopMachineDetails<>("No machine suspend necessary - no locations", 0); } // Only release this machine if we ourselves provisioned it (e.g. it might be running other // services) if (provisioner == null) { log.debug("No machine decommissioning necessary for " + entity() + " - did not provision"); return new StopMachineDetails<>("No machine suspend necessary - did not provision", 0); } Location machine = getLocation(null); if (!(machine instanceof MachineLocation)) { log.debug( "No decommissioning necessary for " + entity() + " - not a machine location (" + machine + ")"); return new StopMachineDetails<>( "No machine suspend necessary - not a machine (" + machine + ")", 0); } if (!(provisioner instanceof SuspendsMachines)) { log.debug("Location provisioner ({}) cannot suspend machines", provisioner); throw new UnsupportedOperationException( "Location provisioner cannot suspend machines: " + provisioner); } clearEntityLocationAttributes(machine); SuspendsMachines.class.cast(provisioner).suspendMachine(MachineLocation.class.cast(machine)); return new StopMachineDetails<>("Suspended " + machine, 1); }