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]]
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
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
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
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)
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
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)