def test_stack_by_name_tenants(self): self.assertEqual(self.stack.id, db_api.stack_get_by_name(self.ctx, self.stack_name).id) ctx2 = create_context(self.m, self.username, 'stack_service_test_tenant2') self.assertEqual(None, db_api.stack_get_by_name(ctx2, self.stack_name))
def run_rule(self, context, wr, now=timeutils.utcnow()): action_map = {'ALARM': 'AlarmActions', 'NORMAL': 'OKActions', 'NODATA': 'InsufficientDataActions'} watcher = watchrule.WatchRule(wr.rule, wr.watch_data, wr.last_evaluated, now) new_state = watcher.get_alarm_state() if new_state != wr.state: logger.warn('WATCH: stack:%s, watch_name:%s %s', wr.stack_name, wr.name, new_state) if not action_map[new_state] in wr.rule: logger.info('no action for new state %s', new_state) wr.state = new_state wr.save() else: s = db_api.stack_get_by_name(None, wr.stack_name) if s and s.status in ('CREATE_COMPLETE', 'UPDATE_COMPLETE'): user_creds = db_api.user_creds_get(s.user_creds_id) ctxt = ctxtlib.RequestContext.from_dict(dict(user_creds)) stack = parser.Stack.load(ctxt, s.id) for a in wr.rule[action_map[new_state]]: greenpool.spawn_n(stack[a].alarm) wr.state = new_state wr.save() wr.last_evaluated = now
def describe_stack_resources(self, context, stack_name, physical_resource_id, logical_resource_id): auth.authenticate(context) if stack_name is not None: s = db_api.stack_get_by_name(context, stack_name) else: rs = db_api.resource_get_by_physical_resource_id(context, physical_resource_id) if not rs: msg = "The specified PhysicalResourceId doesn't exist" raise AttributeError(msg) s = rs.stack if not s: raise AttributeError("The specified stack doesn't exist") stack = parser.Stack.load(context, s.id) if logical_resource_id is not None: name_match = lambda r: r.name == logical_resource_id else: name_match = lambda r: True return [api.format_stack_resource(resource) for resource in stack if resource.id is not None and name_match(resource)]
def create_stack(self, context, stack_name, template, params, args): """ The create_stack method creates a new stack using the template provided. Note that at this stage the template has already been fetched from the heat-api process if using a template-url. arg1 -> RPC context. arg2 -> Name of the stack you want to create. arg3 -> Template of stack you want to create. arg4 -> Stack Input Params arg4 -> Request parameters/args passed from API """ logger.info('template is %s' % template) if db_api.stack_get_by_name(None, stack_name): raise AttributeError('Stack already exists with that name') tmpl = parser.Template(template) # Extract the template parameters, and any common query parameters template_params = parser.Parameters(stack_name, tmpl, params) common_params = api.extract_args(args) stack = parser.Stack(context, stack_name, tmpl, template_params, **common_params) response = stack.validate() if response['Description'] != 'Successfully validated': return response stack_id = stack.store() greenpool.spawn_n(stack.create) return dict(stack.identifier())
def event_create(self, context, event): stack_name = event['stack'] resource_name = event['resource'] stack = db_api.stack_get_by_name(context, stack_name) resource = db_api.resource_get_by_name_and_stack(context, resource_name, stack.id) if not resource: return ['Unknown resource', None] new_event = { 'name': event['message'], 'resource_status_reason': event['reason'], 'StackId': stack.id, 'LogicalResourceId': resource.name, 'PhysicalResourceId': None, 'ResourceType': event['resource_type'], 'ResourceProperties': {}, } try: result = db_api.event_create(context, new_event) new_event['id'] = result.id return [None, new_event] except Exception as ex: logger.warn('db error %s' % str(ex)) msg = 'Error creating event' return [msg, None]
def create_stack(self, cnxt, stack_name, template, params, files, args): """ The create_stack method creates a new stack using the template provided. Note that at this stage the template has already been fetched from the heat-api process if using a template-url. :param cnxt: RPC context. :param stack_name: Name of the stack you want to create. :param template: Template of stack you want to create. :param params: Stack Input Params :param files: Files referenced from the template (currently provider templates). :param args: Request parameters/args passed from API """ logger.info('template is %s' % template) def _stack_create(stack): # Create the stack, and create the periodic task if successful stack.create() if stack.action == stack.CREATE and stack.status == stack.COMPLETE: # Schedule a periodic watcher task for this stack self._start_watch_task(stack.id, cnxt) else: logger.warning("Stack create failed, status %s" % stack.status) if db_api.stack_get_by_name(cnxt, stack_name): raise exception.StackExists(stack_name=stack_name) tenant_limit = cfg.CONF.max_stacks_per_tenant if db_api.stack_count_all_by_tenant(cnxt) >= tenant_limit: message = _("You have reached the maximum stacks per tenant, %d." " Please delete some stacks.") % tenant_limit raise exception.RequestLimitExceeded(message=message) tmpl = parser.Template(template, files=files) if len(tmpl[tpl.RESOURCES]) > cfg.CONF.max_resources_per_stack: raise exception.StackResourceLimitExceeded() # Extract the common query parameters common_params = api.extract_args(args) env = environment.Environment(params) stack = parser.Stack(cnxt, stack_name, tmpl, env, **common_params) self._validate_deferred_auth_context(cnxt, stack) stack.validate() # Creates a trust and sets the trust_id and trustor_user_id in # the current context, before we store it in stack.store() # Does nothing if deferred_auth_method is 'password' stack.clients.keystone().create_trust_context() stack_id = stack.store() self._start_in_thread(stack_id, _stack_create, stack) return dict(stack.identifier())
def delete_stack(self, stack_name): cnxt = utils.dummy_context() db_stack = db_api.stack_get_by_name(cnxt, stack_name) stack_identity = {'stack_name': stack_name, 'stack_id': db_stack.id, 'tenant': db_stack.tenant, 'path': ''} srv = service.EngineService("host", "engine") srv.delete_stack(cnxt, stack_identity)
def metadata_list_resources(self, context, stack_name): """ Return the resource IDs of the given stack. """ stack = db_api.stack_get_by_name(None, stack_name) if stack: return [res.name for res in stack.resources] else: return None
def list_stack_resources(self, context, stack_name): auth.authenticate(context) s = db_api.stack_get_by_name(context, stack_name) if not s: raise AttributeError('Unknown stack name') stack = parser.Stack.load(context, s.id) return [api.format_stack_resource(resource) for resource in stack if resource.id is not None]
def delete_stack(self, stack_name): cnxt = utils.dummy_context() db_stack = db_api.stack_get_by_name(cnxt, stack_name) stack_identity = {'stack_name': stack_name, 'stack_id': db_stack.id, 'tenant': db_stack.tenant, 'path': ''} srv = service.EngineService("host", "engine") srv.thread_group_mgr = SynchronousThreadGroupManager() srv.worker_service = self.worker srv.delete_stack(cnxt, stack_identity)
def get_template(self, context, stack_name, params): """ Get the template. arg1 -> RPC context. arg2 -> Name of the stack you want to see. arg3 -> Dict of http request parameters passed in from API side. """ auth.authenticate(context) s = db_api.stack_get_by_name(context, stack_name) if s: return s.raw_template.template return None
def identify_stack(self, cnxt, stack_name): """ The identify_stack method returns the full stack identifier for a single, live stack given the stack name. :param cnxt: RPC context. :param stack_name: Name or UUID of the stack to look up. """ if uuidutils.is_uuid_like(stack_name): s = db_api.stack_get(cnxt, stack_name, show_deleted=True) # may be the name is in uuid format, so if get by id returns None, # we should get the info by name again if not s: s = db_api.stack_get_by_name(cnxt, stack_name) else: s = db_api.stack_get_by_name(cnxt, stack_name) if s: stack = parser.Stack.load(cnxt, stack=s) return dict(stack.identifier()) else: raise exception.StackNotFound(stack_name=stack_name)
def identify_stack(self, context, stack_name): """ The identify_stack method returns the full stack identifier for a single, live stack given the stack name. arg1 -> RPC context. arg2 -> Name of the stack to look up. """ s = db_api.stack_get_by_name(context, stack_name) if s: stack = parser.Stack.load(context, s.id) return dict(stack.identifier()) else: raise AttributeError('Unknown stack name')
def update_stack(self, stack_name, scenario_tmpl): cnxt = utils.dummy_context() db_stack = db_api.stack_get_by_name(cnxt, stack_name) srv = service.EngineService("host", "engine") thread_group_mgr = service.ThreadGroupManager() srv.thread_group_mgr = thread_group_mgr hot_tmpl = self.scenario_template_to_hot(scenario_tmpl) stack_identity = {'stack_name': stack_name, 'stack_id': db_stack.id, 'tenant': db_stack.tenant, 'path': ''} srv.update_stack(cnxt, stack_identity, hot_tmpl, params={}, files={}, environment_files=None, args={})
def _validate_new_stack(self, cnxt, stack_name, parsed_template): if db_api.stack_get_by_name(cnxt, stack_name): raise exception.StackExists(stack_name=stack_name) tenant_limit = cfg.CONF.max_stacks_per_tenant if db_api.stack_count_all(cnxt) >= tenant_limit: message = _("You have reached the maximum stacks per tenant, %d." " Please delete some stacks.") % tenant_limit raise exception.RequestLimitExceeded(message=message) num_resources = len(parsed_template[parsed_template.RESOURCES]) if num_resources > cfg.CONF.max_resources_per_stack: message = exception.StackResourceLimitExceeded.msg_fmt raise exception.RequestLimitExceeded(message=message)
def describe_stack_resource(self, context, stack_name, resource_name): auth.authenticate(context) s = db_api.stack_get_by_name(context, stack_name) if not s: raise AttributeError('Unknown stack name') stack = parser.Stack.load(context, s.id) if resource_name not in stack: raise AttributeError('Unknown resource name') resource = stack[resource_name] if resource.id is None: raise AttributeError('Resource not created') return api.format_stack_resource(stack[resource_name])
def identify_stack(self, cnxt, stack_name): """ The identify_stack method returns the full stack identifier for a single, live stack given the stack name. arg1 -> RPC context. arg2 -> Name or UUID of the stack to look up. """ if uuidutils.is_uuid_like(stack_name): s = db_api.stack_get(cnxt, stack_name, show_deleted=True) else: s = db_api.stack_get_by_name(cnxt, stack_name) if s: stack = parser.Stack.load(cnxt, stack=s) return dict(stack.identifier()) else: raise exception.StackNotFound(stack_name=stack_name)
def create_stack(self, cnxt, stack_name, template, params, files, args): """ The create_stack method creates a new stack using the template provided. Note that at this stage the template has already been fetched from the heat-api process if using a template-url. :param cnxt: RPC context. :param stack_name: Name of the stack you want to create. :param template: Template of stack you want to create. :param params: Stack Input Params :param files: Files referenced from the template (currently provider templates). :param args: Request parameters/args passed from API """ logger.info('template is %s' % template) self._validate_mandatory_credentials(cnxt) def _stack_create(stack): # Create the stack, and create the periodic task if successful stack.create() if stack.action == stack.CREATE and stack.status == stack.COMPLETE: # Schedule a periodic watcher task for this stack self._timer_in_thread(stack.id, self._periodic_watcher_task, sid=stack.id) else: logger.warning("Stack create failed, status %s" % stack.status) if db_api.stack_get_by_name(cnxt, stack_name): raise exception.StackExists(stack_name=stack_name) tmpl = parser.Template(template, files=files) # Extract the common query parameters common_params = api.extract_args(args) env = environment.Environment(params) stack = parser.Stack(cnxt, stack_name, tmpl, env, **common_params) stack.validate() stack_id = stack.store() self._start_in_thread(stack_id, _stack_create, stack) return dict(stack.identifier())
def create_stack(self, context, stack_name, template, params, args): """ The create_stack method creates a new stack using the template provided. Note that at this stage the template has already been fetched from the heat-api process if using a template-url. arg1 -> RPC context. arg2 -> Name of the stack you want to create. arg3 -> Template of stack you want to create. arg4 -> Stack Input Params arg4 -> Request parameters/args passed from API """ logger.info('template is %s' % template) def _stack_create(stack): # Create the stack, and create the periodic task if successful stack.create() if stack.state == stack.CREATE_COMPLETE: # Schedule a periodic watcher task for this stack self._timer_in_thread(stack.id, self._periodic_watcher_task, sid=stack.id) else: logger.warning("Stack create failed, state %s" % stack.state) if db_api.stack_get_by_name(context, stack_name): raise exception.StackExists(stack_name=stack_name) tmpl = parser.Template(template) # Extract the template parameters, and any common query parameters template_params = parser.Parameters(stack_name, tmpl, params) common_params = api.extract_args(args) stack = parser.Stack(context, stack_name, tmpl, template_params, **common_params) response = stack.validate() if response: return {'Description': response} stack_id = stack.store() self._start_in_thread(stack_id, _stack_create, stack) return dict(stack.identifier())
def _backup_stack(self, create_if_missing=True): """ Get a Stack containing any in-progress resources from the previous stack state prior to an update. """ s = db_api.stack_get_by_name(self.context, self._backup_name(), owner_id=self.id) if s is not None: logger.debug(_("Loaded existing backup stack")) return self.load(self.context, stack=s) elif create_if_missing: templ = Template.load(self.context, self.t.id) templ.files = copy.deepcopy(self.t.files) prev = type(self)(self.context, self.name, templ, self.env, owner_id=self.id) prev.store(backup=True) logger.debug(_("Created new backup stack")) return prev else: return None
def _backup_stack(self, create_if_missing=True): ''' Get a Stack containing any in-progress resources from the previous stack state prior to an update. ''' s = db_api.stack_get_by_name(self.context, self._backup_name(), owner_id=self.id) if s is not None: logger.debug('Loaded existing backup stack') return self.load(self.context, stack=s) elif create_if_missing: prev = type(self)(self.context, self.name, self.t, self.env, owner_id=self.id) prev.store(backup=True) logger.debug('Created new backup stack') return prev else: return None
def metadata_get_resource(self, context, stack_name, resource_name): """ Get the metadata for the given resource. """ s = db_api.stack_get_by_name(None, stack_name) if not s: logger.warn("Stack %s not found" % stack_name) return ['stack', None] stack = parser.Stack.load(None, s.id) if resource_name not in stack: logger.warn("Resource not found %s:%s." % (stack_name, resource_name)) return ['resource', None] resource = stack[resource_name] return [None, resource.metadata]
def delete_stack(self, context, stack_name, params): """ The delete_stack method deletes a given stack. arg1 -> RPC context. arg2 -> Name of the stack you want to delete. arg3 -> Params passed from API. """ auth.authenticate(context) st = db_api.stack_get_by_name(context, stack_name) if not st: raise AttributeError('Unknown stack name') logger.info('deleting stack %s' % stack_name) stack = parser.Stack.load(context, st.id) greenpool.spawn_n(stack.delete) return None
def list_events(self, context, stack_name, params): """ The list_events method lists all events associated with a given stack. arg1 -> RPC context. arg2 -> Name of the stack you want to get events for. arg3 -> Params passed from API. """ auth.authenticate(context) if stack_name is not None: st = db_api.stack_get_by_name(context, stack_name) if not st: raise AttributeError('Unknown stack name') events = db_api.event_get_all_by_stack(context, st.id) else: events = db_api.event_get_all_by_tenant(context) return {'events': [api.format_event(e) for e in events]}
def update_stack(self, context, stack_name, template, params, args): """ The update_stack method updates an existing stack based on the provided template and parameters. Note that at this stage the template has already been fetched from the heat-api process if using a template-url. arg1 -> RPC context. arg2 -> Name of the stack you want to create. arg3 -> Template of stack you want to create. arg4 -> Stack Input Params arg4 -> Request parameters/args passed from API """ logger.info('template is %s' % template) auth.authenticate(context) # Get the database representation of the existing stack db_stack = db_api.stack_get_by_name(None, stack_name) if not db_stack: raise AttributeError('No stack exists with that name') current_stack = parser.Stack.load(context, db_stack.id) # Now parse the template and any parameters for the updated # stack definition. tmpl = parser.Template(template) template_params = parser.Parameters(stack_name, tmpl, params) common_params = api.extract_args(args) updated_stack = parser.Stack(context, stack_name, tmpl, template_params, **common_params) response = updated_stack.validate() if response['Description'] != 'Successfully validated': return response greenpool.spawn_n(current_stack.update, updated_stack) return {'StackName': current_stack.name, 'StackId': current_stack.id}
def show_stack(self, context, stack_name, params): """ The show_stack method returns the attributes of one stack. arg1 -> RPC context. arg2 -> Name of the stack you want to see, or None to see all arg3 -> Dict of http request parameters passed in from API side. """ auth.authenticate(context) if stack_name is not None: s = db_api.stack_get_by_name(context, stack_name) if s: stacks = [s] else: raise AttributeError('Unknown stack name') else: stacks = db_api.stack_get_by_tenant(context) or [] def format_stack_detail(s): stack = parser.Stack.load(context, s.id) return api.format_stack(stack) return {'stacks': [format_stack_detail(s) for s in stacks]}
def rule_action(self, new_state): logger.warn('WATCH: stack:%s, watch_name:%s %s', self.stack_name, self.name, new_state) actioned = False if not self.ACTION_MAP[new_state] in self.rule: logger.info('no action for new state %s', new_state) actioned = True else: s = db_api.stack_get_by_name(None, self.stack_name) if s and s.status in (parser.Stack.CREATE_COMPLETE, parser.Stack.UPDATE_COMPLETE): user_creds = db_api.user_creds_get(s.user_creds_id) ctxt = ctxtlib.RequestContext.from_dict(user_creds) stack = parser.Stack.load(ctxt, s.id) for a in self.rule[self.ACTION_MAP[new_state]]: greenpool.spawn_n(stack[a].alarm) actioned = True else: logger.warning("Could not process watch state %s for stack" % new_state) return actioned
def create_stack(self, context, stack_name, template, params, args): """ The create_stack method creates a new stack using the template provided. Note that at this stage the template has already been fetched from the heat-api process if using a template-url. arg1 -> RPC context. arg2 -> Name of the stack you want to create. arg3 -> Template of stack you want to create. arg4 -> Stack Input Params arg4 -> Request parameters/args passed from API """ logger.info("template is %s" % template) if db_api.stack_get_by_name(context, stack_name): raise AttributeError("Stack already exists with that name") tmpl = parser.Template(template) # Extract the template parameters, and any common query parameters template_params = parser.Parameters(stack_name, tmpl, params) common_params = api.extract_args(args) stack = parser.Stack(context, stack_name, tmpl, template_params, **common_params) response = stack.validate() if response: return {"Description": response} stack_id = stack.store() self._start_in_thread(stack_id, stack_name, stack.create) # Schedule a periodic watcher task for this stack self._timer_in_thread(stack_id, stack_name, self._periodic_watcher_task, sid=stack_id) return dict(stack.identifier())
def create_stack(self, cnxt, stack_name, template, params, files, args): """ The create_stack method creates a new stack using the template provided. Note that at this stage the template has already been fetched from the heat-api process if using a template-url. :param cnxt: RPC context. :param stack_name: Name of the stack you want to create. :param template: Template of stack you want to create. :param params: Stack Input Params :param files: Files referenced from the template :param args: Request parameters/args passed from API """ logger.info(_('template is %s') % template) def _stack_create(stack): # Create/Adopt a stack, and create the periodic task if successful if stack.adopt_stack_data: stack.adopt() else: stack.create() if (stack.action in (stack.CREATE, stack.ADOPT) and stack.status == stack.COMPLETE): # Schedule a periodic watcher task for this stack self._start_watch_task(stack.id, cnxt) else: logger.warning(_("Stack create failed, status %s") % stack.status) if db_api.stack_get_by_name(cnxt, stack_name): raise exception.StackExists(stack_name=stack_name) tenant_limit = cfg.CONF.max_stacks_per_tenant if db_api.stack_count_all_by_tenant(cnxt) >= tenant_limit: message = _("You have reached the maximum stacks per tenant, %d." " Please delete some stacks.") % tenant_limit raise exception.RequestLimitExceeded(message=message) tmpl = parser.Template(template, files=files) if len(tmpl[tmpl.RESOURCES]) > cfg.CONF.max_resources_per_stack: raise exception.RequestLimitExceeded( message=exception.StackResourceLimitExceeded.msg_fmt) # Extract the common query parameters common_params = api.extract_args(args) env = environment.Environment(params) stack = parser.Stack(cnxt, stack_name, tmpl, env, **common_params) self._validate_deferred_auth_context(cnxt, stack) stack.validate() stack.store() self.thread_group_mgr.start_with_lock(cnxt, stack, self.engine_id, _stack_create, stack) return dict(stack.identifier())
def get_by_name(cls, context, stack_name): db_stack = db_api.stack_get_by_name(context, six.text_type(stack_name)) if not db_stack: return None stack = cls._from_db_object(context, cls(context), db_stack) return stack
def get_by_name(cls, context, stack_name): db_stack = db_api.stack_get_by_name(context, stack_name) if not db_stack: return None stack = cls._from_db_object(context, cls(context), db_stack) return stack
def rollback_stack(self, stack_name): cntxt = utils.dummy_context() db_stack = db_api.stack_get_by_name(cntxt, stack_name) stk = stack.Stack.load(cntxt, stack=db_stack) stk.rollback()