Module: RVC::Util

Extended by:
Util
Included in:
CmdModule, RubyEvaluator, Util
Defined in:
lib/rvc/util.rb

Constant Summary collapse

UserError =
Class.new(Exception)
PROGRESS_BAR_LEFT =
"["
PROGRESS_BAR_MIDDLE =
"="
PROGRESS_BAR_RIGHT =
"]"

Instance Method Summary collapse

Instance Method Details

#collect_children(obj, path) ⇒ Object



168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
# File 'lib/rvc/util.rb', line 168

def collect_children obj, path
  spec = {
    :objectSet => [
      {
        :obj => obj,
        :skip => true,
        :selectSet => [
          RbVmomi::VIM::TraversalSpec(
            :path => path,
            :type => obj.class.wsdl_name
          )
        ]
      }
    ],
    :propSet => [
      {
        :type => 'ManagedEntity',
        :pathSet => %w(name),
      }
    ]
  }

  results = obj._connection.propertyCollector.RetrieveProperties(:specSet => [spec])

  # Work around ESX 4.0 ignoring the skip field
  results.reject! { |r| r.obj == obj }

  Hash[results.map { |r| [r['name'], r.obj] }]
end

#display_inventory(tree, folder, indent = 0, &b) ⇒ Object



60
61
62
63
64
65
66
67
68
69
70
# File 'lib/rvc/util.rb', line 60

def display_inventory tree, folder, indent=0, &b
  tree[folder].sort_by { |k,(o,h)| o._ref }.each do |k,(o,h)|
    case o
    when VIM::Folder
      puts "#{"  "*indent}--#{k}"
      display_inventory tree, o, (indent+1), &b
    else
      b[o,h,indent]
    end
  end
end

#err(msg) ⇒ Object

Raises:



81
82
83
# File 'lib/rvc/util.rb', line 81

def err msg
  raise UserError.new(msg)
end

#interactive?Boolean

Returns:

  • (Boolean)


145
146
147
# File 'lib/rvc/util.rb', line 145

def interactive?
  terminal_columns > 0
end

#lookup(path) ⇒ Object

XXX just use an optional argument for type



26
27
28
# File 'lib/rvc/util.rb', line 26

def lookup path
  $shell.fs.lookup path
end

#lookup!(path, types) ⇒ Object



37
38
39
40
41
42
43
44
# File 'lib/rvc/util.rb', line 37

def lookup! path, types
  types = [types] unless types.is_a? Enumerable
  lookup(path).tap do |objs|
    objs.each do |obj|
      err "Expected #{types*'/'} but got #{obj.class} at #{path.inspect}" unless types.any? { |type| obj.is_a? type }
    end
  end
end

#lookup_single(path) ⇒ Object



30
31
32
33
34
35
# File 'lib/rvc/util.rb', line 30

def lookup_single path
  objs = lookup path
  err "Not found: #{path.inspect}" if objs.empty?
  err "More than one match for #{path.inspect}" if objs.size > 1
  objs.first
end

#lookup_single!(path, type) ⇒ Object



46
47
48
49
50
51
# File 'lib/rvc/util.rb', line 46

def lookup_single! path, type
  objs = lookup!(path, type)
  err "Not found: #{path.inspect}" if objs.empty?
  err "More than one match for #{path.inspect}" if objs.size > 1
  objs.first
end


53
54
55
56
57
58
# File 'lib/rvc/util.rb', line 53

def menu items
  items.each_with_index { |x, i| puts "#{i} #{x}" }
  input = Readline.readline("? ", false)
  return if !input or input.empty?
  items[input.to_i]
end

#progress(tasks) ⇒ Object



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
# File 'lib/rvc/util.rb', line 106

def progress tasks
  interested = %w(info.progress info.state info.entityName info.error info.name)
  connection = single_connection tasks
  connection.serviceInstance.wait_for_multiple_tasks interested, tasks do |h|
    if interactive?
      h.each do |task,props|
        state, entityName, name = props['info.state'], props['info.entityName'], props['info.name']
        name = $` if name =~ /_Task$/
        if state == 'running'
          text = "#{name} #{entityName}: #{state} "
          progress = props['info.progress']
          barlen = terminal_columns - text.size - 2
          progresslen = ((progress||0)*barlen)/100
          progress_bar = "#{PROGRESS_BAR_LEFT}#{PROGRESS_BAR_MIDDLE * progresslen}#{' ' * (barlen-progresslen)}#{PROGRESS_BAR_RIGHT}"
          $stdout.write "\e[K#{text}#{progress_bar}\n"
        elsif state == 'error'
          error = props['info.error']
          $stdout.write "\e[K#{name} #{entityName}: #{error.fault.class.wsdl_name}: #{error.localizedMessage}\n"
        else
          $stdout.write "\e[K#{name} #{entityName}: #{state}\n"
        end
      end
      $stdout.write "\e[#{h.size}A"
      $stdout.flush
    end
  end
  $stdout.write "\e[#{tasks.size}B" if interactive?
  true
end

#search_path(bin) ⇒ Object



72
73
74
75
76
77
78
# File 'lib/rvc/util.rb', line 72

def search_path bin
  ENV['PATH'].split(':').each do |x|
    path = File.join(x, bin)
    return path if File.exists? path
  end
  nil
end

#single_connection(objs) ⇒ Object



85
86
87
88
89
90
# File 'lib/rvc/util.rb', line 85

def single_connection objs
  conns = objs.map { |x| x._connection rescue nil }.compact.uniq
  err "No connections" if conns.size == 0
  err "Objects span multiple connections" if conns.size > 1
  conns[0]
end

#system_fg(cmd, env = {}) ⇒ Object



156
157
158
159
160
161
162
163
164
165
166
# File 'lib/rvc/util.rb', line 156

def system_fg cmd, env={}
  pid = fork do
    env.each { |k,v| ENV[k] = v }
    Process.setpgrp
    tcsetpgrp
    exec cmd
  end
  Process.waitpid2 pid
  tcsetpgrp
  nil
end

#tasks(objs, sym, args = {}) ⇒ Object



92
93
94
# File 'lib/rvc/util.rb', line 92

def tasks objs, sym, args={}
  progress(objs.map { |obj| obj._call :"#{sym}_Task", args })
end

#tcsetpgrp(pgrp = Process.getpgrp) ⇒ Object



149
150
151
152
153
154
# File 'lib/rvc/util.rb', line 149

def tcsetpgrp pgrp=Process.getpgrp
  return unless $stdin.tty?
  trap('TTOU', 'SIG_IGN')
  $stdin.ioctl 0x5410, [pgrp].pack('I')
  trap('TTOU', 'SIG_DFL')
end

#terminal_columnsObject



136
137
138
139
140
141
142
143
# File 'lib/rvc/util.rb', line 136

def terminal_columns
  begin
    require 'curses'
    Curses.cols
  rescue LoadError
    80
  end
end