/** * Returns a queued {@link Task} which provisions a machine in the given location and returns that * machine. The task can be used as a supplier to subsequent methods. */ protected Task<MachineLocation> provisionAsync(final MachineProvisioningLocation<?> location) { return DynamicTasks.queue( Tasks.<MachineLocation>builder() .displayName("provisioning (" + location.getDisplayName() + ")") .body(new ProvisionMachineTask(location)) .build()); }
/** * 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); }
/** * Some clouds (e.g. Rackspace) give us VMs that have two nics: one for private and one for * public. If the private IP is used then it doesn't work, even for a cluster purely internal to * Rackspace! * * <p>TODO Ugly. Need to understand more and find a better fix. Perhaps in Cassandra itself if * necessary. Also need to investigate further: - does it still fail if BroadcastAddress is set to * private IP? - is `openIptables` opening it up for both interfaces? - for aws->rackspace comms * between nodes (thus using the public IP), will it be listening on an accessible port? - ideally * do a check, open a server on one port on the machine, see if it is contactable on the public * address; and set that as a flag on the cloud */ protected void setCloudPreferredSensorNames() { if (detectedCloudSensors.get()) return; synchronized (detectedCloudSensors) { if (detectedCloudSensors.get()) return; MachineProvisioningLocation<?> loc = getProvisioningLocation(); if (loc != null) { try { Method method = loc.getClass().getMethod("getProvider"); method.setAccessible(true); String provider = (String) method.invoke(loc); String result = "(nothing special)"; if (provider != null) { if (provider.contains("rackspace") || provider.contains("cloudservers") || provider.contains("softlayer")) { /* These clouds have 2 NICs and it has to be consistent, so use public IP here to allow external access; * (TODO internal access could be configured to improve performance / lower cost, * if we know all nodes are visible to each other) */ if (getConfig(LISTEN_ADDRESS_SENSOR) == null) setConfig(LISTEN_ADDRESS_SENSOR, CassandraNode.ADDRESS.getName()); if (getConfig(BROADCAST_ADDRESS_SENSOR) == null) setConfig(BROADCAST_ADDRESS_SENSOR, CassandraNode.ADDRESS.getName()); result = "public IP for both listen and broadcast"; } else if (provider.contains("google-compute")) { /* Google nodes cannot reach themselves/each-other on the public IP, * and there is no hostname, so use private IP here */ if (getConfig(LISTEN_ADDRESS_SENSOR) == null) setConfig(LISTEN_ADDRESS_SENSOR, CassandraNode.SUBNET_HOSTNAME.getName()); if (getConfig(BROADCAST_ADDRESS_SENSOR) == null) setConfig(BROADCAST_ADDRESS_SENSOR, CassandraNode.SUBNET_HOSTNAME.getName()); result = "private IP for both listen and broadcast"; } } log.debug( "Cassandra NICs inferred {} for {}; using location {}, based on provider {}", new Object[] {result, this, loc, provider}); } catch (Exception e) { log.debug( "Cassandra NICs auto-detection failed for {} in location {}: {}", new Object[] {this, loc, e}); } } detectedCloudSensors.set(true); } }
public String getRackName() { String name = getAttribute(CassandraNode.RACK_NAME); if (name == null) { MachineLocation machine = getMachineOrNull(); MachineProvisioningLocation<?> provisioningLocation = getProvisioningLocation(); if (machine != null) { name = machine.getConfig(CloudLocationConfig.CLOUD_AVAILABILITY_ZONE_ID); } if (name == null && provisioningLocation != null) { name = provisioningLocation.getConfig(CloudLocationConfig.CLOUD_AVAILABILITY_ZONE_ID); } if (name == null) { name = "UNKNOWN_RACK"; } setAttribute((AttributeSensor<String>) RACK_NAME, name); } return name; }
// referenced by cassandra-rackdc.properties, read by some of the cassandra snitches public String getDatacenterName() { String name = getAttribute(CassandraNode.DATACENTER_NAME); if (name == null) { MachineLocation machine = getMachineOrNull(); MachineProvisioningLocation<?> provisioningLocation = getProvisioningLocation(); if (machine != null) { name = machine.getConfig(CloudLocationConfig.CLOUD_REGION_ID); } if (name == null && provisioningLocation != null) { name = provisioningLocation.getConfig(CloudLocationConfig.CLOUD_REGION_ID); } if (name == null) { name = "UNKNOWN_DATACENTER"; } setAttribute((AttributeSensor<String>) DATACENTER_NAME, name); } return name; }
public MachineLocation call() throws Exception { // Blocks if a latch was configured. entity().getConfig(BrooklynConfigKeys.PROVISION_LATCH); final Map<String, Object> flags = obtainProvisioningFlags(location); if (!(location instanceof LocalhostMachineProvisioningLocation)) log.info( "Starting {}, obtaining a new location instance in {} with ports {}", new Object[] {entity(), location, flags.get("inboundPorts")}); entity().sensors().set(SoftwareProcess.PROVISIONING_LOCATION, location); Transition expectedState = entity().sensors().get(Attributes.SERVICE_STATE_EXPECTED); // BROOKLYN-263: see corresponding code in doStop() if (expectedState != null && (expectedState.getState() == Lifecycle.STOPPING || expectedState.getState() == Lifecycle.STOPPED)) { throw new IllegalStateException( "Provisioning aborted before even begun for " + entity() + " in " + location + " (presumably by a concurrent call to stop"); } entity() .sensors() .set(AttributesInternal.INTERNAL_PROVISIONING_TASK_STATE, ProvisioningTaskState.RUNNING); MachineLocation machine; try { machine = Tasks.withBlockingDetails( "Provisioning machine in " + location, new ObtainLocationTask(location, flags)); entity().sensors().set(INTERNAL_PROVISIONED_MACHINE, machine); } finally { entity().sensors().remove(AttributesInternal.INTERNAL_PROVISIONING_TASK_STATE); } if (machine == null) { throw new NoMachinesAvailableException( "Failed to obtain machine in " + location.toString()); } if (log.isDebugEnabled()) { log.debug( "While starting {}, obtained new location instance {}", entity(), (machine instanceof SshMachineLocation ? machine + ", details " + ((SshMachineLocation) machine).getUser() + ":" + Sanitizer.sanitize(((SshMachineLocation) machine).config().getLocalBag()) : machine)); } return machine; }
public MachineLocation call() throws NoMachinesAvailableException { return location.obtain(flags); }