Ejemplo n.º 1
0
 def start(self):
     log.debug("AppManager starting ...")
     self.max_proc_replicas = int(
         CFG.get_safe("container.process.max_replicas", 0))
     if self.use_pd:
         from ion.core.process.pd_core import ProcessDispatcherClient
         self.pd_client = ProcessDispatcherClient(self.container)
Ejemplo n.º 2
0
 def start(self):
     log.debug("AppManager starting ...")
     self.max_proc_replicas = int(CFG.get_safe("container.process.max_replicas", 0))
     if self.use_pd:
         from ion.core.process.pd_core import ProcessDispatcherClient
         self.pd_client = ProcessDispatcherClient(self.container)
Ejemplo n.º 3
0
class AppManager(object):
    def __init__(self, container):
        self.container = container
        self.apps = []
        self.use_pd = CFG.get_safe("container.process.use_process_dispatcher") is True
        self.pd_client = None

    def start(self):
        log.debug("AppManager starting ...")
        self.max_proc_replicas = int(CFG.get_safe("container.process.max_replicas", 0))
        if self.use_pd:
            from ion.core.process.pd_core import ProcessDispatcherClient
            self.pd_client = ProcessDispatcherClient(self.container)

    def stop(self):
        log.debug("AppManager stopping ...")
        # Stop apps in reverse order of startup
        for appdef in reversed(self.apps):
            self.stop_app(appdef)

        self.pd_client = None
        log.debug("AppManager stopped, OK.")

    def start_rel_from_url(self, rel_url="", config=None):
        """
        @brief Read the rel file and call start_rel
        """
        log.info("AppManager.start_rel_from_url(rel_url=%s) ...", rel_url)

        try:
            rel = Config([rel_url]).data
            self.start_rel(rel, config)
            log.debug("AppManager.start_rel_from_url(rel_url=%s) done,  OK.", rel_url)
            return True
        except ConfigNotFound as cnf:
            log.warning("Could not find container deploy file '%s'", rel_url)
        except Exception as ex:
            log.exception("Could not start container deploy file '%s'", rel_url)
            raise ContainerAppError(ex.message)

        return False

    def start_rel(self, rel=None, config=None):
        """
        @brief Recurse over the rel and start apps defined there.
        Note: apps in a rel file can come in one of 2 forms:
        1 processapp: In-line defined process to be started as app
        2 app file: Reference to an app definition in an app file
        If the rel file provides an app config block, it is provided to spawn the process.
        Any given function config dict is merged on top of this.
        """
        log.debug("AppManager.start_rel(rel=%s) ...", rel)

        if rel is None:
            return

        if self.use_pd:
            log.info("Sending rel file to PD")
            import json
            rel_def = json.loads(json.dumps(rel))     # HACK to get rid of OrderedDict (not serializable)
            cmd_res = self.pd_client.start_rel_blocking(rel_def, timeout=None)
            return cmd_res

        for rel_app_cfg in rel.apps:
            name = rel_app_cfg.name
            log.debug("app definition in rel: %s" % str(rel_app_cfg))

            if 'processapp' in rel_app_cfg:
                # Case 1: Rel contains definition of process to start as app
                name, module, cls = rel_app_cfg.processapp

                rel_cfg = None
                if 'config' in rel_app_cfg:
                    rel_cfg = deepcopy(rel_app_cfg.config)
                    if config:
                        dict_merge(rel_cfg, config, inplace=True)

                if 'replicas' in rel_app_cfg:
                    proc_replicas = int(rel_app_cfg["replicas"])
                    if self.max_proc_replicas > 0:
                        if proc_replicas > self.max_proc_replicas:
                            log.info("Limiting number of proc replicas to %s from %s", self.max_proc_replicas, proc_replicas)
                        proc_replicas = min(proc_replicas, self.max_proc_replicas)
                    if proc_replicas < 1 or proc_replicas > 100:
                        log.warn("Invalid number of process replicas: %s", proc_replicas)
                        proc_replicas = 1
                    for i in xrange(proc_replicas):
                        proc_name = "%s.%s" % (name, i) if i else name
                        self.container.spawn_process(proc_name, module, cls, rel_cfg)
                else:
                    self.container.spawn_process(name, module, cls, rel_cfg)
                self.apps.append(DotDict(type="application", name=name, processapp=rel_app_cfg.processapp))

            else:
                # Case 2: Rel contains reference to app file to start
                app_file_path = 'res/apps/%s.yml' % (name)
                rel_cfg = rel_app_cfg.get('config', None)
                if config:
                    dict_merge(rel_cfg, config, inplace=True)
                self.start_app_from_url(app_file_path, config=rel_cfg)

    def start_app_from_url(self, app_url="", config=None):
        """
        @brief Read the app file and call start_app
        """
        log.debug("AppManager.start_app_from_url(app_url=%s) ..." % app_url)

        try:
            app = Config([app_url]).data
            self.start_app(appdef=app, config=config)
            return True
        except ConfigNotFound as cnf:
            log.warning("Could not find container app file '%s'" % app_url)
        except Exception as ex:
            log.exception("Could not start app file %s" % app_url)
            raise ContainerAppError(ex.message)

        return False

    def start_app(self, appdef=None, config=None):
        """
        @brief Start an app from an app definition.
        Note: apps can come in one of 2 variants:
        1 processapp: In-line defined process to be started
        2 regular app: Full app definition
        """
        log.debug("AppManager.start_app(appdef=%s) ..." % appdef)

        appdef = DotDict(appdef)

        if 'config' in appdef:
            app_cfg = deepcopy(appdef.config)
            if config:
                dict_merge(app_cfg, config, inplace=True)
            config = app_cfg

        if 'processapp' in appdef:
            # Case 1: Appdef contains definition of process to start
            name, module, cls = appdef.processapp
            try:
                pid = self.container.spawn_process(name, module, cls, config)
                appdef._pid = pid
                self.apps.append(appdef)
            except Exception:
                log.exception("Appl %s start from processapp failed" % appdef.name)
        else:
            # Case 2: Appdef contains full app start params
            modpath = appdef.mod
            try:
                mod = named_any(modpath)
                appdef._mod_loaded = mod

                # Start the app
                supid, state = mod.start(self.container, START_PERMANENT, appdef, config)
                appdef._supid = supid
                appdef._state = state

                log.debug("App '%s' started. Root sup-id=%s" % (appdef.name, supid))

                self.apps.append(appdef)
            except Exception:
                log.exception("Appl %s start from appdef failed" % appdef.name)

    def stop_app(self, appdef):
        log.debug("App '%s' stopping" % appdef.name)
        try:
            if '_mod_loaded' in appdef:
                appdef._mod_loaded.stop(self.container, appdef._state)
        except Exception as ex:
            log.exception("Application %s stop failed" % appdef.name)
