예제 #1
0
    def before(self, state):
        headers = state.request.headers
        user = headers.get('X-User')
        user_id = headers.get('X-User-Id')
        project = headers.get('X-Project-Name')
        project_id = headers.get('X-Project-Id')
        domain_id = headers.get('X-User-Domain-Id')
        domain_name = headers.get('X-User-Domain-Name')
        auth_token = headers.get('X-Storage-Token')
        auth_token = headers.get('X-Auth-Token', auth_token)
        show_deleted = headers.get('X-Show-Deleted')
        auth_token_info = state.request.environ.get('keystone.token_info')
        roles = (headers.get('X-Roles', None)
                 and headers.get('X-Roles').split(','))

        auth_url = headers.get('X-Auth-Url')
        if auth_url is None:
            importutils.import_module('keystonemiddleware.auth_token')
            auth_url = cfg.CONF.keystone_authtoken.auth_uri

        state.request.context = context.make_context(
            auth_token=auth_token,
            auth_url=auth_url,
            auth_token_info=auth_token_info,
            user=user,
            user_id=user_id,
            project=project,
            project_id=project_id,
            domain_id=domain_id,
            domain_name=domain_name,
            show_deleted=show_deleted,
            roles=roles)
예제 #2
0
    def before(self, state):
        headers = state.request.headers
        user = headers.get('X-User')
        user_id = headers.get('X-User-Id')
        project = headers.get('X-Project-Name')
        project_id = headers.get('X-Project-Id')
        domain_id = headers.get('X-User-Domain-Id')
        domain_name = headers.get('X-User-Domain-Name')
        auth_token = headers.get('X-Storage-Token')
        auth_token = headers.get('X-Auth-Token', auth_token)
        show_deleted = headers.get('X-Show-Deleted')
        auth_token_info = state.request.environ.get('keystone.token_info')
        roles = (headers.get('X-Roles', None)
                 and headers.get('X-Roles').split(','))

        state.request.context = context.make_context(
            auth_token=auth_token,
            auth_token_info=auth_token_info,
            user=user,
            user_id=user_id,
            project=project,
            project_id=project_id,
            domain_id=domain_id,
            domain_name=domain_name,
            show_deleted=show_deleted,
            roles=roles)
예제 #3
0
파일: hooks.py 프로젝트: Jean-Emile/watcher
    def before(self, state):
        headers = state.request.headers
        user = headers.get('X-User')
        user_id = headers.get('X-User-Id')
        project = headers.get('X-Project-Name')
        project_id = headers.get('X-Project-Id')
        domain_id = headers.get('X-User-Domain-Id')
        domain_name = headers.get('X-User-Domain-Name')
        auth_token = headers.get('X-Storage-Token')
        auth_token = headers.get('X-Auth-Token', auth_token)
        show_deleted = headers.get('X-Show-Deleted')
        auth_token_info = state.request.environ.get('keystone.token_info')

        auth_url = headers.get('X-Auth-Url')
        if auth_url is None:
            importutils.import_module('keystonemiddleware.auth_token')
            auth_url = cfg.CONF.keystone_authtoken.auth_uri

        state.request.context = context.make_context(
            auth_token=auth_token,
            auth_url=auth_url,
            auth_token_info=auth_token_info,
            user=user,
            user_id=user_id,
            project=project,
            project_id=project_id,
            domain_id=domain_id,
            domain_name=domain_name,
            show_deleted=show_deleted)
예제 #4
0
파일: base.py 프로젝트: sjamgade/watcher
    def __init__(self, config, osc=None):
        """Constructor: the signature should be identical within the subclasses

        :param config: Configuration related to this plugin
        :type config: :py:class:`~.Struct`
        :param osc: An OpenStackClients instance
        :type osc: :py:class:`~.OpenStackClients` instance
        """
        super(BaseStrategy, self).__init__(config)
        self.ctx = context.make_context()
        self._name = self.get_name()
        self._display_name = self.get_display_name()
        self._goal = self.get_goal()
        # default strategy level
        self._strategy_level = level.StrategyLevel.conservative
        self._cluster_state_collector = None
        # the solution given by the strategy
        self._solution = default.DefaultSolution(goal=self.goal, strategy=self)
        self._osc = osc
        self._collector_manager = None
        self._compute_model = None
        self._storage_model = None
        self._baremetal_model = None
        self._input_parameters = utils.Struct()
        self._audit_scope = None
        self._datasource_backend = None
