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
|
require_relative "os_linux"
require_relative "os_windows"
require "rbconfig"
module Train::Platforms::Detect::Helpers
module OSCommon
include Train::Platforms::Detect::Helpers::Linux
include Train::Platforms::Detect::Helpers::Windows
def ruby_host_os(regex)
::RbConfig::CONFIG["host_os"] =~ regex
end
def winrm?
backend_name == "TrainPlugins::WinRM::Connection"
end
def backend_name
@backend.class.name
end
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
def unix_file_exist?(path)
@backend.run_command("test -f #{path}").exit_status == 0
end
def command_output(cmd)
res = @backend.run_command(cmd).stdout
# When you try to execute command using ssh connction as root user and you have provided ssh user identity file
# it gives standard output to login as authorised user other than root. To show this standard ouput 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" && res =~ /Please login as the user/
raise Train::UserError, "SSH failed: #{res}"
end
res.strip! unless res.nil?
res
end
def unix_uname_s
return @uname[:s] if @uname.key?(:s)
@uname[:s] = command_output("uname -s")
end
def unix_uname_r
return @uname[:r] if @uname.key?(:r)
@uname[:r] = command_output("uname -r")
end
def unix_uname_m
return @uname[:m] if @uname.key?(:m)
@uname[:m] = command_output("uname -m")
end
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
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
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
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
def unix_uuid_from_machine_file
# require 'pry';binding.pry
%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
# 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.
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
# This hashes the passed string into SHA1.
# Then it downgrades the 160bit SHA1 to a 128bit
# then we format it as a valid UUIDv5.
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
def json_cmd(cmd)
cmd = @backend.run_command(cmd)
if cmd.exit_status == 0 && !cmd.stdout.empty?
require "json"
eos_ver = JSON.parse(cmd.stdout)
@platform[:release] = eos_ver["version"]
@platform[:arch] = eos_ver["architecture"]
true
end
rescue JSON::ParserError
nil
end
def set_from_uname
@platform[:name] = unix_uname_s.lines.first.chomp
@platform[:release] = unix_uname_r.lines.first.chomp
true
end
end
end
|