Module: Train::Platforms::Detect::Helpers::OSCommon

Includes:
Linux, Windows
Included in:
Scanner, UUID
Defined in:
lib/train/platforms/detect/helpers/os_common.rb

Instance Method Summary collapse

Methods included from Windows

#check_cmd, #check_powershell, #detect_windows, #local_windows?, #read_wmic, #read_wmic_cpu, #windows_uuid, #windows_uuid_from_chef, #windows_uuid_from_machine_file, #windows_uuid_from_registry, #windows_uuid_from_wmic

Methods included from Linux

#linux_os_release, #lsb_config, #lsb_release, #parse_os_release_info, #read_linux_lsb, #redhatish, #redhatish_platform, #redhatish_version

Instance Method Details

#backend_nameObject



18
19
20
# File 'lib/train/platforms/detect/helpers/os_common.rb', line 18

def backend_name
  @backend.class.name
end

#brocade_versionObject



75
76
77
78
79
80
81
82
83
# File 'lib/train/platforms/detect/helpers/os_common.rb', line 75

def brocade_version
  return @cache[:brocade] if @cache.key?(:brocade)

  res = command_output("version")

  m = res.match(/^Fabric OS:\s+v(\S+)$/)

  @cache[:brocade] = m && { version: m[1], type: "fos" }
end

#cisco_show_versionObject



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/train/platforms/detect/helpers/os_common.rb', line 85

def cisco_show_version
  return @cache[:cisco] if @cache.key?(:cisco)

  res = command_output("show version")

  m = res.match(/Cisco IOS Software, [^,]+? \(([^,]+?)\), Version (\d+\.\d+)/)
  unless m.nil?
    return @cache[:cisco] = { version: m[2], model: m[1], type: "ios" }
  end

  m = res.match(/Cisco IOS Software, IOS-XE Software, [^,]+? \(([^,]+?)\), Version (\d+\.\d+\.\d+[A-Z]*)/)
  unless m.nil?
    return @cache[:cisco] = { version: m[2], model: m[1], type: "ios-xe" }
  end

  m = res.match(/Cisco Nexus Operating System \(NX-OS\) Software/)
  unless m.nil?
    v = res[/^\s*system:\s+version (\d+\.\d+)/, 1]
    return @cache[:cisco] = { version: v, type: "nexus" }
  end

  @cache[:cisco] = nil
end

#command_output(cmd) ⇒ Object



36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/train/platforms/detect/helpers/os_common.rb', line 36

def command_output(cmd)
  res = @backend.run_command(cmd)
  stdout = res.stdout
  stderr = res.stderr
  # When you try to execute command using ssh connection as root user and you have provided ssh user identity file
  # it gives standard output to login as authorized user other than root. To show this standard output as an error
  # to user we are matching the string of stdout and raising the error here so that user gets exact information.
  if @backend.class.to_s == "Train::Transports::SSH::Connection"
    if stdout =~ /Please login as the user/
      raise Train::UserError, "SSH failed: #{stdout}"
    end

    if stderr =~ /WARNING: Your password has expired/
      raise Train::UserError, "SSH failed: #{stderr}"
    end
  end

  stdout.strip! unless stdout.nil?
  stdout
end

#json_cmd(cmd) ⇒ Object



164
165
166
167
168
169
170
171
172
173
174
175
# File 'lib/train/platforms/detect/helpers/os_common.rb', line 164

def json_cmd(cmd)
  cmd = @backend.run_command(cmd)
  if cmd.exit_status == 0 && !cmd.stdout.empty?
    require "json" unless defined?(JSON)
    eos_ver = JSON.parse(cmd.stdout)
    @platform[:release] = eos_ver["version"]
    @platform[:arch] = eos_ver["architecture"]
    true
  end
rescue JSON::ParserError
  nil
end

#ruby_host_os(regex) ⇒ Object



10
11
12
# File 'lib/train/platforms/detect/helpers/os_common.rb', line 10

def ruby_host_os(regex)
  ::RbConfig::CONFIG["host_os"] =~ regex
end

#set_from_unameObject



177
178
179
180
181
# File 'lib/train/platforms/detect/helpers/os_common.rb', line 177

def set_from_uname
  @platform[:name]    = unix_uname_s.lines.first.chomp
  @platform[:release] = unix_uname_r.lines.first.chomp
  true
