hawk/app/models/master.rb
# 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