예제 #5
0
 def test_action_plan_init(self, m_request):
     m_request.context = context.make_context()
     act_plan_dict = api_utils.action_plan_post_data()
     del act_plan_dict['state']
     del act_plan_dict['audit_id']
     del act_plan_dict['first_action_id']
     act_plan = api_action_plan.ActionPlan(**act_plan_dict)
     self.assertEqual(wtypes.Unset, act_plan.state)
예제 #6
0
class AuditTemplatePatchType(types.JsonPatchType):

    _ctx = context_utils.make_context()

    @staticmethod
    def mandatory_attrs():
        return []

    @staticmethod
    def validate(patch):
        if patch.path == "/goal" and patch.op != "remove":
            AuditTemplatePatchType._validate_goal(patch)
        elif patch.path == "/goal" and patch.op == "remove":
            raise exception.OperationNotPermitted(
                _("Cannot remove 'goal' attribute "
                  "from an audit template"))
        if patch.path == "/strategy":
            AuditTemplatePatchType._validate_strategy(patch)
        return types.JsonPatchType.validate(patch)

    @staticmethod
    def _validate_goal(patch):
        patch.path = "/goal_id"
        goal = patch.value

        if goal:
            available_goals = objects.Goal.list(AuditTemplatePatchType._ctx)
            available_goal_uuids_map = {g.uuid: g for g in available_goals}
            available_goal_names_map = {g.name: g for g in available_goals}
            if goal in available_goal_uuids_map:
                patch.value = available_goal_uuids_map[goal].id
            elif goal in available_goal_names_map:
                patch.value = available_goal_names_map[goal].id
            else:
                raise exception.InvalidGoal(goal=goal)

    @staticmethod
    def _validate_strategy(patch):
        patch.path = "/strategy_id"
        strategy = patch.value
        if strategy:
            available_strategies = objects.Strategy.list(
                AuditTemplatePatchType._ctx)
            available_strategy_uuids_map = {
                s.uuid: s
                for s in available_strategies
            }
            available_strategy_names_map = {
                s.name: s
                for s in available_strategies
            }
            if strategy in available_strategy_uuids_map:
                patch.value = available_strategy_uuids_map[strategy].id
            elif strategy in available_strategy_names_map:
                patch.value = available_strategy_names_map[strategy].id
            else:
                raise exception.InvalidStrategy(strategy=strategy)
예제 #7
0
 def add_checkstate_job(self):
     # 30 minutes interval
     interval = CONF.watcher_decision_engine.check_periodic_interval
     ap_manager = objects.action_plan.StateManager()
     if CONF.watcher_decision_engine.action_plan_expiry != 0:
         self.add_job(ap_manager.check_expired,
                      'interval',
                      args=[context.make_context()],
                      seconds=interval,
                      next_run_time=datetime.datetime.now())
예제 #8
0
 def start(self):
     """Start service."""
     context = watcher_context.make_context(is_admin=True)
     self.add_job(self.get_services_status,
                  name='service_status',
                  trigger='interval',
                  jobstore='default',
                  args=[context],
                  next_run_time=datetime.datetime.now(),
                  seconds=CONF.periodic_interval)
     super(APISchedulingService, self).start()
예제 #9
0
def _get_action_plan_payload(action):
    action_plan = None
    strategy_uuid = None
    audit = None
    try:
        action_plan = action.action_plan
        audit = objects.Audit.get(wcontext.make_context(show_deleted=True),
                                  action_plan.audit_id)
        if audit.strategy_id:
            strategy_uuid = objects.Strategy.get(
                wcontext.make_context(show_deleted=True),
                audit.strategy_id).uuid
    except NotImplementedError:
        raise exception.EagerlyLoadedActionRequired(action=action.uuid)

    action_plan_payload = ap_notifications.TerseActionPlanPayload(
        action_plan=action_plan,
        audit_uuid=audit.uuid, strategy_uuid=strategy_uuid)

    return action_plan_payload
