Esempio n. 1
0
    def step_class(self):
        """
        PickleFields are a bad idea in this case, the references are to the full Class name such as
        chroma_core.models.host.ConfigureNTPStep so if you move them, or rename them, the
        PickleField fails. To make matters worse debugging the failures is really hard.

        This code below decodes the Picklefield by hand if it fails (we only have 1 case so it's easy) and then
        returns an instance of the class. In a future patch I would suggest the Picklefield is abandoned
        completely.

        The field will be of the form.

        "�cchroma_core.models.host
         ConfigureCorosyncStep
         q."

        We are interested in the middle line.

        This doesn't solve the whole problem, because anything in args could break it, but as of 3.0 it is OK.

        Truthfully the describe string should be created when the step is created and not created dynamically. Something
        for 3.1 maybe.
        """

        # If PickleField succeeds you get a type, otherwise a string.
        if type(self.step_klass) is type:
            return self.step_klass
        else:
            # Very have to build this now, because at module level all the children may not exist yet.
            if self._step_types == {}:
                for step_type in util.all_subclasses(Step):
                    self._step_types[step_type.__name__] = step_type

            return self._step_types[b64decode(self.step_klass).split()[1]]
Esempio n. 2
0
def terminate_block_device_drivers():
    console_log.info("Terminating drivers for block device types")
    for cls in util.all_subclasses(BlockDevice):
        error = cls.terminate_driver()

        if error:
            return agent_error(error)

    return agent_result_ok
Esempio n. 3
0
def initialise_block_device_drivers():
    console_log.info("Initialising drivers for block device types")
    for cls in util.all_subclasses(BlockDevice):
        error = cls.initialise_driver(config.profile_managed)

        if error:
            return agent_error(error)

    return agent_result_ok
Esempio n. 4
0
def terminate_block_device_drivers():
    """
    When the agent is stopped we want to allow block devices to do any termination that they might need, this function
    may also be called by the manager.
    """
    console_log.info("Terminating drivers for block device types")
    for cls in util.all_subclasses(BlockDevice):
        error = cls.terminate_driver()

        if error:
            return agent_error(error)

    return agent_result_ok
Esempio n. 5
0
def initialise_block_device_drivers():
    """
    When the agent is run we want to allow block devices to do any initialization that they might need, this function
    may also be called by the manager.
    """
    console_log.info("Initialising drivers for block device types")
    for cls in util.all_subclasses(BlockDevice):
        error = cls.initialise_driver(config.profile_managed)

        if error:
            return agent_error(error)

    return agent_result_ok
    def create(cls, address, remote_access_func):
        """ check cache for controller at this address, update if necessary and return controller object """
        if address not in cls.controller_instances:
            # Note: this assumes OS will not be changed on a remote host during parent process lifetime
            try:
                # return available class with highest priority (positive integer closest to 0)
                # Note: if identical class_priority values exist in resultant list, either class could be returned
                required_class = sorted(
                    [_cls for _cls in util.all_subclasses(cls) if _cls._applicable(address, remote_access_func)],
                    key=attrgetter("class_priority"),
                )[0]
            except IndexError:
                raise RuntimeError("Current platform version not applicable")

            cls.controller_instances[address] = required_class(address, remote_access_func)

        return cls.controller_instances[address]
    def managed_target_of_type(cls, target_type):
        """
        :param target_type:  is a string describing the target required, generally ost, mdt or mgt
        :return: Returns a klass of the type required by looking through the subclasses
        """
        try:
            # Hack I need to work out with Joe.
            if target_type == "mgt":
                target_type = "mgs"

            target_type = target_type.lower()

            subtype = next(klass
                           for klass in util.all_subclasses(ManagedTarget)
                           if target_type == klass().target_type())

            return subtype
        except StopIteration:
            raise NotImplementedError("ManagedTarget %s unknown" % target_type)
