Esempio n. 1
0
def add_unit(config, environment, verbose, log, service_name, num_units):
    """Add a unit of a service to the environment.
    """
    provider = environment.get_machine_provider()
    placement_policy = provider.get_placement_policy()
    client = yield provider.connect()

    try:
        yield legacy.check_environment(
            client, provider.get_legacy_config_keys())
        yield sync_environment_state(client, config, environment.name)

        service_manager = ServiceStateManager(client)
        service_state = yield service_manager.get_service_state(service_name)
        if (yield service_state.is_subordinate()):
            raise JujuError("Subordinate services acquire units from "
                            "their principal service.")

        for i in range(num_units):
            unit_state = yield service_state.add_unit_state()
            yield place_unit(client, placement_policy, unit_state)
            log.info("Unit %r added to service %r",
                     unit_state.unit_name, service_state.service_name)
    finally:
        yield client.close()
Esempio n. 2
0
def constraints_set(env_config, environment, service_name, constraint_strs):
    """
    Machine constraints allow you to pick the hardware to which your services
    will be deployed. Examples:

    $ juju set-constraints --service-name mysql mem=8G cpu=4

    $ juju set-constraints instance-type=t1.micro

    Available constraints vary by provider type, and will be ignored if not
    understood by the current environment's provider. The current set of
    available constraints across all providers is:

    On Amazon EC2:

        * arch (CPU architecture: i386/amd64/arm; amd64 by default)
        * cpu (processing power in Amazon ECU; 1 by default)
        * mem (memory in [MGT]iB; 512M by default)
        * instance-type (unset by default)
        * ec2-zone (unset by default)

    On Orchestra:

        * orchestra-classes (unset by default)

    On MAAS:

        * maas-name (unset by default)

    Service settings, if specified, will override environment settings, which
    will in turn override the juju defaults of mem=512M, cpu=1, arch=amd64.

    New constraints set on an entity will completely replace that entity's
    pre-existing constraints.

    To override an environment constraint with the juju default when setting
    service constraints, just specify "name=" (rather than just not specifying
    the constraint at all, which will cause it to inherit the environment's
    value).

    To entirely unset a constraint, specify "name=any".
    """
    provider = environment.get_machine_provider()
    constraint_set = yield provider.get_constraint_set()
    constraints = constraint_set.parse(constraint_strs)
    client = yield provider.connect()
    try:
        yield legacy.check_constraints(client, constraint_strs)
        yield sync_environment_state(client, env_config, environment.name)
        if service_name is None:
            esm = EnvironmentStateManager(client)
            yield esm.set_constraints(constraints)
        else:
            ssm = ServiceStateManager(client)
            service = yield ssm.get_service_state(service_name)
            yield service.set_constraints(constraints)
    finally:
        yield client.close()
Esempio n. 3
0
def terminate_machine(config, environment, verbose, log, machine_ids):
    """Terminates the machines in `machine_ids`.

    Like the underlying code in MachineStateManager, it's permissible
    if the machine ID is already terminated or even never running. If
    we determine this is not desired behavior, presumably propagate
    that back to the state manager.

    XXX However, we currently special case support of not terminating
    the "root" machine, that is the one running the provisioning
    agent. At some point, this will be managed like any other service,
    but until then it seems best to ensure it's not terminated at this
    level.
    """

    provider = environment.get_machine_provider()
    client = yield provider.connect()
    terminated_machine_ids = []
    try:
        yield sync_environment_state(client, config, environment.name)
        machine_state_manager = MachineStateManager(client)
        for machine_id in machine_ids:
            if machine_id == 0:
                raise CannotTerminateMachine(
                    0, "environment would be destroyed")
            removed = yield machine_state_manager.remove_machine_state(
                machine_id)
            if not removed:
                raise MachineStateNotFound(machine_id)
            terminated_machine_ids.append(machine_id)
    finally:
        yield client.close()
        if terminated_machine_ids:
            log.info(
                "Machines terminated: %s",
                ", ".join(str(id) for id in terminated_machine_ids))