예제 #10
0
파일: sync.py 프로젝트: Oliverlyn/watcher
    def __init__(self):
        self.ctx = context.make_context()
        self.discovered_map = None

        self._available_goals = None
        self._available_goals_map = None

        self._available_strategies = None
        self._available_strategies_map = None

        # This goal mapping maps stale goal IDs to the synced goal
        self.goal_mapping = dict()
        # This strategy mapping maps stale strategy IDs to the synced goal
        self.strategy_mapping = dict()

        self.stale_audit_templates_map = {}
예제 #11
0
    def setUp(self):
        super(TestSyncer, self).setUp()
        self.ctx = context.make_context()

        # This mock simulates the strategies discovery done in discover()
        self.m_available_strategies = mock.Mock(
            return_value={
                fake_strategies.FakeDummy1Strategy1.get_name():
                fake_strategies.FakeDummy1Strategy1,
                fake_strategies.FakeDummy1Strategy2.get_name():
                fake_strategies.FakeDummy1Strategy2,
                fake_strategies.FakeDummy2Strategy3.get_name():
                fake_strategies.FakeDummy2Strategy3,
                fake_strategies.FakeDummy2Strategy4.get_name():
                fake_strategies.FakeDummy2Strategy4,
            })

        self.m_available_goals = mock.Mock(
            return_value={
                fake_goals.FakeDummy1.get_name(): fake_goals.FakeDummy1,
                fake_goals.FakeDummy2.get_name(): fake_goals.FakeDummy2,
            })

        self.goal1_spec = fake_goals.FakeDummy1(
            config=mock.Mock()).get_efficacy_specification()
        self.goal2_spec = fake_goals.FakeDummy2(
            config=mock.Mock()).get_efficacy_specification()

        p_goals_load = mock.patch.object(
            default.DefaultGoalLoader,
            'load',
            side_effect=lambda goal: self.m_available_goals()[goal]())
        p_goals = mock.patch.object(default.DefaultGoalLoader,
                                    'list_available', self.m_available_goals)
        p_strategies = mock.patch.object(default.DefaultStrategyLoader,
                                         'list_available',
                                         self.m_available_strategies)

        p_goals.start()
        p_goals_load.start()
        p_strategies.start()

        self.syncer = sync.Syncer()
        self.addCleanup(p_goals.stop)
        self.addCleanup(p_goals_load.stop)
        self.addCleanup(p_strategies.stop)
예제 #12
0
 def sync(self):
     ctx = context.make_context()
     action_loader = default.DefaultActionLoader()
     available_actions = action_loader.list_available()
     for action_type in available_actions.keys():
         load_action = action_loader.load(action_type)
         load_description = load_action.get_description()
         try:
             action_desc = objects.ActionDescription.get_by_type(
                 ctx, action_type)
             if action_desc.description != load_description:
                 action_desc.description = load_description
                 action_desc.save()
         except exception.ActionDescriptionNotFound:
             obj_action_desc = objects.ActionDescription(ctx)
             obj_action_desc.action_type = action_type
             obj_action_desc.description = load_description
             obj_action_desc.create()
예제 #13
0
 def __init__(self,
              url=None,
              engine=None,
              tablename='apscheduler_jobs',
              metadata=None,
              pickle_protocol=pickle.HIGHEST_PROTOCOL,
              tag=None):
     super(WatcherJobStore, self).__init__(url, engine, tablename, metadata,
                                           pickle_protocol)
     metadata = maybe_ref(metadata) or MetaData()
     self.jobs_t = Table(tablename,
                         metadata,
                         autoload=True,
                         autoload_with=engine)
     service_ident = service.ServiceHeartbeat.get_service_name()
     self.tag = tag or {'host': service_ident[0], 'name': service_ident[1]}
     self.service_id = objects.Service.list(context=context.make_context(),
                                            filters=self.tag)[0].id
