Class: PuppetX::Voxpupuli::Corosync::Provider::CibHelper

Inherits:
Puppet::Provider
  • Object
show all
Defined in:
lib/puppet_x/voxpupuli/corosync/provider/cib_helper.rb

Direct Known Subclasses

Crmsh, Pcs

Class Method Summary collapse

Class Method Details

._get_epoch(cmd, cib = nil) ⇒ Object



109
110
111
112
113
114
115
116
117
118
# File 'lib/puppet_x/voxpupuli/corosync/provider/cib_helper.rb', line 109

def self._get_epoch(cmd, cib = nil)
  raw, status = run_command_in_cib(cmd, cib, false)
  return :absent if status.nonzero?

  doc = REXML::Document.new(raw)
  current_epoch = REXML::XPath.first(doc, '/cib').attributes['epoch']
  current_admin_epoch = REXML::XPath.first(doc, '/cib').attributes['admin_epoch']
  currentvalue = "#{current_admin_epoch}.#{current_epoch}" if current_epoch && current_admin_epoch
  currentvalue || :absent
end

._run_command_in_cib(cmd, cib = nil, failonfail = true, custom_environment = { combine: true }) ⇒ Object

Raises:

  • (Puppet::Error)


17
18
19
20
21
22
23
24
25
# File 'lib/puppet_x/voxpupuli/corosync/provider/cib_helper.rb', line 17

def self._run_command_in_cib(cmd, cib = nil, failonfail = true, custom_environment = { combine: true })
  debug("Executing #{cmd} in the CIB") if cib.nil?
  debug("Executing #{cmd} in the shadow CIB \"#{cib}\"") unless cib.nil?
  raw = Puppet::Util::Execution.execute(cmd, { failonfail: failonfail }.merge(custom_environment))
  status = raw.exitstatus
  return raw, status if status.zero? || failonfail == false
  raise Puppet::Error, "Command #{cmd.join(' ')} failed" if cib.nil?
  raise Puppet::Error, "Command #{cmd.join(' ')} failed in the shadow CIB \"#{cib}\"" unless cib.nil?
end

.node2hash(node, anon_hash_nodes = []) ⇒ Object

The node2hash method maps resource locations from XML into hashes. An anonymous hash is returned for node names given in ‘anon_hash_nodes`.



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/puppet_x/voxpupuli/corosync/provider/cib_helper.rb', line 42

def self.node2hash(node, anon_hash_nodes = [])
  attr = {}
  name = ''

  return nil unless node.instance_of? REXML::Element

  # Add attributes from the node
  node.attributes.each do |key, val|
    if key == 'id'
      name = val
    else
      attr[key] = val
    end
  end

  # Traverse elements in the XML tree recursively
  node.elements.each do |child|
    attr[child.name] = [] unless attr[child.name].is_a? Array
    attr[child.name] << node2hash(child, anon_hash_nodes)
  end

  # Return only the attributes if requested and a hash otherwise
  anon_hash_nodes.include?(node.name) ? attr : { name => attr }
end

.nvpairs_to_hash(e) ⇒ Object

given an XML element containing some <nvpair>s, return a hash. Return an empty hash if ‘e` is nil.



29
30
31
32
33
34
35
36
37
38
# File 'lib/puppet_x/voxpupuli/corosync/provider/cib_helper.rb', line 29

def self.nvpairs_to_hash(e)
  return {} if e.nil?

  hash = {}
  e.each_element do |i|
    hash[i.attributes['name']] = i.attributes['value'].strip
  end

  hash
end

.rule_expression(rulename, expressions, boolean_op = 'and') ⇒ Object

Generate a string with the rule expression

  • rulename is the name of the rule (used in error messages)

  • expressions is an array of expressions as returned by node2hash()

  • boolean_op is the operator; this must be either ‘and’ or ‘or’

Raises:

  • (Puppet::Error)


71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/puppet_x/voxpupuli/corosync/provider/cib_helper.rb', line 71

def self.rule_expression(rulename, expressions, boolean_op = 'and')
  rule_parameters = []
  count = 0

  raise Puppet::Error, "boolean-op must be 'and' or 'or' in rule #{rulename}" if boolean_op != 'and' && boolean_op != 'or'

  expressions.each do |expr|
    rule_parameters << boolean_op if count.positive?
    count += 1

    raise Puppet::Error, "attribute must be defined for expression #{count} in rule #{rulename}" if expr['attribute'].nil?

    raise Puppet::Error, "operation must be defined for expression #{count} in rule #{rulename}" if expr['operation'].nil?

    attribute = expr['attribute']
    operation = expr['operation']

    case operation
    when 'defined', 'not_defined'
      rule_parameters << operation
      rule_parameters << attribute

    when 'lt', 'gt', 'lte', 'gte', 'eq', 'ne'
      raise Puppet::Error, "value must be defined for expression #{count} in rule #{rulename}" if expr['value'].nil?

      rule_parameters << attribute
      rule_parameters << operation
      rule_parameters << expr['value']

    else
      # FIXME: time- and date-based expressions not yet implemented
      raise Puppet::Error, "illegal operation '#{operation}' for expression #{count} in rule #{rulename}"
    end
  end

  rule_parameters
end

.wait_for_nonzero_epoch(shadow_cib) ⇒ Object

This function waits for the epoch to be different than 0.0 different than :absent. Returns the value of the epoch as soon an it is present and different that 0.0 or eventually returns the value after a certain time.



123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
# File 'lib/puppet_x/voxpupuli/corosync/provider/cib_helper.rb', line 123

def self.wait_for_nonzero_epoch(shadow_cib)
  begin
    Timeout.timeout(60) do
      if shadow_cib
        epoch = get_epoch
        while epoch == :absent || epoch.start_with?('0.')
          sleep 2
          epoch = get_epoch
        end
      else
        sleep 2 while ['0.0', :absent].include?(get_epoch)
      end
    end
  rescue Timeout::Error
    debug('Timeout reached while fetching a relevant epoch')
  end
  get_epoch
end