def command(options): """Interactively debug a hook remotely on a service unit. """ environment = get_environment(options) provider = environment.get_machine_provider() client = yield provider.connect() # Verify unit and retrieve ip address options.log.debug("Retrieving unit and machine information.") ip_address, unit = yield get_ip_address_for_unit( client, provider, options.unit_name) # Verify hook name if options.hook_names != ["*"]: options.log.debug("Verifying hook names...") yield validate_hooks(client, unit, options.hook_names) # Enable debug log options.log.debug( "Enabling hook debug on unit (%r)..." % options.unit_name) yield unit.enable_hook_debug(options.hook_names) # If we don't have an ipaddress the unit isn't up yet, wait for it. if not ip_address: options.log.info("Waiting for unit") # Wait and verify the agent is running. while 1: exists_d, watch_d = unit.watch_agent() exists = yield exists_d if exists: options.log.info("Unit running") break yield watch_d # Refetch the unit address ip_address, unit = yield get_ip_address_for_unit( client, provider, options.unit_name) # Connect via ssh and start tmux. options.log.info("Connecting to remote machine %s...", ip_address) # Encode the script as base64 so that we can deliver it with a single # ssh command while still retaining standard input on the terminal fd. script = SCRIPT.replace("{unit_name}", options.unit_name) script_b64 = base64.encodestring(script).replace("\n", "").strip() cmd = '"F=`mktemp`; echo %s | base64 -d > \$F; . \$F"' % script_b64 # Yield to facilitate testing. yield os.system( "ssh -t ubuntu@%s 'sudo /bin/bash -c %s'" % (ip_address, cmd)) options.log.info("Debug session ended.") # Ends hook debugging. yield client.close()
def test_get_ip_address_for_unit_with_unassigned_machine(self): """Service unit exists, but it doesn't have an assigned machine.""" service_state = yield self.add_service("wordpress") yield service_state.add_unit_state() e = yield self.assertFailure( get_ip_address_for_unit(self.client, self.provider, "wordpress/0"), ServiceUnitStateMachineNotAssigned) self.assertEqual( str(e), "Service unit 'wordpress/0' is not assigned to a machine")
def test_get_ip_address_for_unit_with_unassigned_machine(self): """Service unit exists, but it doesn't have an assigned machine.""" service_state = yield self.add_service("wordpress") yield service_state.add_unit_state() e = yield self.assertFailure( get_ip_address_for_unit(self.client, self.provider, "wordpress/0"), ServiceUnitStateMachineNotAssigned) self.assertEqual( str(e), "Service unit 'wordpress/0' is not assigned to a machine")
def test_get_ip_address_for_unit(self): """Verify can retrieve dns name, unit state with unit name.""" service_state = yield self.add_service("wordpress") unit_state = yield service_state.add_unit_state() machine_state = yield self.start_machine("steamcloud-1.com") yield unit_state.assign_to_machine(machine_state) yield unit_state.set_public_address("steamcloud-1.com") dns_name, lookedup_unit_state = yield get_ip_address_for_unit( self.client, self.provider, "wordpress/0") self.assertEqual(dns_name, "steamcloud-1.com") self.assertEqual(lookedup_unit_state.unit_name, "wordpress/0")
def test_get_ip_address_for_unit(self): """Verify can retrieve dns name, unit state with unit name.""" service_state = yield self.add_service("wordpress") unit_state = yield service_state.add_unit_state() machine_state = yield self.start_machine("steamcloud-1.com") yield unit_state.assign_to_machine(machine_state) yield unit_state.set_public_address("steamcloud-1.com") dns_name, lookedup_unit_state = yield get_ip_address_for_unit( self.client, self.provider, "wordpress/0") self.assertEqual(dns_name, "steamcloud-1.com") self.assertEqual(lookedup_unit_state.unit_name, "wordpress/0")
def command(options): """Launch an ssh shell on the given unit or machine. """ environment = get_environment(options) provider = environment.get_machine_provider() client = yield provider.connect() label = machine = unit = None # First check if it's a juju machine id if options.unit_or_machine.isdigit(): options.log.debug( "Fetching machine address using juju machine id.") ip_address, machine = yield get_ip_address_for_machine( client, provider, options.unit_or_machine) machine.get_ip_address = get_ip_address_for_machine label = "machine" # Next check if it's a unit elif "/" in options.unit_or_machine: options.log.debug( "Fetching machine address using unit name.") ip_address, unit = yield get_ip_address_for_unit( client, provider, options.unit_or_machine) unit.get_ip_address = get_ip_address_for_unit label = "unit" else: raise MachineStateNotFound(options.unit_or_machine) agent_state = machine or unit # Now verify the relevant agent is operational via its agent. exists_d, watch_d = agent_state.watch_agent() exists = yield exists_d if not exists: # If not wait on it. options.log.info("Waiting for %s to come up." % label) yield watch_d # Double check the address we have is valid, else refetch. if ip_address is None: ip_address, machine = yield agent_state.get_ip_address( client, provider, options.unit_or_machine) yield client.close() options.log.info("Connecting to %s %s at %s", label, options.unit_or_machine, ip_address) open_ssh(options.ssh_flags, ip_address, options.ssh_command)
def _expand_unit_or_machine(client, provider, path): """Expands service unit or machine ID into DNS name""" parts = path.split(":") if len(parts) > 1: remote_system = parts[0] ip_address = None if remote_system.isdigit(): # machine id, will not pick up dotted IP addresses ip_address, _ = yield get_ip_address_for_machine( client, provider, remote_system) elif "/" in remote_system: # service unit ip_address, _ = yield get_ip_address_for_unit( client, provider, remote_system) if ip_address: returnValue("ubuntu@%s:%s" % (ip_address, ":".join(parts[1:]))) returnValue(path) # no need to expand
def _expand_unit_or_machine(client, provider, path): """Expands service unit or machine ID into DNS name""" parts = path.split(":") if len(parts) > 1: remote_system = parts[0] ip_address = None if remote_system.isdigit(): # machine id, will not pick up dotted IP addresses ip_address, _ = yield get_ip_address_for_machine( client, provider, remote_system) elif "/" in remote_system: # service unit ip_address, _ = yield get_ip_address_for_unit( client, provider, remote_system) if ip_address: returnValue("ubuntu@%s:%s" % (ip_address, ":".join(parts[1:]))) returnValue(path) # no need to expand
def command(options): """Launch an ssh shell on the given unit or machine. """ environment = get_environment(options) provider = environment.get_machine_provider() client = yield provider.connect() label = machine = unit = None # First check if it's a juju machine id if options.unit_or_machine.isdigit(): options.log.debug("Fetching machine address using juju machine id.") ip_address, machine = yield get_ip_address_for_machine( client, provider, options.unit_or_machine) machine.get_ip_address = get_ip_address_for_machine label = "machine" # Next check if it's a unit elif "/" in options.unit_or_machine: options.log.debug("Fetching machine address using unit name.") ip_address, unit = yield get_ip_address_for_unit( client, provider, options.unit_or_machine) unit.get_ip_address = get_ip_address_for_unit label = "unit" else: raise MachineStateNotFound(options.unit_or_machine) agent_state = machine or unit # Now verify the relevant agent is operational via its agent. exists_d, watch_d = agent_state.watch_agent() exists = yield exists_d if not exists: # If not wait on it. options.log.info("Waiting for %s to come up." % label) yield watch_d # Double check the address we have is valid, else refetch. if ip_address is None: ip_address, machine = yield agent_state.get_ip_address( client, provider, options.unit_or_machine) yield client.close() options.log.info("Connecting to %s %s at %s", label, options.unit_or_machine, ip_address) open_ssh(options.ssh_flags, ip_address, options.ssh_command)