Puppet Function: pcmk_nodes_added

Defined in:
lib/puppet/parser/functions/pcmk_nodes_added.rb
Function type:
Ruby 3.x API

Overview

pcmk_nodes_added()Any

Input data cluster_members string separated by a space:

  • String A space-separated string containing a list of node names

  • String A list containing either a single string (single ip) or a list of strings (multiple ipaddresses) associated to each cluster node

  • String the version of pcs used

  • Output of ‘crm_node -l` (only used to ease unit testing) (optional)

Output forms:

  • array - output the plain array of nodes that have been added compared

    to the running cluster. It returns an empty array in case the
    cluster is not set up or if crm_node return an error
    

Returns:

  • (Any)


2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
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
# File 'lib/puppet/parser/functions/pcmk_nodes_added.rb', line 2

newfunction(
    :pcmk_nodes_added,
    type: :rvalue,
    arity: -1,
    doc: <<-eof
Input data cluster_members string separated by a space:
* String A space-separated string containing a list of node names
* String A list containing either a single string (single ip) or a list of strings
(multiple ipaddresses) associated to each cluster node
* String the version of pcs used
* Output of `crm_node -l` (only used to ease unit testing) (optional)

Output forms:
* array - output the plain array of nodes that have been added compared
        to the running cluster. It returns an empty array in case the
        cluster is not set up or if crm_node return an error
    eof
) do |args|
  # no point in doing this if the crm_node executable does not exist
  return [] if Facter::Util::Resolution.which('crm_node') == nil
  nodes = args[0]
  addr_list = args[1]
  pcs_version = args[2]
  crm_node_list = args[3]
  unless nodes.is_a? String
    fail "Got unsupported nodes input data: #{nodes.inspect}"
  end
  unless addr_list.is_a? Array
    fail "Got unsupported addr_list input data: #{addr_list.inspect}"
  end
  if crm_node_list && !crm_node_list.kind_of?(String) then
    fail "Got unsupported crm_node_list #{crm_node_list.inspect}"
  end
  node_list = nodes.split()
  fail "pcmk_cluster_setup: node list and addr list should be of the same size when defined and not empty" if addr_list.size > 0 and addr_list.size != node_list.size

  if crm_node_list && crm_node_list.kind_of?(String) then
    return [] if crm_node_list.empty?
    crm_nodes_output = crm_node_list
  else
    # A typical crm_node -l output is like the following:
    # [root@foobar-0 ~]# crm_node -l
    # 3 foobar-2 member
    # 1 foobar-0 member
    # 2 foobar-1 lost
    crm_nodes_output = `crm_node -l`
    # if the command fails we certainly did not add any nodes
    return [] if $?.exitstatus != 0
  end
  Puppet.debug("pcmk_nodes_added: crm_nodes_output #{crm_nodes_output}")

  crm_nodes = []
  crm_nodes_output.lines.each { |line|
    (id, node, state, _) = line.split(" ").collect(&:strip)
    valid_states = %w(member lost)
    state.downcase! if state
    crm_nodes.push(node.strip) if valid_states.include? state
  }
  nodes_added = node_list - crm_nodes

  if pcs_version =~ /0.10/
    # If the addr_list was specified we need to return a list in the form of
    # ['node1 addr=1.2.3.4', 'node2 addr=1.2.3.5 addr=1.2.3.6', 'node3 addr=1.2.3.7']
    if addr_list.size > 0
      ret = []
      nodes_addrs_added = node_list.zip(addr_list)
        .select { |node_addr| nodes_added.include?(node_addr[0]) }
      nodes_addrs_added.each do |node_addr|
        node = node_addr[0]
        ip = node_addr[1]
        # addr can be '1.2.3.4' or ['1.2.3.4', '1.2.3.5'] or
        if ip.is_a? String
          addr = "addr=#{ip}"
        elsif ip.is_a? Array
          addr = ''
          ip.each do |i|
            addr += "addr=#{i}"
            addr += " " if not i.equal?(ip.last)
          end
        else
          fail "pcmk_nodes_added: One of the addresses in addr_list is neither a String nor an Array"
        end
        ret << "#{node} #{addr}"
      end
    # only node_added is specified so we just return the original string
    else
      ret = nodes_added
    end
  elsif pcs_version =~ /0.9/
    # With pcs 0.9 only non-knet clusters are supported, aka only one address can be used
    # so we take the node name as we always did
    ret = nodes_added
  else
    fail("pcmk_nodes_added: pcs #{pcs_version} is unsupported")
  end

  Puppet.debug("pcmk_nodes_added: #{ret} [#{node_list} - #{crm_nodes}]")
  ret
end