예제 #14
0
    def setUp(self):
        super(TestSyncer, self).setUp()
        self.ctx = context.make_context()

        # This mock simulates the strategies discovery done in discover()
        self.m_available_strategies = mock.Mock(return_value={
            fake_strategies.FakeDummy1Strategy1.get_name():
                fake_strategies.FakeDummy1Strategy1,
            fake_strategies.FakeDummy1Strategy2.get_name():
                fake_strategies.FakeDummy1Strategy2,
            fake_strategies.FakeDummy2Strategy3.get_name():
                fake_strategies.FakeDummy2Strategy3,
            fake_strategies.FakeDummy2Strategy4.get_name():
                fake_strategies.FakeDummy2Strategy4,
        })

        self.m_available_goals = mock.Mock(return_value={
            fake_goals.FakeDummy1.get_name(): fake_goals.FakeDummy1,
            fake_goals.FakeDummy2.get_name(): fake_goals.FakeDummy2,
        })

        self.goal1_spec = fake_goals.FakeDummy1(
            config=mock.Mock()).get_efficacy_specification()
        self.goal2_spec = fake_goals.FakeDummy2(
            config=mock.Mock()).get_efficacy_specification()

        p_goals_load = mock.patch.object(
            default.DefaultGoalLoader, 'load',
            side_effect=lambda goal: self.m_available_goals()[goal]())
        p_goals = mock.patch.object(
            default.DefaultGoalLoader, 'list_available',
            self.m_available_goals)
        p_strategies = mock.patch.object(
            default.DefaultStrategyLoader, 'list_available',
            self.m_available_strategies)

        p_goals.start()
        p_goals_load.start()
        p_strategies.start()

        self.syncer = sync.Syncer()
        self.addCleanup(p_goals.stop)
        self.addCleanup(p_goals_load.stop)
        self.addCleanup(p_strategies.stop)
예제 #15
0
def _get_common_payload(action_plan):
    audit = None
    strategy = None
    try:
        audit = action_plan.audit
        strategy = action_plan.strategy
    except NotImplementedError:
        raise exception.EagerlyLoadedActionPlanRequired(
            action_plan=action_plan.uuid)

    goal = objects.Goal.get(wcontext.make_context(show_deleted=True),
                            audit.goal_id)
    audit_payload = audit_notifications.TerseAuditPayload(audit=audit,
                                                          goal_uuid=goal.uuid)

    strategy_payload = strategy_notifications.StrategyPayload(
        strategy=strategy)

    return audit_payload, strategy_payload
예제 #16
0
 def cancel_ongoing_audits(self):
     audit_filters = {
         'audit_type': objects.audit.AuditType.ONESHOT.value,
         'state': objects.audit.State.ONGOING,
         'hostname': CONF.host
     }
     local_context = context.make_context()
     ongoing_audits = objects.Audit.list(local_context,
                                         filters=audit_filters)
     for audit in ongoing_audits:
         audit.state = objects.audit.State.CANCELLED
         audit.save()
         LOG.info(
             "Audit %(uuid)s has been cancelled because it was in "
             "%(state)s state when Decision Engine had been stopped "
             "on %(hostname)s host.", {
                 'uuid': audit.uuid,
                 'state': objects.audit.State.ONGOING,
                 'hostname': audit.hostname
             })
예제 #17
0
    def setUp(self):
        super(TestSyncer, self).setUp()
        self.ctx = context.make_context()

        # This mock simulates the strategies discovery done in discover()
        self.m_available_strategies = mock.Mock(return_value={
            fake_strategies.FakeDummy1Strategy1.get_name():
                fake_strategies.FakeDummy1Strategy1,
            fake_strategies.FakeDummy1Strategy2.get_name():
                fake_strategies.FakeDummy1Strategy2,
            fake_strategies.FakeDummy2Strategy3.get_name():
                fake_strategies.FakeDummy2Strategy3,
            fake_strategies.FakeDummy2Strategy4.get_name():
                fake_strategies.FakeDummy2Strategy4,
        })

        p_strategies = mock.patch.object(
            default.DefaultStrategyLoader, 'list_available',
            self.m_available_strategies)
        p_strategies.start()

        self.syncer = sync.Syncer()
        self.addCleanup(p_strategies.stop)