Ejemplo n.º 4
0
class AppManager(object):
    def __init__(self, container):
        self.container = container
        self.apps = []
        self.use_pd = CFG.get_safe(
            "container.process.use_process_dispatcher") is True
        self.pd_client = None

    def start(self):
        log.debug("AppManager starting ...")
        self.max_proc_replicas = int(
            CFG.get_safe("container.process.max_replicas", 0))
        if self.use_pd:
            from ion.core.process.pd_core import ProcessDispatcherClient
            self.pd_client = ProcessDispatcherClient(self.container)

    def stop(self):
        log.debug("AppManager stopping ...")
        # Stop apps in reverse order of startup
        for appdef in reversed(self.apps):
            self.stop_app(appdef)

        self.pd_client = None
        log.debug("AppManager stopped, OK.")

    def start_rel_from_url(self, rel_url="", config=None):
        """
        @brief Read the rel file and call start_rel
        """
        log.info("AppManager.start_rel_from_url(rel_url=%s) ...", rel_url)

        try:
            rel = Config([rel_url]).data
            self.start_rel(rel, config)
            log.debug("AppManager.start_rel_from_url(rel_url=%s) done,  OK.",
                      rel_url)
            return True
        except ConfigNotFound as cnf:
            log.warning("Could not find container deploy file '%s'", rel_url)
        except Exception as ex:
            log.exception("Could not start container deploy file '%s'",
                          rel_url)
            raise ContainerAppError(ex.message)

        return False

    def start_rel(self, rel=None, config=None):
        """
        @brief Recurse over the rel and start apps defined there.
        Note: apps in a rel file can come in one of 2 forms:
        1 processapp: In-line defined process to be started as app
        2 app file: Reference to an app definition in an app file
        If the rel file provides an app config block, it is provided to spawn the process.
        Any given function config dict is merged on top of this.
        """
        log.debug("AppManager.start_rel(rel=%s) ...", rel)

        if rel is None:
            return

        if self.use_pd:
            log.info("Sending rel file to PD")
            import json
            rel_def = json.loads(json.dumps(
                rel))  # HACK to get rid of OrderedDict (not serializable)
            cmd_res = self.pd_client.start_rel_blocking(rel_def, timeout=None)
            return cmd_res

        for rel_app_cfg in rel.apps:
            name = rel_app_cfg.name
            log.debug("app definition in rel: %s" % str(rel_app_cfg))

            if 'processapp' in rel_app_cfg:
                # Case 1: Rel contains definition of process to start as app
                name, module, cls = rel_app_cfg.processapp

                rel_cfg = None
                if 'config' in rel_app_cfg:
                    rel_cfg = deepcopy(rel_app_cfg.config)
                    if config:
                        dict_merge(rel_cfg, config, inplace=True)

                if 'replicas' in rel_app_cfg:
                    proc_replicas = int(rel_app_cfg["replicas"])
                    if self.max_proc_replicas > 0:
                        if proc_replicas > self.max_proc_replicas:
                            log.info(
                                "Limiting number of proc replicas to %s from %s",
                                self.max_proc_replicas, proc_replicas)
                        proc_replicas = min(proc_replicas,
                                            self.max_proc_replicas)
                    if proc_replicas < 1 or proc_replicas > 100:
                        log.warn("Invalid number of process replicas: %s",
                                 proc_replicas)
                        proc_replicas = 1
                    for i in xrange(proc_replicas):
                        proc_name = "%s.%s" % (name, i) if i else name
                        self.container.spawn_process(proc_name, module, cls,
                                                     rel_cfg)
                else:
                    self.container.spawn_process(name, module, cls, rel_cfg)
                self.apps.append(
                    DotDict(type="application",
                            name=name,
                            processapp=rel_app_cfg.processapp))

            else:
                # Case 2: Rel contains reference to app file to start
                app_file_path = 'res/apps/%s.yml' % (name)
                rel_cfg = rel_app_cfg.get('config', None)
                if config:
                    dict_merge(rel_cfg, config, inplace=True)
                self.start_app_from_url(app_file_path, config=rel_cfg)

    def start_app_from_url(self, app_url="", config=None):
        """
        @brief Read the app file and call start_app
        """
        log.debug("AppManager.start_app_from_url(app_url=%s) ..." % app_url)

        try:
            app = Config([app_url]).data
            self.start_app(appdef=app, config=config)
            return True
        except ConfigNotFound as cnf:
            log.warning("Could not find container app file '%s'" % app_url)
        except Exception as ex:
            log.exception("Could not start app file %s" % app_url)
            raise ContainerAppError(ex.message)

        return False

    def start_app(self, appdef=None, config=None):
        """
        @brief Start an app from an app definition.
        Note: apps can come in one of 2 variants:
        1 processapp: In-line defined process to be started
        2 regular app: Full app definition
        """
        log.debug("AppManager.start_app(appdef=%s) ..." % appdef)

        appdef = DotDict(appdef)

        if 'config' in appdef:
            app_cfg = deepcopy(appdef.config)
            if config:
                dict_merge(app_cfg, config, inplace=True)
            config = app_cfg

        if 'processapp' in appdef:
            # Case 1: Appdef contains definition of process to start
            name, module, cls = appdef.processapp
            try:
                pid = self.container.spawn_process(name, module, cls, config)
                appdef._pid = pid
                self.apps.append(appdef)
            except Exception:
                log.exception("Appl %s start from processapp failed" %
                              appdef.name)
        else:
            # Case 2: Appdef contains full app start params
            modpath = appdef.mod
            try:
                mod = named_any(modpath)
                appdef._mod_loaded = mod

                # Start the app
                supid, state = mod.start(self.container, START_PERMANENT,
                                         appdef, config)
                appdef._supid = supid
                appdef._state = state

                log.debug("App '%s' started. Root sup-id=%s" %
                          (appdef.name, supid))

                self.apps.append(appdef)
            except Exception:
                log.exception("Appl %s start from appdef failed" % appdef.name)

    def stop_app(self, appdef):
        log.debug("App '%s' stopping" % appdef.name)
        try:
            if '_mod_loaded' in appdef:
                appdef._mod_loaded.stop(self.container, appdef._state)
        except Exception as ex:
            log.exception("Application %s stop failed" % appdef.name)
Ejemplo n.º 5
0
 def on_init(self):
     self.rr = self.clients.resource_registry
     self.pd_client = ProcessDispatcherClient(
         self.container, CFG.get_safe("service.process_dispatcher", {}))