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()
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()
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()
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)
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)
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")
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")
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)