Esempio n. 8
0
class AlertResource(LongPollingAPI, SeverityResource):
    """
    Notification of a bad health state.  Alerts refer to particular objects (such as
    servers or targets), and can either be active (indicating this is a current
    problem) or inactive (indicating this is a historical record of a problem).
    """

    message = fields.CharField(readonly=True,
                               help_text=("Human readable description "
                                          "of the alert, about one sentence"))

    alert_item = fields.CharField(help_text="URI of affected item")

    affected = fields.ListField(
        null=True,
        help_text=("List of objects which are affected by the alert "
                   "(e.g. a target alert also affects the file system to "
                   "which the target belongs)"))

    alert_item_str = fields.CharField(
        readonly=True,
        help_text=("A human readable noun describing the object "
                   "that is the subject of the alert"))

    record_type = fields.CharField(
        attribute='record_type',
        help_text="The type of the alert described as a Python classes",
        enumerations=[
            class_.__name__ for class_ in util.all_subclasses(AlertStateBase)
        ])

    severity = fields.CharField(attribute='severity',
                                help_text=("String indicating the "
                                           "severity of the alert, "
                                           "one of %s") %
                                STR_TO_SEVERITY.keys(),
                                enumerations=STR_TO_SEVERITY.keys())

    # Long polling should return when any of the tables below changes or has changed.
    long_polling_tables = [AlertState, LNetOfflineAlert]

    def dispatch(self, request_type, request, **kwargs):
        return self.handle_long_polling_dispatch(request_type, request,
                                                 **kwargs)

    def prepend_urls(self):
        return [
            url(r'^(?P<resource_name>%s)/dismiss_all%s$' %
                (self._meta.resource_name, trailing_slash()),
                self.wrap_view('dismiss_all'),
                name='api_alert_dismiss_all'),
        ]

    def dismiss_all(self, request, **kwargs):
        if (request.method != 'PUT') or (not request.user.is_authenticated()):
            return http.HttpUnauthorized()

        AlertState.objects.filter(dismissed=False).exclude(
            active=True, severity__in=[40, 30]).update(dismissed=True)

        return http.HttpNoContent()

    def dehydrate_alert_item(self, bundle):
        return api.get_resource_uri(bundle.obj.alert_item)

    def dehydrate_alert_item_str(self, bundle):
        return str(bundle.obj.alert_item)

    def dehydrate_message(self, bundle):
        return bundle.obj.message()

    def dehydrate_affected(self, bundle):
        from chroma_api.urls import api

        alert = bundle.obj

        affected_objects = []

        def affect_target(target):
            affected_objects.append(target)
            if target.filesystem_member:
                affected_objects.append(target.filesystem)
            elif target.target_type == "mgs":
                for fs in target.managedfilesystem_set.all():
                    affected_objects.append(fs)

        affected_objects.extend(alert.affected_objects)

        alert.affected_targets(affect_target)

        affected_objects.append(alert.alert_item)

        return [api.get_resource_uri(ao) for ao in set(affected_objects)]

    def build_filters(self, filters=None):

        filters = super(AlertResource, self).build_filters(filters)

        # Map False to None and 'active_bool' to 'active'
        if 'active_bool__exact' in filters:
            filters['active__exact'] = None if not filters[
                'active_bool__exact'] else True
            del filters['active_bool__exact']

        return filters

    class Meta:
        queryset = AlertState.objects.order_by('-begin')
        resource_name = 'alert'

        filtering = {
            'begin': SeverityResource.ALL_FILTER_DATE,
            'end': SeverityResource.ALL_FILTER_DATE,
            'message': SeverityResource.ALL_FILTER_STR,
            'active': SeverityResource.ALL_FILTER_BOOL,
            'dismissed': SeverityResource.ALL_FILTER_BOOL,
            'id': SeverityResource.ALL_FILTER_INT,
            'severity': SeverityResource.ALL_FILTER_ENUMERATION,
            'created_at': SeverityResource.ALL_FILTER_DATE,
            'alert_type': SeverityResource.ALL_FILTER_ENUMERATION,
            'alert_item_id': SeverityResource.ALL_FILTER_INT,
            'lustre_pid': SeverityResource.ALL_FILTER_INT,
            'record_type': SeverityResource.ALL_FILTER_ENUMERATION
        }

        ordering = ['begin', 'end', 'active']
        authorization = DjangoAuthorization()
        authentication = AnonymousAuthentication()
        list_allowed_methods = ['get']
        detail_allowed_methods = ['get', 'patch', 'put']
        always_return_data = True
