Пример #1
0
 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))
Пример #2
0
    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
Пример #3
0
    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)]
Пример #4
0
    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())
Пример #5
0
 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]
Пример #6
0
    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())
Пример #7
0
 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)
Пример #8
0
 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
Пример #9
0
    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]
Пример #10
0
 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)
Пример #11
0
 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
Пример #12
0
    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)
Пример #13
0
 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')
Пример #14
0
 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={})
Пример #15
0
    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)
Пример #16
0
    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])
Пример #17
0
 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)
Пример #18
0
    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())
Пример #19
0
    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())
Пример #20
0
 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
Пример #21
0
 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
Пример #22
0
    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]
Пример #23
0
    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
Пример #24
0
    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]}
Пример #25
0
    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}
Пример #26
0
    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]}
Пример #27
0
    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
Пример #28
0
    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())
Пример #29
0
    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())
Пример #30
0
 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
Пример #31
0
 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
Пример #32
0
 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()
Пример #33
0
 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()