summaryrefslogtreecommitdiff
path: root/lib/ohai/plugins/rackspace.rb
blob: 469290b66cc1769ad7b14cc7d7edad348df879b0 (plain)
1
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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
# frozen_string_literal: true
#
# Author:: Cary Penniman (<cary@rightscale.com>)
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

Ohai.plugin(:Rackspace) do
  provides "rackspace"

  depends "kernel", "network/interfaces"

  # Checks for matching rackspace kernel name
  #
  # === Return
  # true:: If kernel name matches
  # false:: Otherwise
  def has_rackspace_kernel?
    kernel[:release].end_with?("-rscloud")
  end

  # Checks for rackspace provider attribute
  #
  # === Return
  # true:: If rackspace provider attribute found
  # false:: Otherwise
  def has_rackspace_metadata?
    so = shell_out("xenstore-read vm-data/provider_data/provider")
    if so.exitstatus == 0
      so.stdout.strip.casecmp("rackspace") == 0
    end
  rescue Ohai::Exceptions::Exec
    false
  end

  # Checks for the rackspace manufacturer on Windows
  # === Return
  # true:: If the rackspace cloud can be identified
  # false:: Otherwise
  def has_rackspace_manufacturer?
    return false unless RUBY_PLATFORM.match?(/mswin|mingw32|windows/)

    require "wmi-lite/wmi" unless defined?(WmiLite::Wmi)
    wmi = WmiLite::Wmi.new
    if wmi.first_of("Win32_ComputerSystem")["PrimaryOwnerName"] == "Rackspace"
      logger.trace("Plugin Rackspace: has_rackspace_manufacturer? == true")
      true
    end
  end

  # Identifies the rackspace cloud
  #
  # === Return
  # true:: If the rackspace cloud can be identified
  # false:: Otherwise
  def looks_like_rackspace?
    hint?("rackspace") || has_rackspace_metadata? || has_rackspace_kernel? || has_rackspace_manufacturer?
  end

  # Names rackspace ip address
  #
  # === Parameters
  # name<Symbol>:: Use :public_ip or :private_ip
  # eth<Symbol>:: Interface name of public or private ip
  def get_ip_address(name, eth)
    network[:interfaces][eth][:addresses].each do |key, info|
      if info["family"] == "inet"
        rackspace[name] = key
        break # break when we found an address
      end
    end
  end

  # Names rackspace ipv6 address for interface
  #
  # === Parameters
  # name<Symbol>:: Use :public_ip or :private_ip
  # eth<Symbol>:: Interface name of public or private ip
  def get_global_ipv6_address(name, eth)
    network[:interfaces][eth][:addresses].each do |key, info|
      # check if we got an ipv6 address and if its in global scope
      if info["family"] == "inet6" && info["scope"] == "Global"
        rackspace[name] = key
        break # break when we found an address
      end
    end
  end

  # Get the rackspace region
  #
  def get_region
    so = shell_out("xenstore-ls vm-data/provider_data")
    if so.exitstatus == 0
      so.stdout.split("\n").each do |line|
        rackspace[:region] = line.split[2].delete('\"') if /^region/.match?(line)
      end
    end
  rescue Ohai::Exceptions::Exec
    logger.trace("Plugin Rackspace: Unable to find xenstore-ls, cannot capture region information for Rackspace cloud")
    nil
  end

  # Get the rackspace instance_id
  #
  def get_instance_id
    so = shell_out("xenstore-read name")
    if so.exitstatus == 0
      rackspace[:instance_id] = so.stdout.gsub(/instance-/, "")
    end
  rescue Ohai::Exceptions::Exec
    logger.trace("Plugin Rackspace: Unable to find xenstore-read, cannot capture instance ID information for Rackspace cloud")
    nil
  end

  # Get the rackspace private networks
  #
  def get_private_networks
    so = shell_out("xenstore-ls vm-data/networking")
    if so.exitstatus == 0
      networks = []
      so.stdout.split("\n").map { |l| l.split("=").first.strip }.map do |item|
        so = shell_out("xenstore-read vm-data/networking/#{item}")
        if so.exitstatus == 0
          networks.push(FFI_Yajl::Parser.new.parse(so.stdout))
        else
          logger.trace("Plugin Rackspace: Unable to capture custom private networking information for Rackspace cloud")
          return false
        end
      end
      # these networks are already known to ohai, and are not 'private networks'
      networks.delete_if { |hash| hash["label"] == "private" }
      networks.delete_if { |hash| hash["label"] == "public" }
    end
  rescue Ohai::Exceptions::Exec
    logger.trace("Plugin Rackspace: Unable to capture custom private networking information for Rackspace cloud")
    nil
  end

  collect_data do
    require "resolv"

    # Adds rackspace Mash
    if looks_like_rackspace?
      rackspace Mash.new
      get_ip_address(:public_ip, :eth0)
      get_ip_address(:private_ip, :eth1)
      get_region
      get_instance_id
      # public_ip + private_ip are deprecated in favor of public_ipv4 and local_ipv4 to standardize.
      rackspace[:public_ipv4] = rackspace[:public_ip]
      get_global_ipv6_address(:public_ipv6, :eth0)
      unless rackspace[:public_ip].nil?
        rackspace[:public_hostname] = begin
          Resolv.getname(rackspace[:public_ip])
                                      rescue Resolv::ResolvError, Resolv::ResolvTimeout
                                        rackspace[:public_ip]
        end
      end
      rackspace[:local_ipv4] = rackspace[:private_ip]
      get_global_ipv6_address(:local_ipv6, :eth1)
      rackspace[:local_hostname] = hostname
      private_networks = get_private_networks
      rackspace[:private_networks] = private_networks if private_networks
    end
  end

end