class AlertResource(SeverityResource):
    """
    Notification of a bad health state.  Alerts refer to particular objects (such as
    servers or targets), and can either be active (indicating this is a current
    problem) or inactive (indicating this is a historical record of a problem).
    """

    message = fields.CharField(readonly=True,
                               help_text=("Human readable description "
                                          "of the alert, about one sentence"))

    alert_item = fields.CharField(help_text="URI of affected item")

    affected = fields.ListField(
        null=True,
        help_text=("List of objects which are affected by the alert "
                   "(e.g. a target alert also affects the file system to "
                   "which the target belongs)"),
    )

    alert_item_str = fields.CharField(
        readonly=True,
        help_text=("A human readable noun describing the object "
                   "that is the subject of the alert"))

    record_type = fields.CharField(
        attribute="record_type",
        help_text="The type of the alert described as a Python classes",
        enumerations=[
            class_.__name__ for class_ in util.all_subclasses(AlertStateBase)
        ],
    )

    severity = fields.CharField(
        attribute="severity",
        help_text=("String indicating the "
                   "severity of the alert, "
                   "one of %s") % STR_TO_SEVERITY.keys(),
        enumerations=STR_TO_SEVERITY.keys(),
    )

    def prepend_urls(self):
        return [
            url(
                r"^(?P<resource_name>%s)/dismiss_all%s$" %
                (self._meta.resource_name, trailing_slash()),
                self.wrap_view("dismiss_all"),
                name="api_alert_dismiss_all",
            )
        ]

    def dismiss_all(self, request, **kwargs):
        if (request.method != "PUT") or (not request.user.is_authenticated()):
            return http.HttpUnauthorized()

        AlertState.objects.filter(dismissed=False).exclude(
            active=True, severity__in=[40, 30]).update(dismissed=True)

        return http.HttpNoContent()

    def dehydrate_alert_item(self, bundle):
        from chroma_api.urls import api

        return api.get_resource_uri(bundle.obj.alert_item)

    def dehydrate_alert_item_str(self, bundle):
        return str(bundle.obj.alert_item)

    def dehydrate_message(self, bundle):
        return bundle.obj.message()

    def dehydrate_affected(self, bundle):
        from chroma_api.urls import api

        alert = bundle.obj

        affected_objects = []

        def affect_target(target):
            affected_objects.append(target)
            if target.filesystem_member:
                affected_objects.append(target.filesystem)
            elif target.target_type == "mgs":
                for fs in target.managedfilesystem_set.all():
                    affected_objects.append(fs)

        affected_objects.extend(alert.affected_objects)

        alert.affected_targets(affect_target)

        affected_objects.append(alert.alert_item)

        return [api.get_resource_uri(ao) for ao in set(affected_objects)]

    def build_filters(self, filters=None):

        filters = super(AlertResource, self).build_filters(filters)

        # Map False to None and 'active_bool' to 'active'
        if "active_bool__exact" in filters:
            filters["active__exact"] = None if not filters[
                "active_bool__exact"] else True
            del filters["active_bool__exact"]

        return filters

    class Meta:
        queryset = AlertState.objects.order_by("-begin")
        resource_name = "alert"

        filtering = {
            "begin": SeverityResource.ALL_FILTER_DATE,
            "end": SeverityResource.ALL_FILTER_DATE,
            "message": SeverityResource.ALL_FILTER_STR,
            "active": SeverityResource.ALL_FILTER_BOOL,
            "dismissed": SeverityResource.ALL_FILTER_BOOL,
            "id": SeverityResource.ALL_FILTER_INT,
            "severity": SeverityResource.ALL_FILTER_ENUMERATION,
            "created_at": SeverityResource.ALL_FILTER_DATE,
            "alert_type": SeverityResource.ALL_FILTER_ENUMERATION,
            "alert_item_id": SeverityResource.ALL_FILTER_INT,
            "lustre_pid": SeverityResource.ALL_FILTER_INT,
            "record_type": SeverityResource.ALL_FILTER_ENUMERATION,
        }

        ordering = ["begin", "end", "active"]
        serializer = DateSerializer()
        authorization = DjangoAuthorization()
        authentication = AnonymousAuthentication()
        list_allowed_methods = ["get"]
        detail_allowed_methods = ["get", "patch", "put"]
        always_return_data = True
Esempio n. 10
0
 def from_dict(cls, dict):
     cls_name = dict.pop('__dict_struct_type__')
     cls_ = next(class_ for class_ in util.all_subclasses(DictStruct)
                 if class_.__module__ + "." + class_.__name__ == cls_name)
     return cls_(**dict)