예제 #18
0
파일: sync.py 프로젝트: sue-fly/watcher
    def __init__(self):
        self.ctx = context.make_context()
        self.discovered_map = None

        self._available_goals = None
        self._available_goals_map = None

        self._available_strategies = None
        self._available_strategies_map = None

        self._available_scoringengines = None
        self._available_scoringengines_map = None

        # This goal mapping maps stale goal IDs to the synced goal
        self.goal_mapping = dict()
        # This strategy mapping maps stale strategy IDs to the synced goal
        self.strategy_mapping = dict()
        # Maps stale scoring engine IDs to the synced scoring engines
        self.se_mapping = dict()

        self.stale_audit_templates_map = {}
        self.stale_audits_map = {}
        self.stale_action_plans_map = {}
예제 #19
0
 def __init__(self, gconfig=None, service_name=None, **kwargs):
     gconfig = None or {}
     super(ServiceHeartbeat, self).__init__(gconfig, **kwargs)
     ServiceHeartbeat.service_name = service_name
     self.context = context.make_context()
     self.send_beat()
예제 #20
0
 def __init__(self, scope):
     self.ctx = context.make_context()
     self.scope = scope
예제 #21
0
class AuditTemplatePostType(wtypes.Base):
    _ctx = context_utils.make_context()

    name = wtypes.wsattr(wtypes.text, mandatory=True)
    """Name of this audit template"""

    description = wtypes.wsattr(wtypes.text, mandatory=False)
    """Short description of this audit template"""

    deadline = wsme.wsattr(datetime.datetime, mandatory=False)
    """deadline of the audit template"""

    extra = wtypes.wsattr({wtypes.text: types.jsontype}, mandatory=False)
    """The metadata of the audit template"""

    goal = wtypes.wsattr(wtypes.text, mandatory=True)
    """Goal UUID or name of the audit template"""

    strategy = wtypes.wsattr(wtypes.text, mandatory=False)
    """Strategy UUID or name of the audit template"""

    version = wtypes.text
    """Internal version of the audit template"""

    scope = wtypes.wsattr(types.jsontype, mandatory=False, default=[])
    """Audit Scope"""

    def as_audit_template(self):
        return AuditTemplate(
            name=self.name,
            description=self.description,
            deadline=self.deadline,
            extra=self.extra,
            goal_id=self.goal,  # Dirty trick ...
            goal=self.goal,
            strategy_id=self.strategy,  # Dirty trick ...
            strategy_uuid=self.strategy,
            version=self.version,
            scope=self.scope,
        )

    @staticmethod
    def validate(audit_template):
        available_goals = objects.Goal.list(AuditTemplatePostType._ctx)
        available_goal_uuids_map = {g.uuid: g for g in available_goals}
        available_goal_names_map = {g.name: g for g in available_goals}
        if audit_template.goal in available_goal_uuids_map:
            goal = available_goal_uuids_map[audit_template.goal]
        elif audit_template.goal in available_goal_names_map:
            goal = available_goal_names_map[audit_template.goal]
        else:
            raise exception.InvalidGoal(goal=audit_template.goal)

        common_utils.Draft4Validator(
            default.DefaultScope.DEFAULT_SCHEMA).validate(audit_template.scope)

        if audit_template.strategy:
            available_strategies = objects.Strategy.list(
                AuditTemplatePostType._ctx)
            available_strategies_map = {
                s.uuid: s for s in available_strategies}
            if audit_template.strategy not in available_strategies_map:
                raise exception.InvalidStrategy(
                    strategy=audit_template.strategy)

            strategy = available_strategies_map[audit_template.strategy]
            # Check that the strategy we indicate is actually related to the
            # specified goal
            if strategy.goal_id != goal.id:
                choices = ["'%s' (%s)" % (s.uuid, s.name)
                           for s in available_strategies]
                raise exception.InvalidStrategy(
                    message=_(
                        "'%(strategy)s' strategy does relate to the "
                        "'%(goal)s' goal. Possible choices: %(choices)s")
                    % dict(strategy=strategy.name, goal=goal.name,
                           choices=", ".join(choices)))
            audit_template.strategy = strategy.uuid

        # We force the UUID so that we do not need to query the DB with the
        # name afterwards
        audit_template.goal = goal.uuid

        return audit_template
예제 #22
0
 def __init__(self, scope, config):
     self.ctx = context.make_context()
     self.scope = scope
     self.config = config
