def initialize(self): self.__contr_mgr = ContainerManager()
def initialize(self): self.__app_mgr = ApplianceManager() self.__contr_mgr = ContainerManager()
def __init__(self): self.__app_api = ApplianceAPIManager() self.__contr_mgr = ContainerManager() self.__app_db = ApplianceDBManager() self.__vol_mgr = VolumeManager()
def __init__(self, app_id): super(ApplianceDeletionChecker, self).__init__(3000) self.__app_id = app_id self.__app_api = ApplianceAPIManager() self.__app_db = ApplianceDBManager() self.__contr_mgr = ContainerManager()
class ApplianceManager(Manager): def __init__(self): self.__app_api = ApplianceAPIManager() self.__contr_mgr = ContainerManager() self.__app_db = ApplianceDBManager() self.__vol_mgr = VolumeManager() async def get_appliance(self, app_id): status, app, err = await self.__app_db.get_appliance(app_id) if status != 200: return status, app, err app = Appliance(**app) status, app.containers, err = await self.__contr_mgr.get_containers( appliance=app_id) if app.data_persistence: _, local_vols, _ = await self.__vol_mgr.get_local_volumes( appliance=app_id) _, global_vols, _ = await self.__vol_mgr.get_global_volumes_by_appliance( app_id) app.data_persistence.volumes = local_vols + global_vols if len(app.containers) == 0 \ and (not app.data_persistence or len(app.data_persistence.volumes) == 0): await self.__app_db.delete_appliance(app_id) return 404, None, "Appliance '%s' is not found" % app_id return 200, app, None async def create_appliance(self, data): vol_mgr = self.__vol_mgr def validate_volume_mounts(app, vols_existed, vols_declared): all_vols = set(vols_existed) | set(vols_declared) vols_to_mount = set([ pv.src for c in app.containers for pv in c.persistent_volumes ]) return list(vols_to_mount - all_vols) async def update_global_volumes(global_vols, app_id): for gpv in global_vols: gpv.subscribe(app_id) resps = await multi( [vol_mgr.update_volume(gpv) for gpv in global_vols]) for status, _, err in resps: if status != 200: self.logger.error(err) def set_container_volume_scope(contrs, vols): vols = {v.id: v for v in vols} for c in contrs: for pv in c.persistent_volumes: if pv.src in vols: pv.scope = vols[pv.src].scope status, app, _ = await self.get_appliance(data['id']) if status == 200 and len(app.containers) > 0: return 409, None, "Appliance '%s' already exists" % data['id'] status, app, err = Appliance.parse(data) if status != 200: self.logger.error(err) return status, None, err # create persistent volumes if any dp = app.data_persistence if dp: resps = await multi([ vol_mgr.get_local_volume(app.id, v.id) for v in dp.local_volumes ] + [vol_mgr.get_global_volume(v.id) for v in dp.global_volumes]) vols_existed = set( [v.id for status, v, _ in resps if status == 200]) vols_declared = set([v.id for v in dp.volumes]) invalid_vols = validate_volume_mounts(app, vols_existed, vols_declared) if len(invalid_vols) > 0: await self._clean_up_incomplete_appliance(app.id) return 400, None, 'Invalid persistent volume(s): %s' % invalid_vols global_vols = [ v for _, v, _ in resps if v and v.scope == volume.VolumeScope.GLOBAL ] if len(vols_existed) < len(dp.volumes): resps = await multi([ vol_mgr.create_volume(v.to_save()) for v in dp.volumes if v.id not in vols_existed ]) for status, v, err in resps: if status != 201: self.logger.error(err) await self._clean_up_incomplete_appliance(app.id) return status, None, err if v.scope == volume.VolumeScope.GLOBAL: global_vols += v, await update_global_volumes(global_vols, app.id) set_container_volume_scope(app.containers, dp.volumes) # create containers resps = await multi([ self.__contr_mgr.create_container(c.to_save()) for c in app.containers ]) for status, _, err in resps: if status != 201: self.logger.error(err) await self._clean_up_incomplete_appliance(app.id) return status, None, err status, _, err = await self.save_appliance(app) if status != 200: self.logger.error(err) await self._clean_up_incomplete_appliance(app.id) return status, None, err scheduler = self._get_scheduler(app.scheduler) self.logger.info('Appliance %s uses %s' % (app.id, scheduler.__class__.__name__)) ApplianceScheduleExecutor(app.id, scheduler).start() return 201, app, None async def delete_appliance(self, app_id, purge_data=False): vol_mgr = self.__vol_mgr self.logger.debug('Purge data?: %s' % purge_data) status, app, err = await self.get_appliance(app_id) if status != 200: self.logger.error(err) return status, None, err self.logger.info("Stop monitoring appliance '%s'" % app_id) # deprovision containers status, msg, err = await self.__contr_mgr.delete_containers( appliance=app_id) if status != 200: self.logger.error(err) return 207, None, "Failed to deprovision jobs of appliance '%s'" % app_id self.logger.info(msg) # deprovision/delete local persistent volumes if any if app.data_persistence: _, local_vols, _ = await vol_mgr.get_local_volumes(appliance=app_id ) resps = await multi([(vol_mgr.purge_local_volume( app_id, v.id) if purge_data else vol_mgr.deprovision_volume(v)) for v in local_vols]) for i, (status, _, err) in enumerate(resps): if status != 200: self.logger.error(err) return 207, None, "Failed to deprovision persistent volume '%s'" % local_vols[ i].id if purge_data: _, global_vols, _ = await vol_mgr.get_global_volumes_by_appliance( app_id) for gpv in global_vols: gpv.unsubscribe(app_id) for status, _, err in (await multi( [vol_mgr.update_volume(gpv) for gpv in global_vols])): if status != 200: self.logger.error(err) # deprovision appliance status, msg, err = await self.__app_api.deprovision_appliance(app_id) if status != 200 and status != 404: self.logger.error(err) return 207, None, "Failed to deprovision appliance '%s'" % app_id if purge_data: await self.__app_db.delete_appliance(app_id) ApplianceDeletionChecker(app_id).start() return status, msg, None async def save_appliance(self, app, upsert=True): return await self.__app_db.save_appliance(app, upsert) def _get_scheduler(self, sched): try: sched_mod = '.'.join(sched.name.split('.')[:-1]) sched_class = sched.name.split('.')[-1] return getattr(importlib.import_module(sched_mod), sched_class)(sched.config) except Exception as e: self.logger.error(str(e)) return schedule.local.DefaultApplianceScheduler() async def _clean_up_incomplete_appliance(self, app_id): await self.__app_db.delete_appliance(app_id) await self.__contr_mgr.delete_containers(appliance=app_id)