def unregister_callback(self, group, cb_func): if not self._started: raise ContainerConfigError("StatsManager not started") if group not in self._stats_callbacks: raise ContainerConfigError("Unknown stats group: %s" % group) cbs = self._stats_callbacks[group] cbs.pop(cb_func, None)
def register_callback(self, group, cb_func): if not self._started: raise ContainerConfigError("StatsManager not started") if group not in self._stats_callbacks: raise ContainerConfigError("Unknown stats group: %s" % group) if group == "SVCREQ": # Special treatment because service gateway may be started late from ion.service.service_gateway import sg_instance if sg_instance and not sg_instance.request_callback: sg_instance.register_request_callback(self._sg_callback) cbs = self._stats_callbacks[group] if cb_func in cbs: return cbs.append(cb_func)
def _create_service_instance(self, process_id, name, module, cls, config): """ Creates an instance of a "service", be it a Service, Agent, Stream, etc. @rtype BaseService @return An instance of a "service" """ # SERVICE INSTANCE. service_instance = for_name(module, cls) if not isinstance(service_instance, BaseService): raise ContainerConfigError( "Instantiated service not a BaseService %r" % service_instance) # Prepare service instance service_instance.errcause = "" service_instance.id = process_id service_instance.container = self.container service_instance.CFG = config service_instance._proc_name = name service_instance._proc_start_time = time.time() # start service dependencies (RPC clients) self._start_service_dependencies(service_instance) return service_instance
def _spawn_agent_process(self, process_id, name, module, cls, config): """ Spawn a process acting as agent process. Attach to service pid. """ service_instance = self._create_service_instance( process_id, name, module, cls, config) if not isinstance(service_instance, ResourceAgent): raise ContainerConfigError( "Agent process must extend ResourceAgent") # Set the resource ID if we get it through the config resource_id = get_safe(service_instance.CFG, "agent.resource_id") if resource_id: service_instance.resource_id = resource_id rsvc = ProcessRPCServer(node=self.container.node, from_name=service_instance.id, service=service_instance, process=service_instance) # cleanup method to delete process queue (@TODO: leaks a bit here - should use XOs) cleanup = lambda _: self._cleanup_method(service_instance.id, rsvc) proc = self.proc_sup.spawn(name=service_instance.id, service=service_instance, listeners=[rsvc], proc_name=service_instance._proc_name, cleanup_method=cleanup) self.proc_sup.ensure_ready( proc, "_spawn_agent_process for %s" % service_instance.id) # map gproc to service_instance self._spawned_proc_to_process[proc.proc] = service_instance # set service's reference to process service_instance._process = proc # Now call the on_init of the agent. self._service_init(service_instance) if not service_instance.resource_id: log.warn("New agent pid=%s has no resource_id set" % process_id) self._service_start(service_instance) proc.start_listeners() if service_instance.resource_id: # look to load any existing policies for this resource if self._is_policy_management_service_available( ) and self.container.governance_controller: self.container.governance_controller.update_resource_access_policy( service_instance.resource_id) else: log.warn("Agent process id=%s does not define resource_id!!" % service_instance.id) return service_instance
def _spawn_agent_process(self, process_id, name, module, cls, config): """ Spawn a process acting as agent process. Attach to service pid. """ service_instance = self._create_service_instance( process_id, name, module, cls, config) if not isinstance(service_instance, ResourceAgent): raise ContainerConfigError( "Agent process must extend ResourceAgent") # Set the resource ID if we get it through the config resource_id = get_safe(service_instance.CFG, "agent.resource_id") if resource_id: service_instance.resource_id = resource_id # Now call the on_init of the agent. self._service_init(service_instance) if not service_instance.resource_id: log.warn("New agent pid=%s has no resource_id set" % process_id) self._service_start(service_instance) rsvc = ProcessRPCServer(node=self.container.node, from_name=service_instance.id, service=service_instance, process=service_instance) proc = self.proc_sup.spawn(name=service_instance.id, service=service_instance, listeners=[rsvc], proc_name=service_instance._proc_name) self.proc_sup.ensure_ready( proc, "_spawn_agent_process for %s" % service_instance.id) # map gproc to service_instance self._spawned_proc_to_process[proc.proc] = service_instance # set service's reference to process service_instance._process = proc # Directory registration caps = service_instance.get_capabilities() self.container.directory.register( "/Agents", service_instance.id, **dict(name=service_instance._proc_name, container=service_instance.container.id, resource_id=service_instance.resource_id, agent_id=service_instance.agent_id, def_id=service_instance.agent_def_id, capabilities=caps)) if not service_instance.resource_id: log.warn("Agent process id=%s does not define resource_id!!" % service_instance.id) return service_instance
def assert_configuration(config): """ Checks that configuration is OK. This is separate so that it can be called after config changes (from directory, command line etc) """ from pyon.core.exception import ContainerConfigError from pyon.util.containers import is_basic_identifier if not is_basic_identifier(config.get_safe("system.root_org", "")): raise ContainerConfigError( "Config entry 'system.root_org' has illegal value")
def _create_service_instance(self, process_id, name, module, cls, config): # SERVICE INSTANCE. service_instance = for_name(module, cls) if not isinstance(service_instance, BaseService): raise ContainerConfigError( "Instantiated service not a BaseService %r" % service_instance) # Prepare service instance service_instance.errcause = "" service_instance.id = process_id service_instance.container = self.container service_instance.CFG = config service_instance._proc_name = name # start service dependencies (RPC clients) self._start_service_dependencies(service_instance) return service_instance
def _spawn_agent_process(self, process_id, name, module, cls, config): """ Spawn a process acting as agent process. Attach to service pid. """ service_instance = self._create_service_instance( process_id, name, module, cls, config) if not isinstance(service_instance, ResourceAgent): raise ContainerConfigError( "Agent process must extend ResourceAgent") # Set the resource ID if we get it through the config resource_id = get_safe(service_instance.CFG, "agent.resource_id") if resource_id: service_instance.resource_id = resource_id # Now call the on_init of the agent. self._service_init(service_instance) if not service_instance.resource_id: log.warn("New agent pid=%s has no resource_id set" % process_id) self._service_start(service_instance) self._set_service_endpoint(service_instance, service_instance.id) # Directory registration caps = service_instance.get_capabilities() self.container.directory.register( "/Agents", service_instance.id, **dict(name=service_instance._proc_name, container=service_instance.container.id, resource_id=service_instance.resource_id, agent_id=service_instance.agent_id, def_id=service_instance.agent_def_id, capabilities=caps)) if not service_instance.resource_id: log.warn("Agent process id=%s does not define resource_id!!" % service_instance.id) return service_instance
def _start_service_dependencies(self, service_instance): service_instance.errcause = "setting service dependencies" log.debug("spawn_process dependencies: %s", service_instance.dependencies) # TODO: Service dependency != process dependency for dependency in service_instance.dependencies: client = getattr(service_instance.clients, dependency) assert client, "Client for dependency not found: %s" % dependency # @TODO: should be in a start_client in RPCClient chain client.process = service_instance client.node = self.container.node # ensure that dep actually exists and is running if service_instance.name != 'bootstrap' or ( service_instance.name == 'bootstrap' and service_instance.CFG.level == dependency): svc_de = self.container.directory.lookup("/Services/%s" % dependency) if svc_de is None: raise ContainerConfigError( "Dependency for service %s not running: %s" % (service_instance.name, dependency))
def _create_process_instance(self, process_id, name, module, cls, config): """ Creates an instance of a "service", be it a Service, Agent, Stream, etc. @rtype BaseService @return An instance of a "service" """ # SERVICE INSTANCE. process_instance = for_name(module, cls) if not isinstance(process_instance, BaseService): raise ContainerConfigError( "Instantiated service not a BaseService %r" % process_instance) # Prepare service instance process_instance.errcause = "" process_instance.id = process_id process_instance.container = self.container process_instance.CFG = config process_instance._proc_name = name process_instance._proc_start_time = time.time() #Unless the process has been started as part of another Org, default to the container Org or the ION Org if config.has_key('org_name'): process_instance.org_name = config['org_name'] else: process_instance.org_name = CFG.get_safe( 'container.org_name', CFG.get_safe('system.root_org', 'ION')) # Add stateful process operations if hasattr(process_instance, "_flush_state"): def _flush_state(): if not hasattr(process_instance, "_proc_state"): process_instance._proc_state = {} process_instance._proc_state_changed = False return process_instance.container.state_repository.put_state( process_instance.id, process_instance._proc_state) process_instance._proc_state_changed = False def _load_state(): if not hasattr(process_instance, "_proc_state"): process_instance._proc_state = {} try: new_state = process_instance.container.state_repository.get_state( process_instance.id) process_instance._proc_state.clear() process_instance._proc_state.update(new_state) process_instance._proc_state_changed = False except Exception as ex: log.warn("Process %s load state failed: %s", process_instance.id, str(ex)) process_instance._flush_state = _flush_state process_instance._load_state = _load_state process_start_mode = get_safe(config, "process.start_mode") if process_start_mode == "RESTART": if hasattr(process_instance, "_load_state"): process_instance._load_state() # start service dependencies (RPC clients) self._start_process_dependencies(process_instance) return process_instance
def _spawn_agent_process(self, process_id, name, module, cls, config): """ Spawn a process acting as agent process. Attach to service pid. """ process_instance = self._create_process_instance( process_id, name, module, cls, config) if not isinstance(process_instance, ResourceAgent) and not isinstance( process_instance, SimpleResourceAgent): raise ContainerConfigError( "Agent process must extend ResourceAgent") listeners = [] # Set the resource ID if we get it through the config resource_id = get_safe(process_instance.CFG, "agent.resource_id") if resource_id: process_instance.resource_id = resource_id alistener = self._create_listening_endpoint( node=self.container.node, from_name=resource_id, service=process_instance, process=process_instance) listeners.append(alistener) rsvc = self._create_listening_endpoint(node=self.container.node, from_name=process_instance.id, service=process_instance, process=process_instance) listeners.append(rsvc) # cleanup method to delete process/agent queue (@TODO: leaks a bit here - should use XOs) def agent_cleanup(x): self._cleanup_method(process_instance.id, rsvc) if resource_id: pass #self._cleanup_method(resource_id, alistener) # disabled, it's probably not architecturally correct to delete this queue proc = self.proc_sup.spawn(name=process_instance.id, service=process_instance, listeners=listeners, proc_name=process_instance._proc_name, cleanup_method=agent_cleanup) self.proc_sup.ensure_ready( proc, "_spawn_agent_process for %s" % process_instance.id) # map gproc to process_instance self._spawned_proc_to_process[proc.proc] = process_instance # set service's reference to process process_instance._process = proc # Now call the on_init of the agent. self._process_init(process_instance) if not process_instance.resource_id: log.warn("New agent pid=%s has no resource_id set" % process_id) self._process_start(process_instance) try: proc.start_listeners() except IonProcessError: self._process_quit(process_instance) self._call_proc_state_changed(process_instance, ProcessStateEnum.FAILED) raise if not process_instance.resource_id: log.warn("Agent process id=%s does not define resource_id!!" % process_instance.id) return process_instance
def op_load_system_policies(cls, calling_process): """ Create the initial set of policy rules for the system. To establish clear rule precedence, denying all anonymous access to Org services first and then add rules which Permit access to specific operations based on conditions. """ orgms_client = OrgManagementServiceProcessClient( process=calling_process) policyms_client = PolicyManagementServiceProcessClient( process=calling_process) ion_org = orgms_client.find_org() system_actor = get_system_actor() log.info('System actor: %s', system_actor._id) sa_user_header = get_system_actor_header(system_actor) policy_rules_filename = calling_process.CFG.get_safe( "bootstrap.initial_policy_rules") if not policy_rules_filename: raise ContainerConfigError("Policy rules file not configured") if not os.path.exists(policy_rules_filename): raise ContainerConfigError("Policy rules file does not exist") with open(policy_rules_filename, "r") as f: policy_rules_yml = f.read() policy_rules_cfg = yaml.safe_load(policy_rules_yml) if "type" not in policy_rules_cfg or policy_rules_cfg[ "type"] != "scioncc_policy_rules": raise ContainerConfigError("Invalid policy rules file content") log.info("Loading %s policy rules", len(policy_rules_cfg["rules"])) for rule_cfg in policy_rules_cfg["rules"]: rule_name, policy_type, rule_desc = rule_cfg["name"], rule_cfg[ "policy_type"], rule_cfg.get("description", "") if rule_cfg.get("enable") is False: log.info("Policy rule %s disabled", rule_name) continue log.info("Loading policy rule %s (%s)", rule_name, policy_type) rule_filename = rule_cfg["rule_def"] if not os.path.isabs(rule_filename): rule_filename = os.path.join( os.path.dirname(policy_rules_filename), rule_filename) with open(rule_filename, "r") as f: rule_def = f.read() ordinal = rule_cfg.get("ordinal", 0) # Create the policy if policy_type == "common_service_access": policyms_client.create_common_service_access_policy( rule_name, rule_desc, rule_def, ordinal=ordinal, headers=sa_user_header) elif policy_type == "service_access": service_name = rule_cfg["service_name"] policyms_client.create_service_access_policy( service_name, rule_name, rule_desc, rule_def, ordinal=ordinal, headers=sa_user_header) elif policy_type == "resource_access": resource_type, resource_name = rule_cfg[ "resource_type"], rule_cfg["resource_name"] res_ids, _ = calling_process.container.resource_registry.find_resources( restype=resource_type, name=resource_name, id_only=True) if res_ids: resource_id = res_ids[0] policyms_client.create_resource_access_policy( resource_id, rule_name, rule_desc, rule_def, ordinal=ordinal, headers=sa_user_header) else: raise ContainerConfigError( "Rule %s has invalid policy type: %s" % (rule_name, policy_type))