Esempio n. 1
0
def deploy(env_config, environment, repository_path, charm_name,
           service_name, log, config_file=None, 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.
    """
    repo, charm_url = resolve(
        charm_name, repository_path, environment.default_series)

    # 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 = 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()
    client = yield provider.connect()

    try:
        storage = yield provider.get_file_storage()
        service_manager = ServiceStateManager(client)
        environment_state_manager = EnvironmentStateManager(client)
        yield environment_state_manager.set_config_state(
            env_config, environment.name)

        # Publish the charm to juju
        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_state = yield service_manager.add_service_state(
            service_name, charm_state)

        # 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
        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()
Esempio n. 2
0
def upgrade_charm(
    config, environment, verbose, log, repository_path, service_name, dry_run):
    """Upgrades a service's charm.

    First determines if an upgrade is available, then updates the
    service charm reference, and marks the units as needing upgrades.
    """
    provider = environment.get_machine_provider()
    client = yield provider.connect()

    service_manager = ServiceStateManager(client)
    service_state = yield service_manager.get_service_state(service_name)
    old_charm_id = yield service_state.get_charm_id()

    old_charm_url = CharmURL.parse(old_charm_id)
    old_charm_url.assert_revision()
    repo, charm_url = resolve(
        str(old_charm_url.with_revision(None)),
        repository_path,
        environment.default_series)
    new_charm_url = charm_url.with_revision(
        (yield repo.latest(charm_url)))

    if charm_url.collection.schema == "local":
        if old_charm_url.revision >= new_charm_url.revision:
            new_revision = old_charm_url.revision + 1
            charm = yield repo.find(new_charm_url)
            if isinstance(charm, CharmDirectory):
                if dry_run:
                    log.info("%s would be set to revision %s",
                             charm.path, new_revision)
                else:
                    log.info("Setting %s to revision %s",
                             charm.path, new_revision)
                    charm.set_revision(new_revision)
                new_charm_url.revision = new_revision

    new_charm_id = str(new_charm_url)

    # Verify its newer than what's deployed
    if not new_charm_url.revision > old_charm_url.revision:
        if dry_run:
            log.info("Service already running latest charm %r", old_charm_id)
        else:
            raise NewerCharmNotFound(old_charm_id)
    elif dry_run:
        log.info("Service would be upgraded from charm %r to %r",
                 old_charm_id, new_charm_id)

    # On dry run, stop before modifying state.
    if not dry_run:
        # Publish the new charm
        storage = provider.get_file_storage()
        publisher = CharmPublisher(client, storage)
        charm = yield repo.find(new_charm_url)
        yield publisher.add_charm(new_charm_id, charm)
        result = yield publisher.publish()
        charm_state = result[0]

        # Update the service charm reference
        yield service_state.set_charm_id(charm_state.id)

    # Mark the units for upgrades
    units = yield service_state.get_all_unit_states()
    for unit in units:
        running, state = yield is_unit_running(client, unit)
        if not running:
            log.info(
                "Unit %r is not in a running state (state: %r), won't upgrade",
                unit.unit_name, state or "uninitialized")
            continue

        if not dry_run:
            yield unit.set_upgrade_flag()
Esempio n. 3
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()
Esempio n. 4
0
 def assert_resolve_remote(self, vague, default, expect):
     repo, url = resolve(vague, None, default)
     self.assertEquals(str(url), expect)
     self.assertTrue(isinstance(repo, RemoteCharmRepository))
     self.assertEquals(repo.url_base, CS_STORE_URL)
Esempio n. 5
0
 def assert_resolve_local(self, vague, default, expect):
     path = self.makeDir()
     repo, url = resolve(vague, path, default)
     self.assertEquals(str(url), expect)
     self.assertTrue(isinstance(repo, LocalCharmRepository))
     self.assertEquals(repo.path, path)
Esempio n. 6
0
 def assert_resolve_remote(self, vague, default, expect):
     repo, url = resolve(vague, None, default)
     self.assertEquals(str(url), expect)
     self.assertTrue(isinstance(repo, RemoteCharmRepository))
     self.assertEquals(repo.url_base, "https://store.juju.ubuntu.com")
Esempio n. 7
0
 def assert_resolve_remote(self, vague, default, expect):
     repo, url = resolve(vague, None, default)
     self.assertEquals(str(url), expect)
     self.assertTrue(isinstance(repo, RemoteCharmRepository))
     self.assertEquals(repo.url_base, "https://store.juju.ubuntu.com")
Esempio n. 8
0
 def assert_resolve_local(self, vague, default, expect):
     path = self.makeDir()
     repo, url = resolve(vague, path, default)
     self.assertEquals(str(url), expect)
     self.assertTrue(isinstance(repo, LocalCharmRepository))
     self.assertEquals(repo.path, path)