ClusterLabs/hawk

View on GitHub
hawk/app/models/master.rb

Summary

Maintainability
B
5 hrs
Test Coverage
# Copyright (c) 2009-2015 Tim Serong <tserong@suse.com>
# See COPYING for license.
require 'invoker'

class Master < Resource
  attribute :child, String

  validates :child,
    presence: { message: _("No Multi-state child specified") }

  validate do |record|
    # TODO(must): Ensure children are sanitized
  end

  def mapping
    self.class.mapping
  end

  class << self
    def all
      super.select do |record|
        record.is_a? self
      end
    end

    def instantiate(xml)
      record = allocate

      record.child = if xml.elements["primitive|group"]
        xml.elements["primitive|group"].attributes["id"]
      else
        nil
      end

      record.meta = if xml.elements["meta_attributes"]
        vals = xml.elements["meta_attributes"].elements.collect do |el|
          [
            el.attributes["name"],
            el.attributes["value"]
          ]
        end

        Hash[vals]
      else
        {}
      end

      record
    end

    def cib_type
      :master
    end

    def mapping
      # TODO(must): Are other meta attributes for clone valid?
      @mapping ||= begin
        {
          "is-managed" => {
            type: "boolean",
            default: "true",
            longdesc: _("Is the cluster allowed to start and stop the resource?")
          },
          "maintenance" => {
            type: "boolean",
            default: "false",
            longdesc: _("Resources in maintenance mode are not monitored by the cluster.")
          },
          "priority" => {
            type: "integer",
            default: "0",
            longdesc: _("If not all resources can be active, the cluster will stop lower priority resources in order to keep higher priority ones active.")
          },
          "target-role" => {
            type: "enum",
            default: "Stopped",
            values: [
              "Started",
              "Stopped",
              "Master"
            ],
            longdesc: _("What state should the cluster attempt to keep this resource in?")
          },
          "clone-max" => {
            type: "integer",
            default: current_cib.nodes.length.to_s,
            longdesc: _("How many copies of the resource to start. Defaults to the number of nodes in the cluster.")
          },
          "clone-node-max" => {
            type: "integer",
            default: "1",
            longdesc: _("How many copies of the resource can be started on a single node. Defaults to 1.")
          },
          "notify" => {
            type: "boolean",
            default: "false",
            longdesc: _("When stopping or starting a copy of the clone, tell all the other copies beforehand and when the action was successful.")
          },
          "globally-unique" => {
            type: "boolean",
            default: "true",
            longdesc: _("Does each copy of the clone perform a different function?")
          },
          "ordered" => {
            type: "boolean",
            default: "false",
            longdesc: _("Should the copies be started in series (instead of in parallel)?")
          },
          "interleave" => {
            type: "boolean",
            default: "false",
            longdesc: _("Changes the behavior of ordering constraints (between clones/masters) so that instances can start/stop as soon as their peer instance has (rather than waiting for every instance of the other clone has).")
          },
          "master-max" => {
            type: "integer",
            default: "1",
            longdesc: _("How many copies of the resource can be promoted to master status.")
          },
          "master-node-max" => {
            type: "integer",
            default: "1",
            longdesc: _("How many copies of the resource can be promoted to master status on a single node.")
          }
        }
      end
    end
  end

  protected

  def update
    unless self.class.exists?(self.id, self.class.cib_type_write)
      errors.add :base, _("The ID \"%{id}\" does not exist") % { id: self.id }
      return false
    end

    begin
      merge_nvpairs("meta_attributes", meta)
      Invoker.instance.cibadmin_replace xml.to_s
    rescue NotFoundError, SecurityError, RuntimeError => e
      errors.add :base, e.message
      return false
    end
  end

  def shell_syntax
    [].tap do |cmd|
      cmd.push "ms #{id} #{child}"

      unless meta.empty?
        cmd.push "meta"

        meta.each do |key, value|
          cmd.push [
            key,
            value.shellescape
          ].join("=")
        end
      end
    end.join(" ")
  end
end