X-Git-Url: https://osm.etsi.org/gitweb/?a=blobdiff_plain;f=juju%2Fmodel.py;h=52721a714f3fa363fb8d8e97e5cc0e84db9a90db;hb=55ae2c120ce031f57ac210f3d7bd203db739f1e9;hp=ab9f71257c9f85a7361d6739fcbf6718008ee6c0;hpb=224a14c0bbd6b0a621a24ae889fea9279755a57b;p=osm%2FN2VC.git diff --git a/juju/model.py b/juju/model.py index ab9f712..52721a7 100644 --- a/juju/model.py +++ b/juju/model.py @@ -6,6 +6,7 @@ import weakref from concurrent.futures import CancelledError from functools import partial +import yaml from theblues import charmstore from .client import client @@ -758,9 +759,6 @@ class Model(object): - series is required; how do we pick a default? """ - if constraints: - constraints = client.Value(**constraints) - if to: placement = [ client.Placement(**p) for p in to @@ -785,6 +783,18 @@ class Model(object): handler = BundleHandler(self) await handler.fetch_plan(entity_id) await handler.execute_plan() + extant_apps = {app for app in self.applications} + pending_apps = set(handler.applications) - extant_apps + if pending_apps: + # new apps will usually be in the model by now, but if some + # haven't made it yet we'll need to wait on them to be added + await asyncio.gather(*[ + asyncio.ensure_future( + self.model._wait_for_new('application', app_name)) + for app_name in pending_apps + ]) + return [app for name, app in self.applications.items() + if name in handler.applications] else: log.debug( 'Deploying %s', entity_id) @@ -813,6 +823,21 @@ class Model(object): """ pass + async def destroy_unit(self, *unit_names): + """Destroy units by name. + + """ + app_facade = client.ApplicationFacade() + app_facade.connect(self.connection) + + log.debug( + 'Destroying unit%s %s', + 's' if len(unit_names) == 1 else '', + ' '.join(unit_names)) + + return await app_facade.Destroy(self.name) + destroy_units = destroy_unit + def get_backup(self, archive_id): """Download a backup archive file. @@ -1148,10 +1173,11 @@ class BundleHandler(object): self.ann_facade.connect(model.connection) async def fetch_plan(self, entity_id): - yaml = await self.charmstore.files(entity_id, - filename='bundle.yaml', - read_file=True) - self.plan = await self.client_facade.GetBundleChanges(yaml) + bundle_yaml = await self.charmstore.files(entity_id, + filename='bundle.yaml', + read_file=True) + self.bundle = yaml.safe_load(bundle_yaml) + self.plan = await self.client_facade.GetBundleChanges(bundle_yaml) async def execute_plan(self): for step in self.plan.changes: @@ -1159,6 +1185,10 @@ class BundleHandler(object): result = await method(*step.args) self.references[step.id_] = result + @property + def applications(self): + return list(self.bundle['services'].keys()) + def resolve(self, reference): if reference and reference.startswith('$'): reference = self.references[reference[1:]] @@ -1224,6 +1254,7 @@ class BundleHandler(object): parts[0] = self.resolve(parts[0]) endpoints[i] = ':'.join(parts) + log.info('Relating %s <-> %s', *endpoints) return await self.model.add_relation(*endpoints) async def deploy(self, charm, series, application, options, constraints, @@ -1272,7 +1303,7 @@ class BundleHandler(object): resources=resources, ) # do the do - log.debug('Deploying %s', charm) + log.info('Deploying %s', charm) await self.app_facade.Deploy([app]) return application @@ -1295,16 +1326,14 @@ class BundleHandler(object): # doesn't, so we're not bothering, either unit_name = self._units_by_app[application].pop() log.debug('Reusing unit %s for %s', unit_name, application) - return unit_name - log.debug('Adding unit of %s%s', - application, - (' to %s' % placement) if placement else '') - result = await self.app_facade.AddUnits( - application=application, - placement=placement, - num_units=1, + return self.model.units[unit_name] + + log.debug('Adding new unit for %s%s', application, + ' to %s' % placement if placement else '') + return await self.model.applications[application].add_unit( + count=1, + to=placement, ) - return result.units[0] async def expose(self, application): """ @@ -1313,6 +1342,7 @@ class BundleHandler(object): be exposed. """ application = self.resolve(application) + log.info('Exposing %s', application) return await self.model.applications[application].expose() async def setAnnotations(self, id_, entity_type, annotations): @@ -1329,13 +1359,11 @@ class BundleHandler(object): Annotations holds the annotations as key/value pairs. """ entity_id = self.resolve(id_) - log.debug('Updating annotations of %s', entity_id) - ann = client.EntityAnnotations( - entity=entity_id, - annotations=annotations, - ) - await self.ann_facade.Set([ann]) - return None + try: + entity = self.model.state.get_entity(entity_type, entity_id) + except KeyError: + entity = await self.model._wait_for_new(entity_type, entity_id) + return await entity.set_annotations(annotations) class CharmStore(object):