end

#unix_file_contents(path) ⇒ Object



22
23
24
25
26
27
28
29
30
# File 'lib/train/platforms/detect/helpers/os_common.rb', line 22

def unix_file_contents(path)
  # keep a log of files incase multiple checks call the same one
  return @files[path] if @files.key?(path)

  res = @backend.run_command("test -f #{path} && cat #{path}")
  # ignore files that can't be read
  @files[path] = res.exit_status == 0 ? res.stdout : nil
  @files[path]
end

#unix_file_exist?(path) ⇒ Boolean

Returns:

  • (Boolean)


32
33
34
# File 'lib/train/platforms/detect/helpers/os_common.rb', line 32

def unix_file_exist?(path)
  @backend.run_command("test -f #{path}").exit_status == 0
end

#unix_uname_mObject



69
70
71
72
73
# File 'lib/train/platforms/detect/helpers/os_common.rb', line 69

def unix_uname_m
  return @uname[:m] if @uname.key?(:m)

  @uname[:m] = command_output("uname -m")
end

#unix_uname_rObject



63
64
65
66
67
# File 'lib/train/platforms/detect/helpers/os_common.rb', line 63

def unix_uname_r
  return @uname[:r] if @uname.key?(:r)

  @uname[:r] = command_output("uname -r")
end

#unix_uname_sObject



57
58
59
60
61
# File 'lib/train/platforms/detect/helpers/os_common.rb', line 57

def unix_uname_s
  return @uname[:s] if @uname.key?(:s)

  @uname[:s] = command_output("uname -s")
end

#unix_uuidObject



109
110
111
112
113
114
# File 'lib/train/platforms/detect/helpers/os_common.rb', line 109

def unix_uuid
  (unix_uuid_from_chef         ||
   unix_uuid_from_machine_file ||
   uuid_from_command           ||
   raise(Train::TransportError, "Cannot find a UUID for your node."))
end

#unix_uuid_from_chefObject



116
117
118
119
120
121
122
# File 'lib/train/platforms/detect/helpers/os_common.rb', line 116

def unix_uuid_from_chef
  file = @backend.file("/var/chef/cache/data_collector_metadata.json")
  if file.exist? && file.size != 0
    json = ::JSON.parse(file.content)
    return json["node_uuid"] if json["node_uuid"]
  end
end

#unix_uuid_from_machine_fileObject



124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
# File 'lib/train/platforms/detect/helpers/os_common.rb', line 124

def unix_uuid_from_machine_file
  %W{
    /etc/chef/chef_guid
    #{ENV["HOME"]}/.chef/chef_guid
    /etc/machine-id
    /var/lib/dbus/machine-id
    /var/db/dbus/machine-id
  }.each do |path|
    file = @backend.file(path)
    next unless file.exist? && file.size != 0
    return file.content.chomp if path =~ /guid/

    return uuid_from_string(file.content.chomp)
  end
  nil
end

#uuid_from_commandObject

This takes a command from the platform detect block to run. We expect the command to return a unique identifier which we turn into a UUID.



144
145
146
147
148
149
# File 'lib/train/platforms/detect/helpers/os_common.rb', line 144

def uuid_from_command
  return unless @platform[:uuid_command]

  result = @backend.run_command(@platform[:uuid_command])
  uuid_from_string(result.stdout.chomp) if result.exit_status == 0 && !result.stdout.empty?
end

#uuid_from_string(string) ⇒ Object

This hashes the passed string into SHA1. Then it downgrades the 160bit SHA1 to a 128bit then we format it as a valid UUIDv5.



154
155
156
157
158
159
160
161
162
# File 'lib/train/platforms/detect/helpers/os_common.rb', line 154

def uuid_from_string(string)
  hash = Digest::SHA1.new
  hash.update(string)
  ary = hash.digest.unpack("NnnnnN")
  ary[2] = (ary[2] & 0x0FFF) | (5 << 12)
  ary[3] = (ary[3] & 0x3FFF) | 0x8000
  # rubocop:disable Style/FormatString
  "%08x-%04x-%04x-%04x-%04x%08x" % ary
end

#winrm?Boolean

Returns:

  • (Boolean)


14
15
16
# File 'lib/train/platforms/detect/helpers/os_common.rb', line 14

def winrm?
  backend_name == "TrainPlugins::WinRM::Connection"
end