class UnconfigureLNetJob(NullStateChangeJob): target_object = models.ForeignKey(LNetConfiguration) state_transition = StateChangeJob.StateTransition(LNetConfiguration, 'lnet_unloaded', 'unconfigured') class Meta: app_label = 'chroma_core' ordering = ['id'] def description(self): return self.long_description(self.target_object) @classmethod def long_description(cls, stateful_object): if stateful_object.is_managed: return help_text[ 'Change lnet state of %s to unconfigured'] % stateful_object.host else: return help_text[ 'Stop monitoring lnet on %s'] % stateful_object.host def get_steps(self): return self.target_object.filter_steps([(UnconfigureLNetStep, { 'host': self.target_object.host })])
class RemoveStratagemJob(StateChangeJob): state_transition = StateChangeJob.StateTransition(StratagemConfiguration, "unconfigured", "removed") stateful_object = "stratagem_configuration" stratagem_configuration = models.ForeignKey(StratagemConfiguration, on_delete=CASCADE) display_group = Job.JOB_GROUPS.COMMON display_order = 10 requires_confirmation = False state_verb = "Remove" class Meta: app_label = "chroma_core" ordering = ["id"] @classmethod def long_description(cls, stateful_object): return "Remove Stratagem for the given filesystem" def description(self): return "Remove Stratagem for the given filesystem" def get_steps(self): return [(DeleteStratagemStep, {"stratagem_configuration": self.stratagem_configuration})] def get_deps(self): return DependOn(self.stratagem_configuration, "unconfigured")
class ConfigureStratagemJob(StateChangeJob): state_transition = StateChangeJob.StateTransition(StratagemConfiguration, "unconfigured", "configured") stateful_object = "stratagem_configuration" stratagem_configuration = models.ForeignKey(StratagemConfiguration, on_delete=CASCADE) display_group = Job.JOB_GROUPS.COMMON display_order = 10 requires_confirmation = False state_verb = "Configure Stratagem" class Meta: app_label = "chroma_core" ordering = ["id"] @classmethod def long_description(cls, stateful_object): return help_text["configure_stratagem_long"] def description(self): return help_text["configure_stratagem_long"] def get_steps(self): steps = [] if os.path.exists(timer_file(self.stratagem_configuration.id)): steps.append((UnconfigureStratagemTimerStep, {"config": self.stratagem_configuration})) steps.append((ConfigureStratagemTimerStep, {"config": self.stratagem_configuration})) return steps
class UnloadLNetJob(LNetStateChangeJob): state_transition = StateChangeJob.StateTransition(LNetConfiguration, "lnet_down", "lnet_unloaded") stateful_object = "lnet_configuration" lnet_configuration = models.ForeignKey(LNetConfiguration) state_verb = "Unload LNet" display_group = Job.JOB_GROUPS.RARE display_order = 110 class Meta: app_label = "chroma_core" ordering = ["id"] @classmethod def long_description(cls, stateful_object): if stateful_object.is_managed: return help_text["unload_lnet"] else: return help_text[ "Stop monitoring lnet on %s"] % stateful_object.host def description(self): return self.long_description(self.lnet_configuration) def get_steps(self): return self.lnet_configuration.filter_steps([ (UnloadLNetStep, { "host": self.lnet_configuration.host }), (GetLNetStateStep, { "host": self.lnet_configuration.host }), ])
class RevokeGrantedTicketJob(StateChangeJob): state_transition = StateChangeJob.StateTransition(Ticket, "granted", "revoked") stateful_object = "ticket" state_verb = "Revoke" ticket = models.ForeignKey("Ticket", on_delete=CASCADE) def get_steps(self): steps = [] ticket = self.ticket.downcast() if ticket.resource_controlled: steps.append((StopResourceStep, { "fqdn": ticket.get_host().fqdn, "ha_label": ticket.ha_label })) else: raise RuntimeError("Ticket `%s' is not resource controlled" % ticket.name) return steps @classmethod def long_description(cls, stateful_object): return help_text["revoke_ticket"] def description(self): return "Revoke ticket %s" % self.ticket.name
class StopUnavailableFilesystemJob(FilesystemJob, StateChangeJob): state_verb = "Stop" state_transition = StateChangeJob.StateTransition(ManagedFilesystem, "unavailable", "stopped") filesystem = models.ForeignKey("ManagedFilesystem") display_group = Job.JOB_GROUPS.INFREQUENT display_order = 30 @classmethod def long_description(cls, stateful_object): return help_text["stop_file_system"] def description(self): return "Stop file system %s" % self.filesystem.name def get_deps(self): deps = [] targets = ObjectCache.get_targets_by_filesystem(self.filesystem_id) targets = [ t for t in targets if not issubclass(t.downcast_class, ManagedMgs) ] for t in targets: deps.append( DependOn(t, "unmounted", acceptable_states=t.not_state("mounted"), fix_state="unavailable")) return DependAll(deps)
class AutoConfigureCorosyncJob(StateChangeJob): state_transition = StateChangeJob.StateTransition(None, None, None) stateful_object = 'corosync_configuration' corosync_configuration = StubCorosyncConfiguration() state_verb = 'Configure Corosync' display_group = Job.JOB_GROUPS.COMMON display_order = 30 class Meta: abstract = True @classmethod def long_description(cls, stateful_object): return help_text["configure_corosync"] def description(self): return help_text[ 'configure_corosync_on'] % self.corosync_configuration.host def get_deps(self): ''' Before Corosync operations are possible some dependencies are need, basically the host must have had its packages installed. Maybe we need a packages object, but this routine at least keeps the detail in one place. Or maybe we need an unacceptable_states lists. :return: ''' if self.corosync_configuration.host.state in [ 'unconfigured', 'undeployed' ]: return DependOn(self.corosync_configuration.host, 'packages_installed') else: return DependAll()
class UnconfigureLNetJob(NullStateChangeJob): target_object = models.ForeignKey(LNetConfiguration, on_delete=CASCADE) state_transition = StateChangeJob.StateTransition(LNetConfiguration, "lnet_unloaded", "unconfigured") class Meta: app_label = "chroma_core" ordering = ["id"] def description(self): return self.long_description(self.target_object) @classmethod def long_description(cls, stateful_object): if stateful_object.is_managed: return help_text[ "Change lnet state of %s to unconfigured"] % stateful_object.host else: return help_text[ "Stop monitoring lnet on %s"] % stateful_object.host def get_steps(self): return self.target_object.filter_steps([(UnconfigureLNetStep, { "fqdn": self.target_object.host.fqdn })])
class EnableLNetJob(NullStateChangeJob): target_object = models.ForeignKey(LNetConfiguration) state_transition = StateChangeJob.StateTransition(LNetConfiguration, 'unconfigured', 'lnet_unloaded') class Meta: app_label = 'chroma_core' ordering = ['id'] def description(self): return self.long_description(self.target_object) @classmethod def long_description(cls, stateful_object): if stateful_object.is_managed: return help_text['Enable LNet on %s'] % stateful_object.host else: return help_text['Start monitoring LNet on %s'] % stateful_object.host def get_deps(self): ''' Before LNet operations are possible some dependencies are need, basically the host must have had its packages installed. Maybe we need a packages object, but this routine at least keeps the detail in one place. Or maybe we need an unacceptable_states lists. :return: ''' if self.target_object.host.state in ['unconfigured', 'undeployed']: return DependOn(self.target_object.host, 'packages_installed') else: return DependAll()
class UnloadLNetJob(LNetStateChangeJob): state_transition = StateChangeJob.StateTransition(LNetConfiguration, 'lnet_down', 'lnet_unloaded') stateful_object = 'lnet_configuration' lnet_configuration = models.ForeignKey(LNetConfiguration) state_verb = 'Unload LNet' display_group = Job.JOB_GROUPS.RARE display_order = 110 class Meta: app_label = 'chroma_core' ordering = ['id'] @classmethod def long_description(cls, stateful_object): if stateful_object.is_managed: return help_text["unload_lnet"] else: return help_text['Stop monitoring lnet on %s'] % stateful_object.host def description(self): return self.long_description(self.lnet_configuration) def get_steps(self): return self.lnet_configuration.filter_steps([(UnloadLNetStep, {'host': self.lnet_configuration.host}), (GetLNetStateStep, {'host': self.lnet_configuration.host})])
class UnconfigureNTPJob(StateChangeJob): state_transition = StateChangeJob.StateTransition(NTPConfiguration, 'configured', 'unconfigured') stateful_object = 'ntp_configuration' ntp_configuration = models.ForeignKey(NTPConfiguration) state_verb = 'Unconfigure NTP' display_group = Job.JOB_GROUPS.COMMON display_order = 30 class Meta: app_label = 'chroma_core' ordering = ['id'] @classmethod def long_description(cls, stateful_object): return help_text["unconfigure_ntp"] def description(self): return "Unconfigure Ntp on %s" % self.ntp_configuration.host def get_steps(self): return [(UnconfigureNTPStep, { 'ntp_configuration': self.ntp_configuration })]
class ForgetFilesystemJob(StateChangeJob): class Meta: app_label = "chroma_core" ordering = ["id"] display_group = Job.JOB_GROUPS.RARE display_order = 40 state_transition = StateChangeJob.StateTransition( ManagedFilesystem, ["unavailable", "stopped", "available"], "forgotten") stateful_object = "filesystem" state_verb = "Forget" filesystem = models.ForeignKey(ManagedFilesystem) requires_confirmation = True @classmethod def long_description(cls, stateful_object): return help_text["remove_file_system"] def description(self): return "Forget unmanaged file system %s" % self.filesystem.name def on_success(self): super(ForgetFilesystemJob, self).on_success() from chroma_core.models.target import ManagedMdt, ManagedOst assert ManagedMdt.objects.filter( filesystem=self.filesystem).count() == 0 assert ManagedOst.objects.filter( filesystem=self.filesystem).count() == 0 self.filesystem.mark_deleted()
class MakeAvailableFilesystemUnavailable(StateChangeJob): """This Job has no steps, so does nothing other then change the state. Although the get_available_job code will find this Job as an option when the FS is in state 'available', because state_verb is None JobScheduler:_add_verbs will strip it out. TODO: RECOMMEND A REVIEW BEFORE RUNNING THIS JOB TO DETERMINE WHAT THE UNAVAILABLE STATE MEANS, OTHER THAN JUST THE STARTING STATE. """ state_verb = None state_transition = StateChangeJob.StateTransition(ManagedFilesystem, "available", "unavailable") filesystem = models.ForeignKey("ManagedFilesystem", on_delete=CASCADE) stateful_object = "filesystem" class Meta: app_label = "chroma_core" ordering = ["id"] def get_steps(self): return [] @classmethod def long_description(cls, stateful_object): return help_text["make_file_system_unavailable"] def description(self): return "Make file system %s unavailable" % self.filesystem.name
class UnconfigureNTPJob(StateChangeJob): state_transition = StateChangeJob.StateTransition(NTPConfiguration, "configured", "unconfigured") stateful_object = "ntp_configuration" ntp_configuration = models.ForeignKey(NTPConfiguration, on_delete=CASCADE) state_verb = "Unconfigure NTP" display_group = Job.JOB_GROUPS.COMMON display_order = 30 class Meta: app_label = "chroma_core" ordering = ["id"] @classmethod def long_description(cls, stateful_object): return help_text["unconfigure_ntp"] def description(self): return "Unconfigure Ntp on {}".format(self.ntp_configuration.host) def get_steps(self): fqdn = self.ntp_configuration.host.fqdn return [(UnconfigureNTPStep, { "fqdn": fqdn }), (RestartNtpStep, { "fqdn": fqdn })]
class UnconfigureCorosyncJob(StateChangeJob): state_transition = StateChangeJob.StateTransition(None, None, None) stateful_object = 'corosync_configuration' corosync_configuration = StubCorosyncConfiguration() state_verb = 'Unconfigure Corosync' display_group = Job.JOB_GROUPS.COMMON display_order = 30 class Meta: abstract = True @classmethod def long_description(cls, stateful_object): return help_text["unconfigure_corosync"] def description(self): return "Unconfigure Corosync on %s" % self.corosync_configuration.host @classmethod def can_run(cls, instance): """We don't want people to unconfigure corosync on a node that has a ManagedTargetMount so make the command available only when that is not the case. :param instance: CorosyncConfiguration instance being queried :return: True if no ManagedTargetMounts exist on the host in question. """ from chroma_core.models import ManagedTargetMount return len(ManagedTargetMount.objects.filter(host=instance.host)) == 0
class ForgetStratagemConfigurationJob(StateChangeJob): class Meta: app_label = "chroma_core" ordering = ["id"] @classmethod def long_description(cls, self): return "Forget the stratagem configuration for filesystem" def description(self): return self.long_description(self) def get_requires_confirmation(self): return True def on_success(self): self.stratagem_configuration.mark_deleted() job_log.debug("forgetting stratagem configuration") super(ForgetStratagemConfigurationJob, self).on_success() state_transition = StateChangeJob.StateTransition(StratagemConfiguration, "unconfigured", "removed") stateful_object = "stratagem_configuration" stratagem_configuration = models.ForeignKey(StratagemConfiguration, on_delete=CASCADE) state_verb = "Forget"
class StopPacemakerJob(StateChangeJob): state_transition = StateChangeJob.StateTransition(PacemakerConfiguration, "started", "stopped") stateful_object = "pacemaker_configuration" pacemaker_configuration = models.ForeignKey(PacemakerConfiguration, on_delete=CASCADE) state_verb = "Stop Pacemaker" display_group = Job.JOB_GROUPS.RARE display_order = 100 class Meta: app_label = "chroma_core" ordering = ["id"] @classmethod def long_description(cls, stateful_object): return help_text["stop_pacemaker"] def description(self): return "Stop Pacemaker on %s" % self.pacemaker_configuration.host def get_steps(self): return [(StopPacemakerStep, { "host": self.pacemaker_configuration.host })]
class StopPacemakerJob(StateChangeJob): state_transition = StateChangeJob.StateTransition(PacemakerConfiguration, 'started', 'stopped') stateful_object = 'pacemaker_configuration' pacemaker_configuration = models.ForeignKey(PacemakerConfiguration) state_verb = 'Stop Pacemaker' display_group = Job.JOB_GROUPS.RARE display_order = 100 class Meta: app_label = 'chroma_core' ordering = ['id'] @classmethod def long_description(cls, stateful_object): return help_text["stop_pacemaker"] def description(self): return "Stop Pacemaker on %s" % self.pacemaker_configuration.host def get_steps(self): return [(StopPacemakerStep, { 'host': self.pacemaker_configuration.host })]
class ConfigurePacemakerJob(StateChangeJob): state_transition = StateChangeJob.StateTransition(PacemakerConfiguration, 'unconfigured', 'stopped') stateful_object = 'pacemaker_configuration' pacemaker_configuration = models.ForeignKey(PacemakerConfiguration) state_verb = 'Configure Pacemaker' display_group = Job.JOB_GROUPS.COMMON display_order = 30 class Meta: app_label = 'chroma_core' ordering = ['id'] @classmethod def long_description(cls, stateful_object): return help_text["configure_pacemaker"] def description(self): return help_text[ "configure_pacemaker_on"] % self.pacemaker_configuration.host def get_steps(self): return [(StartPacemakerStep, { 'host': self.pacemaker_configuration.host }), (ConfigurePacemakerStep, { 'host': self.pacemaker_configuration.host }), (StopPacemakerStep, { 'host': self.pacemaker_configuration.host })] def get_deps(self): ''' Before Pacemaker operations are possible the host must have had its packages installed. Maybe we need a packages object, but this routine at least keeps the detail in one place. Also corosync needs to be up and running. This is because configuring pacemaker requires starting pacemaker. Or maybe we need an unacceptable_states lists. :return: ''' if self.pacemaker_configuration.host.state in [ 'unconfigured', 'undeployed' ]: deps = [ DependOn(self.pacemaker_configuration.host, 'packages_installed') ] else: deps = [] deps.append( DependOn(self.pacemaker_configuration.host.corosync_configuration, 'started')) return DependAll(deps)
class ConfigureNTPJob(StateChangeJob): state_transition = StateChangeJob.StateTransition(NTPConfiguration, "unconfigured", "configured") stateful_object = "ntp_configuration" ntp_configuration = models.ForeignKey(NTPConfiguration, on_delete=CASCADE) state_verb = "Start Ntp" display_group = Job.JOB_GROUPS.COMMON display_order = 30 class Meta: app_label = "chroma_core" ordering = ["id"] @classmethod def long_description(cls, stateful_object): return help_text["configure_ntp"] def description(self): return "Configure NTP on {}".format(self.ntp_configuration.host) def get_steps(self): fqdn = self.ntp_configuration.host.fqdn return [ (ConfigureNTPStep, { "fqdn": fqdn }), (StopChronyStep, { "fqdn": fqdn }), (DisableChronyStep, { "fqdn": fqdn }), (EnableNtpStep, { "fqdn": fqdn }), (RestartNtpStep, { "fqdn": fqdn }), ] def get_deps(self): """ Before ntp operations are possible some dependencies are need, basically the host must have had its packages installed. Maybe we need a packages object, but this routine at least keeps the detail in one place. Or maybe we need an unacceptable_states lists. :return: """ if self.ntp_configuration.host.state in ["unconfigured", "undeployed"]: return DependOn(self.ntp_configuration.host, "packages_installed") else: return DependAll()
class StartCorosyncJob(StateChangeJob): state_transition = StateChangeJob.StateTransition(None, None, None) stateful_object = 'corosync_configuration' corosync_configuration = StubCorosyncConfiguration() state_verb = 'Start Corosync' display_group = Job.JOB_GROUPS.COMMON display_order = 30 class Meta: abstract = True @classmethod def long_description(cls, stateful_object): return help_text["start_corosync"] def description(self): return "Start Corosync on %s" % self.corosync_configuration.host
class ConfigureRsyslogJob(StateChangeJob): state_transition = StateChangeJob.StateTransition(RSyslogConfiguration, 'unconfigured', 'configured') stateful_object = 'rsyslog_configuration' rsyslog_configuration = models.ForeignKey(RSyslogConfiguration) state_verb = 'Start RSyslog' display_group = Job.JOB_GROUPS.COMMON display_order = 30 class Meta: app_label = 'chroma_core' ordering = ['id'] @classmethod def long_description(cls, stateful_object): return help_text["configure_rsyslog"] def description(self): return "Configure RSyslog on %s" % self.rsyslog_configuration.host def get_steps(self): return [(ConfigureRsyslogStep, { 'rsyslog_configuration': self.rsyslog_configuration })] def get_deps(self): ''' Before rsyslong operations are possible some dependencies are need, basically the host must have had its packages installed. Maybe we need a packages object, but this routine at least keeps the detail in one place. Or maybe we need an unacceptable_states lists. :return: ''' if self.rsyslog_configuration.host.state in [ 'unconfigured', 'undeployed' ]: return DependOn(self.rsyslog_configuration.host, 'packages_installed') else: return DependAll()
class ForgetFilesystemJob(StateChangeJob): class Meta: app_label = "chroma_core" ordering = ["id"] display_group = Job.JOB_GROUPS.RARE display_order = 40 state_transition = StateChangeJob.StateTransition( ManagedFilesystem, ["unavailable", "stopped", "available"], "forgotten") stateful_object = "filesystem" state_verb = "Forget" filesystem = models.ForeignKey(ManagedFilesystem, on_delete=CASCADE) requires_confirmation = True @classmethod def long_description(cls, stateful_object): return "Forget this filesystem on the manager. The actual filesystem will not be altered." def description(self): return "Forget filesystem {}".format(self.filesystem.name) def on_success(self): super(ForgetFilesystemJob, self).on_success() assert ManagedMdt.objects.filter( filesystem=self.filesystem).count() == 0 assert ManagedOst.objects.filter( filesystem=self.filesystem).count() == 0 self.filesystem.mark_deleted() def get_deps(self): deps = [] ticket = self.filesystem.get_ticket() if ticket: deps.append(DependOn(ticket, "forgotten", fix_state=ticket.state)) for t in self.filesystem.get_filesystem_targets(): deps.append(DependOn(t, "forgotten")) return DependAll(deps)
class StopUnavailableFilesystemJob(StateChangeJob): state_verb = "Stop" state_transition = StateChangeJob.StateTransition(ManagedFilesystem, "unavailable", "stopped") filesystem = models.ForeignKey("ManagedFilesystem", on_delete=CASCADE) display_group = Job.JOB_GROUPS.INFREQUENT display_order = 30 stateful_object = "filesystem" class Meta: app_label = "chroma_core" ordering = ["id"] def get_steps(self): return [] @classmethod def long_description(cls, stateful_object): return help_text["stop_file_system"] def description(self): return "Stop file system %s" % self.filesystem.name def get_deps(self): ticket = self.filesystem.get_ticket() if ticket: return DependAll( [DependOn(ticket, "revoked", fix_state="unavailable")]) deps = [] targets = ObjectCache.get_targets_by_filesystem(self.filesystem_id) targets = [ t for t in targets if not issubclass(t.downcast_class, ManagedMgs) ] for t in targets: deps.append( DependOn(t, "unmounted", acceptable_states=t.not_state("mounted"), fix_state="unavailable")) return DependAll(deps)
class ForgetFilesystemJob(StateChangeJob): class Meta: app_label = "chroma_core" ordering = ["id"] display_group = Job.JOB_GROUPS.RARE display_order = 40 state_transition = StateChangeJob.StateTransition( ManagedFilesystem, ["unavailable", "stopped", "available"], "forgotten") stateful_object = "filesystem" state_verb = "Forget" filesystem = models.ForeignKey(ManagedFilesystem, on_delete=CASCADE) requires_confirmation = True @classmethod def long_description(cls, stateful_object): return help_text["remove_file_system"] def description(self): modifier = "unmanaged" if self.filesystem.immutable_state else "managed" return "Forget %s file system %s" % (modifier, self.filesystem.name) def on_success(self): super(ForgetFilesystemJob, self).on_success() assert ManagedMdt.objects.filter( filesystem=self.filesystem).count() == 0 assert ManagedOst.objects.filter( filesystem=self.filesystem).count() == 0 self.filesystem.mark_deleted() def get_deps(self): deps = [] ticket = self.filesystem.get_ticket() if ticket: deps.append(DependOn(ticket, "forgotten", fix_state=ticket.state)) return DependAll(deps)
class StartUnavailableFilesystemJob(StateChangeJob): state_verb = "Start" state_transition = StateChangeJob.StateTransition(ManagedFilesystem, "unavailable", "available") filesystem = models.ForeignKey("ManagedFilesystem", on_delete=CASCADE) display_group = Job.JOB_GROUPS.COMMON display_order = 20 stateful_object = "filesystem" class Meta: app_label = "chroma_core" ordering = ["id"] def get_steps(self): return [] @classmethod def long_description(cls, stateful_object): return help_text["start_file_system"] def description(self): return "Start filesystem %s" % self.filesystem.name def get_deps(self): ticket = self.filesystem.get_ticket() if ticket: return DependAll( [DependOn(ticket, "granted", fix_state="unavailable")]) deps = [] for t in ObjectCache.get_targets_by_filesystem(self.filesystem_id): # Report filesystem available if MDTs other than 0 are unmounted (_, label, index) = target_label_split(t.get_label()) if label == "MDT" and index != 0: continue deps.append(DependOn(t, "mounted", fix_state="unavailable")) return DependAll(deps)
class LoadLNetJob(LNetStateChangeJob): state_transition = StateChangeJob.StateTransition(LNetConfiguration, "lnet_unloaded", "lnet_down") stateful_object = "lnet_configuration" lnet_configuration = models.ForeignKey(LNetConfiguration, on_delete=CASCADE) state_verb = "Load LNet" display_group = Job.JOB_GROUPS.COMMON display_order = 30 class Meta: app_label = "chroma_core" ordering = ["id"] @classmethod def long_description(cls, stateful_object): if stateful_object.is_managed: return help_text["load_lnet"] else: return help_text[ "Start monitoring LNet on %s"] % stateful_object.host def description(self): return self.long_description(self.lnet_configuration) def get_steps(self): fqdn = self.lnet_configuration.host.fqdn host_id = self.lnet_configuration.host.id return self.lnet_configuration.filter_steps([ (LoadLNetStep, { "fqdn": fqdn }), (GetLNetStateStep, { "host_id": host_id, "fqdn": fqdn }), ])
class MakeAvailableFilesystemUnavailable(FilesystemJob, StateChangeJob): """This Job has no steps, so does nothing other then change the state. Although the get_available_job code will find this Job as an option when the FS is in state 'available', because state_verb is None JobScheduler:_add_verbs will strip it out. TODO: RECOMMEND A REVIEW BEFORE RUNNING THIS JOB TO DETERMINE WHAT THE UNAVAILABLE STATE MEANS, OTHER THAN JUST THE STARTING STATE. """ state_verb = None state_transition = StateChangeJob.StateTransition(ManagedFilesystem, 'available', 'unavailable') filesystem = models.ForeignKey('ManagedFilesystem') @classmethod def long_description(cls, stateful_object): return help_text['make_file_system_unavailable'] def description(self): return "Make file system %s unavailable" % self.filesystem.name
class ForgetTicketJob(StateChangeJob): class Meta: app_label = "chroma_core" ordering = ["id"] state_transition = StateChangeJob.StateTransition(Ticket, ["granted", "revoked"], "forgotten") stateful_object = "ticket" state_verb = "Forget" ticket = models.ForeignKey(Ticket, on_delete=CASCADE) @classmethod def long_description(cls, stateful_object): return help_text["forget_ticket"] def description(self): return "Forget ticket %s" % self.ticket def on_success(self): self.ticket.mark_deleted() super(ForgetTicketJob, self).on_success()
class StartUnavailableFilesystemJob(FilesystemJob, StateChangeJob): state_verb = "Start" state_transition = StateChangeJob.StateTransition(ManagedFilesystem, "unavailable", "available") filesystem = models.ForeignKey("ManagedFilesystem") display_group = Job.JOB_GROUPS.COMMON display_order = 20 @classmethod def long_description(cls, stateful_object): return help_text["start_file_system"] def description(self): return "Start filesystem %s" % self.filesystem.name def get_deps(self): deps = [] for t in ObjectCache.get_targets_by_filesystem(self.filesystem_id): deps.append(DependOn(t, "mounted", fix_state="unavailable")) return DependAll(deps)