/usr/share/pyshared/juju/control/utils.py is in juju-0.7 0.7-0ubuntu2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 | import os
from itertools import tee
from twisted.internet.defer import inlineCallbacks, returnValue
from juju.environment.errors import EnvironmentsConfigError
from juju.state.errors import ServiceUnitStateMachineNotAssigned
from juju.state.environment import EnvironmentStateManager
from juju.state.machine import MachineStateManager
from juju.state.service import ServiceStateManager
def get_environment(options):
env_name = options.environment or os.environ.get("JUJU_ENV")
environment = options.environments.get(env_name)
if environment is None and options.environment:
raise EnvironmentsConfigError(
"Invalid environment %r" % options.environment)
elif environment is None:
environment = options.environments.get_default()
return environment
def sync_environment_state(client, config, name):
"""Push the local environment config to zookeeper.
This needs to be done:
* On any command which can cause the provisioning agent to take action
against the provider (ie create/destroy a machine), because the PA
needs to use credentials stored in the environment config to do so.
* On any command which uses constraints-related code (even if indirectly)
because Constraints objects are provider-specific, and need to be
created with the help of a MachineProvider; and the only way state code
can get a MachineProvider is by getting one from ZK (we certainly don't
want to thread the relevant provider from juju.control and/or the PA
itself all the way through the state code). So, we sync, to ensure
that state code can use an EnvironmentStateManager to get a provider.
"""
esm = EnvironmentStateManager(client)
return esm.set_config_state(config, name)
@inlineCallbacks
def get_ip_address_for_machine(client, provider, machine_id):
"""Returns public DNS name and machine state for the machine id.
:param client: a connected zookeeper client.
:param provider: the `MachineProvider` in charge of the juju.
:param machine_id: machine ID of the desired machine to connect to.
:return: tuple of the DNS name and a `MachineState`.
"""
manager = MachineStateManager(client)
machine_state = yield manager.get_machine_state(machine_id)
instance_id = yield machine_state.get_instance_id()
provider_machine = yield provider.get_machine(instance_id)
returnValue((provider_machine.dns_name, machine_state))
@inlineCallbacks
def get_ip_address_for_unit(client, provider, unit_name):
"""Returns public DNS name and unit state for the service unit.
:param client: a connected zookeeper client.
:param provider: the `MachineProvider` in charge of the juju.
:param unit_name: service unit running on a machine to connect to.
:return: tuple of the DNS name and a `MachineState`.
:raises: :class:`juju.state.errors.ServiceUnitStateMachineNotAssigned`
"""
manager = ServiceStateManager(client)
service_unit = yield manager.get_unit_state(unit_name)
machine_id = yield service_unit.get_assigned_machine_id()
if machine_id is None:
raise ServiceUnitStateMachineNotAssigned(unit_name)
returnValue(
((yield service_unit.get_public_address()), service_unit))
def expand_path(p):
return os.path.abspath(os.path.expanduser(p))
def expand_constraints(s):
if s:
return s.split(" ")
return []
class ParseError(Exception):
"""Used to support returning custom parse errors in passthrough parsing.
Enables similar support to what is seen in argparse, without using its
internals.
"""
def parse_passthrough_args(args, flags_taking_arg=()):
"""Scans left to right, partitioning flags and positional args.
:param args: Unparsed args from argparse
:param flags_taking_arg: One character flags that combine
with arguments.
:return: tuple of flags and positional args
:raises: :class:`juju.control.utils.ParseError`
TODO May need to support long options for other passthrough commands.
"""
args = iter(args)
flags_taking_arg = set(flags_taking_arg)
flags = []
positional = []
while True:
args, peek_args = tee(args)
try:
peeked = peek_args.next()
except StopIteration:
break
if peeked.startswith("-"):
flags.append(args.next())
# Only need to consume the next arg if the flag both takes
# an arg (say -L) and then it has an extra arg following
# (8080:localhost:80), rather than being combined, such as
# -L8080:localhost:80
if len(peeked) == 2 and peeked[1] in flags_taking_arg:
try:
flags.append(args.next())
except StopIteration:
raise ParseError(
"argument -%s: expected one argument" % peeked[1])
else:
# At this point no more flags for the command itself (more
# can follow after the first positional arg, as seen in
# working with ssh, for example), so consume the rest and
# stop parsing options
positional = list(args)
break
return flags, positional
|