예제 #23
0
class PurgeCommand(object):
    """Purges the DB by removing soft deleted entries

    The workflow for this purge is the following:

    # Find soft deleted objects which are expired
    # Find orphan objects
    # Find their related objects whether they are expired or not
    # Merge them together
    # If it does not exceed the limit, destroy them all
    """

    ctx = context.make_context(show_deleted=True)

    def __init__(self, age_in_days=None, max_number=None,
                 uuid=None, exclude_orphans=False, dry_run=None):
        self.age_in_days = age_in_days
        self.max_number = max_number
        self.uuid = uuid
        self.exclude_orphans = exclude_orphans
        self.dry_run = dry_run

        self._delete_up_to_max = None
        self._objects_map = WatcherObjectsMap()

    def get_expiry_date(self):
        if not self.age_in_days:
            return None
        today = datetime.datetime.today()
        expiry_date = today - datetime.timedelta(days=self.age_in_days)
        return expiry_date

    @classmethod
    def get_audit_template_uuid(cls, uuid_or_name):
        if uuid_or_name is None:
            return

        query_func = None
        if not utils.is_uuid_like(uuid_or_name):
            query_func = objects.audit_template.AuditTemplate.get_by_name
        else:
            query_func = objects.audit_template.AuditTemplate.get_by_uuid

        try:
            audit_template = query_func(cls.ctx, uuid_or_name)
        except Exception as exc:
            LOG.exception(exc)
            raise exception.AuditTemplateNotFound(audit_template=uuid_or_name)

        if not audit_template.deleted_at:
            raise exception.NotSoftDeletedStateError(
                name=_('Audit Template'), id=uuid_or_name)

        return audit_template.uuid

    def _find_audit_templates(self, filters=None):
        return objects.audit_template.AuditTemplate.list(
            self.ctx, filters=filters)

    def _find_audits(self, filters=None):
        return objects.audit.Audit.list(self.ctx, filters=filters)

    def _find_action_plans(self, filters=None):
        return objects.action_plan.ActionPlan.list(self.ctx, filters=filters)

    def _find_actions(self, filters=None):
        return objects.action.Action.list(self.ctx, filters=filters)

    def _find_orphans(self):
        orphans = WatcherObjectsMap()

        filters = dict(deleted=False)
        audit_templates = objects.audit_template.AuditTemplate.list(
            self.ctx, filters=filters)
        audits = objects.audit.Audit.list(self.ctx, filters=filters)
        action_plans = objects.action_plan.ActionPlan.list(
            self.ctx, filters=filters)
        actions = objects.action.Action.list(self.ctx, filters=filters)

        audit_template_ids = set(at.id for at in audit_templates)
        orphans.audits = [
            audit for audit in audits
            if audit.audit_template_id not in audit_template_ids]

        # Objects with orphan parents are themselves orphans
        audit_ids = [audit.id for audit in (a for a in audits
                                            if a not in orphans.audits)]
        orphans.action_plans = [
            ap for ap in action_plans
            if ap.audit_id not in audit_ids]

        # Objects with orphan parents are themselves orphans
        action_plan_ids = [ap.id for ap in (a for a in action_plans
                                            if a not in orphans.action_plans)]
        orphans.actions = [
            action for action in actions
            if action.action_plan_id not in action_plan_ids]

        LOG.debug("Orphans found:\n%s", orphans)
        LOG.info(_LI("Orphans found:\n%s"), orphans.get_count_table())

        return orphans

    def _find_soft_deleted_objects(self):
        to_be_deleted = WatcherObjectsMap()

        expiry_date = self.get_expiry_date()
        filters = dict(deleted=True)
        if self.uuid:
            filters["uuid"] = self.uuid
        if expiry_date:
            filters.update(dict(deleted_at__lt=expiry_date))

        to_be_deleted.audit_templates.extend(
            self._find_audit_templates(filters))
        to_be_deleted.audits.extend(self._find_audits(filters))
        to_be_deleted.action_plans.extend(self._find_action_plans(filters))
        to_be_deleted.actions.extend(self._find_actions(filters))

        soft_deleted_objs = self._find_related_objects(
            to_be_deleted, base_filters=dict(deleted=True))

        LOG.debug("Soft deleted objects:\n%s", soft_deleted_objs)

        return soft_deleted_objs

    def _find_related_objects(self, objects_map, base_filters=None):
        base_filters = base_filters or {}

        for audit_template in objects_map.audit_templates:
            filters = {}
            filters.update(base_filters)
            filters.update(dict(audit_template_id=audit_template.id))
            related_objs = WatcherObjectsMap()
            related_objs.audits = self._find_audits(filters)
            objects_map += related_objs

        for audit in objects_map.audits:
            filters = {}
            filters.update(base_filters)
            filters.update(dict(audit_id=audit.id))
            related_objs = WatcherObjectsMap()
            related_objs.action_plans = self._find_action_plans(filters)
            objects_map += related_objs

        for action_plan in objects_map.action_plans:
            filters = {}
            filters.update(base_filters)
            filters.update(dict(action_plan_id=action_plan.id))
            related_objs = WatcherObjectsMap()
            related_objs.actions = self._find_actions(filters)
            objects_map += related_objs

        return objects_map

    def confirmation_prompt(self):
        print(self._objects_map.get_count_table())
        raw_val = input(
            _("There are %(count)d objects set for deletion. "
              "Continue? [y/N]") % dict(count=len(self._objects_map)))

        return strutils.bool_from_string(raw_val)

    def delete_up_to_max_prompt(self, objects_map):
        print(objects_map.get_count_table())
        print(_("The number of objects (%(num)s) to delete from the database "
                "exceeds the maximum number of objects (%(max_number)s) "
                "specified.") % dict(max_number=self.max_number,
                                     num=len(objects_map)))
        raw_val = input(
            _("Do you want to delete objects up to the specified maximum "
              "number? [y/N]"))

        self._delete_up_to_max = strutils.bool_from_string(raw_val)

        return self._delete_up_to_max

    def _aggregate_objects(self):
        """Objects aggregated on a 'per audit template' basis"""
        # todo: aggregate orphans as well
        aggregate = []
        for audit_template in self._objects_map.audit_templates:
            related_objs = WatcherObjectsMap()
            related_objs.audit_templates = [audit_template]
            related_objs.audits = [
                audit for audit in self._objects_map.audits
                if audit.audit_template_id == audit_template.id
            ]
            audit_ids = [audit.id for audit in related_objs.audits]
            related_objs.action_plans = [
                action_plan for action_plan in self._objects_map.action_plans
                if action_plan.audit_id in audit_ids
            ]
            action_plan_ids = [
                action_plan.id for action_plan in related_objs.action_plans
            ]
            related_objs.actions = [
                action for action in self._objects_map.actions
                if action.action_plan_id in action_plan_ids
            ]
            aggregate.append(related_objs)

        return aggregate

    def _get_objects_up_to_limit(self):
        aggregated_objects = self._aggregate_objects()
        to_be_deleted_subset = WatcherObjectsMap()

        for aggregate in aggregated_objects:
            if len(aggregate) + len(to_be_deleted_subset) <= self.max_number:
                to_be_deleted_subset += aggregate
            else:
                break

        LOG.debug(to_be_deleted_subset)
        return to_be_deleted_subset

    def find_objects_to_delete(self):
        """Finds all the objects to be purged

        :returns: A mapping with all the Watcher objects to purged
        :rtype: :py:class:`~.WatcherObjectsMap` instance
        """
        to_be_deleted = self._find_soft_deleted_objects()

        if not self.exclude_orphans:
            to_be_deleted += self._find_orphans()

        LOG.debug("Objects to be deleted:\n%s", to_be_deleted)

        return to_be_deleted

    def do_delete(self):
        LOG.info(_LI("Deleting..."))
        # Reversed to avoid errors with foreign keys
        for entry in reversed(list(self._objects_map)):
            entry.destroy()

    def execute(self):
        LOG.info(_LI("Starting purge command"))
        self._objects_map = self.find_objects_to_delete()

        if (self.max_number is not None and
                len(self._objects_map) > self.max_number):
            if self.delete_up_to_max_prompt(self._objects_map):
                self._objects_map = self._get_objects_up_to_limit()
            else:
                return

        _orphans_note = (_(" (orphans excluded)") if self.exclude_orphans
                         else _(" (may include orphans)"))
        if not self.dry_run and self.confirmation_prompt():
            self.do_delete()
            print(_("Purge results summary%s:") % _orphans_note)
            LOG.info(_LI("Purge results summary%s:"), _orphans_note)
        else:
            LOG.debug(self._objects_map)
            print(_("Here below is a table containing the objects "
                    "that can be purged%s:") % _orphans_note)

        LOG.info("\n%s", self._objects_map.get_count_table())
        print(self._objects_map.get_count_table())
        LOG.info(_LI("Purge process completed"))
