Module: Fog::Hyperv::Utils::Winrm

Included in:
Compute::Real
Defined in:
lib/fog/hyperv/utils/winrm.rb

Overview

WinRM helper methods

Defined Under Namespace

Classes: LocalExecOutput

Instance Method Summary collapse

Instance Method Details

#ps_version?(version) ⇒ Boolean

Check if the PowerShell version is newer than the value specified

Parameters:

  • version (String)

    a semver version to check if powershell matches

Returns:

  • (Boolean)


13
14
15
# File 'lib/fog/hyperv/utils/winrm.rb', line 13

def ps_version?(version)
  Gem::Version(version) >= Gem::Version("#{ps_version[:major]}.#{ps_version[:minor]}")
end

#run_cmd(cmd, _skip_json: false, _target_computer: nil, **options) ⇒ Hash

Run a command on the Hyper-V system

Parameters:

  • cmd (String)

    the PowerShell command to execute

  • _skip_json (Boolean) (defaults to: false)

    should the return data be returned as-is, instead of being sent as JSON

  • _target_computer (String, nil) (defaults to: nil)

    the computer to execute the command on, in case of clustering

  • options (Hash)

    the options to call the command with

Options Hash (**options):

  • _json_depth (Integer) — default: 1

    the depth to limit the JSON object to on return

Returns:

  • (Hash)

    the returned object from PowerShell



24
25
26
27
28
# File 'lib/fog/hyperv/utils/winrm.rb', line 24

def run_cmd(cmd, _skip_json: false, _target_computer: nil, **options)
  _json_depth = options.delete(:_json_depth) { 1 }

  run_cmdlist([[cmd, options.dup]], skip_json: _skip_json, json_depth: _json_depth, target_computer: _target_computer)
end

#run_cmdlist(commands, skip_json: false, target_computer: nil, separate_calls: false, **options) ⇒ Object

Run a list of commands on the Hyper-V system

Parameters:

  • commands (Array<Array(String,Hash)>)

    a list of commands with their arguments to run

  • skip_json (Boolean) (defaults to: false)

    should the return value be given as-is, instead of being sent as JSON

  • target_computer (String, nil) (defaults to: nil)

    the computer to execute the command on, in case of clustering

  • separate_calls (Boolean) (defaults to: false)

    should the commands be run separately

  • options (Hash)

    additional options for the call

Options Hash (**options):

  • json_depth (Integer) — default: 1

    the depth to limit the JSON object to on return



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
# File 'lib/fog/hyperv/utils/winrm.rb', line 37

def run_cmdlist(commands, skip_json: false, target_computer: nil, separate_calls: false, **options)
  target_computer = [target_computer].flatten.compact
  target_computer << '.' if target_computer.empty?

  json_depth = options.delete(:json_depth) { 1 }

  Fog::Logger.debug "run_cmdlist given unknown meta-arguments: #{options.keys.join ', '}" if options.any?

  out = nil
  target_computer.each do |computer|
    connection(computer).shell(:powershell) do |shell|
      # Avoid confirmation questions, abort early on errors
      setup = [
        "$ConfirmPreference = 'None'",
        "$ErrorActionPreference = 'Stop'",
        '$PSNativeCommandUseErrorActionPreference = $true'
      ].join('; ')
      shell.run setup

      pscalls = commands.map.with_index do |(command, args), idx|
        last = idx == commands.size - 1
        build_pscall(command, _to_json: last && !skip_json, _json_depth: json_depth, **args)
      end
      pscalls = [pscalls.join("\n")] unless separate_calls

      pscalls.each do |cmd|
        Fog::Logger.debug "PS; >>> \"#{cmd.split("\n").join("\n\t")}\""
        out = shell.run cmd
        Fog::Logger.debug "PS; <<< OUT=[#{out.stdout.inspect}] ERR=[#{out.stderr.inspect}] EXIT=[#{out.exitcode}]"

        is_success = true
        is_success = shell.run('$?').stdout.strip.downcase == 'true' if out.stderr.include? 'FullyQualifiedErrorId'

        raise Fog::Hyperv::Errors::PSError.new(out, "When executing #{cmd}") if
          out.exitcode != 0 || !is_success
      end
    end
  end

  return out if skip_json
  return nil if out.stdout.strip.empty?

  json = Fog::JSON.decode(out.stdout)
  Fog::Hyperv.uncamelize(json)
end

#run_wql(query, _namespace: 'root/virtualization/v2', **where) ⇒ Hash

Perform a WQL query against the Hyper-V system

Parameters:

  • query (String)

    the query to perform

  • _namespace (String) (defaults to: 'root/virtualization/v2')

    the namespace to perform the call in

  • where (Hash)

    the WHERE arguments to add to the query

Returns:

  • (Hash)

    the return hash from the WQL query



88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/fog/hyperv/utils/winrm.rb', line 88

def run_wql(query, _namespace: 'root/virtualization/v2', **where)
  args = Fog::Hyperv.camelize(where).reject { |k, v| v.nil? || v.is_a?(FalseClass) || k.to_s.start_with?('_') }.map do |k, v|
    "#{k} = #{((v.is_a?(String) || v.to_s =~ /\s/) && v.inspect) || v}"
  end

  query = "#{query}#{" WHERE #{args.join ' AND '}" unless args.none?}"

  Fog::Logger.debug "WQL; in #{_namespace} >>> #{query}"
  data =
    if local?
      raise NotImplementedError, 'Not implemented for local connection'
      # run_cmd('Get-WmiObject', query:, namespace:, _return_fields: options.keys)
    else
      @connection.run_wql(query, "#{_namespace}/*")[:xml_fragment].first
    end
  Fog::Logger.debug "WQL; <<< #{data}"

  data
end