Esempio n. 4
0
def constraints_get(env_config, environment, entity_names, log):
    """
    Show the complete set of applicable constraints for each specified entity.

    This will show the final computed values of all constraints (including
    internal constraints which cannot be set directly via set-constraints).
    """
    provider = environment.get_machine_provider()
    client = yield provider.connect()
    result = {}
    try:
        yield sync_environment_state(client, env_config, environment.name)
        if entity_names:
            msm = MachineStateManager(client)
            ssm = ServiceStateManager(client)
            for name in entity_names:
                if name.isdigit():
                    kind = "machine"
                    entity = yield msm.get_machine_state(name)
                elif "/" in name:
                    kind = "service unit"
                    entity = yield ssm.get_unit_state(name)
                else:
                    kind = "service"
                    entity = yield ssm.get_service_state(name)
                log.info("Fetching constraints for %s %s", kind, name)
                constraints = yield entity.get_constraints()
                result[name] = dict(constraints)
        else:
            esm = EnvironmentStateManager(client)
            log.info("Fetching constraints for environment")
            constraints = yield esm.get_constraints()
            result = dict(constraints)
        yaml.safe_dump(result, sys.stdout)
    finally:
        yield client.close()
Esempio n. 5
0
def deploy(env_config, environment, repository_path, charm_name,
           service_name, log, constraint_strs, config_file=None, upgrade=False,
           num_units=1):
    """Deploy a charm within an environment.

    This will publish the charm to the environment, creating
    a service from the charm, and get it set to be launched
    on a new machine. If --repository is not specified, it
    will be taken from the environment variable JUJU_REPOSITORY.
    """
    repo, charm_url = resolve(
        charm_name, repository_path, environment.default_series)

    log.info("Searching for charm %s in %s" % (charm_url, repo))
    charm = yield repo.find(charm_url)
    if upgrade:
        if repo.type != "local" or charm.type != "dir":
            raise CharmError(
                charm.path,
                "Only local directory charms can be upgraded on deploy")
        charm.set_revision(charm.get_revision() + 1)

    charm_id = str(charm_url.with_revision(charm.get_revision()))

    # Validate config options prior to deployment attempt
    service_options = {}
    service_name = service_name or charm_url.name
    if config_file:
        service_options = parse_config_options(
            config_file, service_name, charm)

    charm = yield repo.find(charm_url)
    charm_id = str(charm_url.with_revision(charm.get_revision()))

    provider = environment.get_machine_provider()
    placement_policy = provider.get_placement_policy()
    constraint_set = yield provider.get_constraint_set()
    constraints = constraint_set.parse(constraint_strs)
    client = yield provider.connect()

    try:
        yield legacy.check_constraints(client, constraint_strs)
        yield legacy.check_environment(
            client, provider.get_legacy_config_keys())
        yield sync_environment_state(client, env_config, environment.name)

        # Publish the charm to juju
        storage = yield provider.get_file_storage()
        publisher = CharmPublisher(client, storage)
        yield publisher.add_charm(charm_id, charm)
        result = yield publisher.publish()

        # In future we might have multiple charms be published at
        # the same time.  For now, extract the charm_state from the
        # list.
        charm_state = result[0]

        # Create the service state
        service_manager = ServiceStateManager(client)
        service_state = yield service_manager.add_service_state(
            service_name, charm_state, constraints)

        # Use the charm's ConfigOptions instance to validate service
        # options.. Invalid options passed will thrown an exception
        # and prevent the deploy.
        state = yield service_state.get_config()
        charm_config = yield charm_state.get_config()
        # return the validated options with the defaults included
        service_options = charm_config.validate(service_options)
        state.update(service_options)
        yield state.write()

        # Create desired number of service units
        if (yield service_state.is_subordinate()):
            log.info("Subordinate %r awaiting relationship "
                     "to principal for deployment.", service_name)
        else:
            for i in xrange(num_units):
                unit_state = yield service_state.add_unit_state()
                yield place_unit(client, placement_policy, unit_state)

        # Check if we have any peer relations to establish
        if charm.metadata.peers:
            relation_manager = RelationStateManager(client)
            for peer_name, peer_info in charm.metadata.peers.items():
                yield relation_manager.add_relation_state(
                    RelationEndpoint(service_name,
                                     peer_info["interface"],
                                     peer_name,
                                     "peer"))

        log.info("Charm deployed as service: %r", service_name)
    finally:
        yield client.close()