예제 #24
0
class AuditTemplatePostType(wtypes.Base):
    _ctx = context_utils.make_context()

    name = wtypes.wsattr(wtypes.text, mandatory=True)
    """Name of this audit template"""

    description = wtypes.wsattr(wtypes.text, mandatory=False)
    """Short description of this audit template"""

    goal = wtypes.wsattr(wtypes.text, mandatory=True)
    """Goal UUID or name of the audit template"""

    strategy = wtypes.wsattr(wtypes.text, mandatory=False)
    """Strategy UUID or name of the audit template"""

    scope = wtypes.wsattr(types.jsontype, mandatory=False, default=[])
    """Audit Scope"""

    def as_audit_template(self):
        return AuditTemplate(
            name=self.name,
            description=self.description,
            goal_id=self.goal,  # Dirty trick ...
            goal=self.goal,
            strategy_id=self.strategy,  # Dirty trick ...
            strategy_uuid=self.strategy,
            scope=self.scope,
        )

    @staticmethod
    def _build_schema():
        SCHEMA = {
            "$schema": "http://json-schema.org/draft-04/schema#",
            "type": "array",
            "items": {
                "type": "object",
                "properties": AuditTemplatePostType._get_schemas(),
                "additionalProperties": False
            }
        }
        return SCHEMA

    @staticmethod
    def _get_schemas():
        collectors = default_loading.ClusterDataModelCollectorLoader(
            ).list_available()
        schemas = {k: c.SCHEMA for k, c
                   in collectors.items() if hasattr(c, "SCHEMA")}
        return schemas

    @staticmethod
    def validate(audit_template):
        available_goals = objects.Goal.list(AuditTemplatePostType._ctx)
        available_goal_uuids_map = {g.uuid: g for g in available_goals}
        available_goal_names_map = {g.name: g for g in available_goals}
        if audit_template.goal in available_goal_uuids_map:
            goal = available_goal_uuids_map[audit_template.goal]
        elif audit_template.goal in available_goal_names_map:
            goal = available_goal_names_map[audit_template.goal]
        else:
            raise exception.InvalidGoal(goal=audit_template.goal)

        if audit_template.scope:
            common_utils.Draft4Validator(
                AuditTemplatePostType._build_schema()
                ).validate(audit_template.scope)

            include_host_aggregates = False
            exclude_host_aggregates = False
            for rule in audit_template.scope[0]['compute']:
                if 'host_aggregates' in rule:
                    include_host_aggregates = True
                elif 'exclude' in rule:
                    for resource in rule['exclude']:
                        if 'host_aggregates' in resource:
                            exclude_host_aggregates = True
            if include_host_aggregates and exclude_host_aggregates:
                raise exception.Invalid(
                    message=_(
                        "host_aggregates can't be "
                        "included and excluded together"))

        if audit_template.strategy:
            available_strategies = objects.Strategy.list(
                AuditTemplatePostType._ctx)
            available_strategies_map = {
                s.uuid: s for s in available_strategies}
            if audit_template.strategy not in available_strategies_map:
                raise exception.InvalidStrategy(
                    strategy=audit_template.strategy)

            strategy = available_strategies_map[audit_template.strategy]
            # Check that the strategy we indicate is actually related to the
            # specified goal
            if strategy.goal_id != goal.id:
                choices = ["'%s' (%s)" % (s.uuid, s.name)
                           for s in available_strategies]
                raise exception.InvalidStrategy(
                    message=_(
                        "'%(strategy)s' strategy does relate to the "
                        "'%(goal)s' goal. Possible choices: %(choices)s")
                    % dict(strategy=strategy.name, goal=goal.name,
                           choices=", ".join(choices)))
            audit_template.strategy = strategy.uuid

        # We force the UUID so that we do not need to query the DB with the
        # name afterwards
        audit_template.goal = goal.uuid

        return audit_template