rvc 1.5.0 → 1.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. data/README.rdoc +1 -1
  2. data/Rakefile +2 -1
  3. data/VERSION +1 -1
  4. data/bin/rvc +53 -9
  5. data/lib/rvc/completion.rb +57 -19
  6. data/lib/rvc/extensions/ComputeResource.rb +2 -2
  7. data/lib/rvc/extensions/DVPortSetting.rb +108 -0
  8. data/lib/rvc/extensions/Datacenter.rb +19 -4
  9. data/lib/rvc/extensions/Datastore.rb +6 -1
  10. data/lib/rvc/extensions/DistributedVirtualPort.rb +146 -0
  11. data/lib/rvc/extensions/DistributedVirtualPortgroup.rb +274 -10
  12. data/lib/rvc/extensions/DistributedVirtualSwitch.rb +124 -3
  13. data/lib/rvc/extensions/Folder.rb +9 -2
  14. data/lib/rvc/extensions/HostSystem.rb +60 -0
  15. data/lib/rvc/extensions/ManagedEntity.rb +19 -0
  16. data/lib/rvc/extensions/ParaVirtualSCSIController.rb +25 -0
  17. data/lib/rvc/extensions/PerfCounterInfo.rb +26 -0
  18. data/lib/rvc/extensions/PerformanceManager.rb +83 -0
  19. data/lib/rvc/extensions/ResourcePool.rb +21 -0
  20. data/lib/rvc/extensions/VirtualDevice.rb +59 -0
  21. data/lib/rvc/extensions/VirtualDisk.rb +25 -0
  22. data/lib/rvc/extensions/VirtualEthernetCard.rb +32 -0
  23. data/lib/rvc/extensions/VirtualMachine.rb +112 -1
  24. data/lib/rvc/field.rb +122 -0
  25. data/lib/rvc/filesystem_session.rb +20 -0
  26. data/lib/rvc/inventory.rb +35 -12
  27. data/lib/rvc/known_hosts.rb +20 -0
  28. data/lib/rvc/memory_session.rb +20 -0
  29. data/lib/rvc/modules.rb +67 -7
  30. data/lib/rvc/modules/alarm.rb +37 -0
  31. data/lib/rvc/modules/basic.rb +172 -41
  32. data/lib/rvc/modules/cluster.rb +18 -2
  33. data/lib/rvc/modules/core.rb +63 -0
  34. data/lib/rvc/modules/datastore.rb +158 -0
  35. data/lib/rvc/modules/device.rb +275 -0
  36. data/lib/rvc/modules/esxcli.rb +193 -0
  37. data/lib/rvc/modules/find.rb +125 -0
  38. data/lib/rvc/modules/issue.rb +33 -0
  39. data/lib/rvc/modules/perf.rb +284 -0
  40. data/lib/rvc/modules/permissions.rb +20 -0
  41. data/lib/rvc/modules/resource_pool.rb +69 -0
  42. data/lib/rvc/modules/role.rb +23 -3
  43. data/lib/rvc/modules/snapshot.rb +20 -0
  44. data/lib/rvc/modules/vds.rb +605 -0
  45. data/lib/rvc/modules/vim.rb +103 -26
  46. data/lib/rvc/modules/vm.rb +93 -220
  47. data/lib/rvc/modules/vnc.rb +50 -13
  48. data/lib/rvc/option_parser.rb +50 -2
  49. data/lib/rvc/readline-ffi.rb +2 -1
  50. data/lib/rvc/shell.rb +34 -33
  51. data/lib/rvc/util.rb +120 -2
  52. data/test/test_fs.rb +9 -5
  53. data/test/test_metric.rb +79 -0
  54. metadata +33 -3
@@ -154,4 +154,4 @@ patch so everyone can use it.
154
154
  == Development
155
155
 
156
156
  Send patches to rlane@vmware.com, or fork the project on GitHub and send me a
157
- pull request.
157
+ pull request. RVC developers hang out in #rvc on Freenode.
data/Rakefile CHANGED
@@ -7,11 +7,12 @@ begin
7
7
  gem.email = "rlane@vmware.com"
8
8
  #gem.homepage = ""
9
9
  gem.authors = ["Rich Lane"]
10
- gem.add_dependency 'rbvmomi', '>= 1.3.0'
10
+ gem.add_dependency 'rbvmomi', '>= 1.5.0'
11
11
  gem.add_dependency 'trollop', '>= 1.16.2'
12
12
  gem.add_dependency 'backports', '>= 1.18.2'
13
13
  gem.add_dependency 'highline', '>= 1.6.1'
14
14
  gem.add_dependency 'zip', '>= 2.0.2'
15
+ gem.add_dependency 'terminal-table', '>= 1.4.2'
15
16
  #gem.add_dependency 'ffi', '>= 1.0.7'
16
17
  end
17
18
  rescue LoadError
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.5.0
1
+ 1.6.0
data/bin/rvc CHANGED
@@ -28,6 +28,7 @@ require 'shellwords'
28
28
  require 'yaml'
29
29
  require 'backports'
30
30
  require 'rvc'
31
+ require 'tempfile'
31
32
 
32
33
  VIM = RbVmomi::VIM
33
34
 
@@ -54,6 +55,7 @@ EOS
54
55
  opt :create_directory, "Create the initial directory if it doesn't exist", :short => :none
55
56
  opt :cmd, "command to evaluate", :short => 'c', :multi => true, :type => :string
56
57
  opt :script, "file to execute", :short => 's', :type => :string
58
+ opt :cookie, "authentication cookie file", :short => 'k', :type => :string
57
59
  end
58
60
 
59
61
  $interactive = $opts[:script].nil? and $stdin.tty?
@@ -77,20 +79,38 @@ $shell.session.connections.each do |key|
77
79
  conn = $shell.session.get_connection(key) or fail "no such connection #{key.inspect}"
78
80
  uri = "#{conn['username']}@#{conn['host']}"
79
81
  begin
80
- puts "Connecting to #{uri}..."
82
+ puts "Connecting to #{conn['host']}..."
81
83
  CMD.vim.connect uri, {}
82
84
  rescue RVC::Util::UserError
83
- puts "Failed to connect to #{uri}: #{$!.message}"
85
+ puts "Failed to connect to #{conn['host']}: #{$!.message}"
84
86
  exit 1
85
87
  end
86
88
  end
87
89
 
90
+ cookies = {}
91
+ certdigests = {}
92
+ if $opts[:cookie]
93
+ File.readlines($opts[:cookie]).each do |info|
94
+ host, cookie, certdigest = info.chomp.split('|')
95
+ cookies[host] = cookie
96
+ certdigests[host] = certdigest
97
+ end
98
+ end
99
+
88
100
  ARGV.each do |uri|
101
+ # get hostname from uri to display in "connecting to..." message
102
+ hostinfo = uri.split("@")
103
+ host = if hostinfo.length > 1
104
+ hostinfo[1].split(":")[0]
105
+ else
106
+ hostinfo[0].split(":")[0]
107
+ end
89
108
  begin
90
- puts "Connecting to #{uri}..." if (ARGV+$shell.session.connections).size > 1
91
- CMD.vim.connect uri, {}
109
+ puts "Connecting to #{host}..." if (ARGV+$shell.session.connections).size > 1
110
+ CMD.vim.connect uri, {:cookie => cookies[host],
111
+ :certdigest => certdigests[host]}
92
112
  rescue RVC::Util::UserError
93
- puts "Failed to connect to #{uri}: #{$!.message}"
113
+ puts "Failed to connect to #{host}: #{$!.message}"
94
114
  exit 1
95
115
  end
96
116
  end
@@ -99,7 +119,11 @@ if $interactive
99
119
  RVC::Completion.install
100
120
  history_fn = "#{ENV['HOME']}/.rvc-history"
101
121
  IO.foreach(history_fn) { |l| Readline::HISTORY << l.chomp } rescue puts "Welcome to RVC. Try the 'help' command."
102
- history = File.open(history_fn, 'a')
122
+ begin
123
+ history = File.open(history_fn, 'a')
124
+ rescue Errno::EACCES
125
+ history = nil
126
+ end
103
127
  end
104
128
 
105
129
  if $opts[:path]
@@ -127,23 +151,43 @@ if defined? Ocra
127
151
  end
128
152
 
129
153
  if $interactive
130
- $stderr.puts "VMRC is not installed. You will be unable to view virtual machine consoles. Use the vmrc.install command to install it." unless CMD.vmrc.find_vmrc
154
+ if ENV['DISPLAY']
155
+ $stderr.puts "VMRC is not installed. You will be unable to view virtual machine consoles. Use the vmrc.install command to install it." unless CMD.vmrc.find_vmrc
156
+ end
131
157
  $stderr.puts "Use the 'connect' command to connect to an ESX or VC server." if $shell.connections.empty?
132
158
  CMD.basic.ls RVC::Util.lookup_single('.')
133
159
  end
134
160
 
161
+ trap "SIGCHLD" do |sig|
162
+ begin
163
+ while pid = Process.wait(-1, Process::WNOHANG)
164
+ end
165
+ rescue Errno::ECHILD
166
+ end
167
+ end
168
+
135
169
  if $opts[:script]
136
170
  $shell.eval_ruby File.read($opts[:script]), $opts[:script]
137
171
  else
138
172
  while true
139
173
  begin
140
- input = $opts[:cmd].shift || Readline.readline($shell.prompt, false) or break
174
+ begin
175
+ input = $opts[:cmd].shift || Readline.readline($shell.prompt, false) or break
176
+ rescue
177
+ puts "\n#{$!.class} during readline: #{$!.message}"
178
+ $!.backtrace.each { |x| puts x } if $shell.debug
179
+ next
180
+ end
141
181
  input = input.strip
142
182
  next if input.empty?
143
- (history.puts input; Readline::HISTORY << input) unless input == Readline::HISTORY.to_a[-1]
183
+ (history && history.puts(input); Readline::HISTORY << input) unless input == Readline::HISTORY.to_a[-1]
144
184
  $shell.eval_input input
145
185
  rescue Interrupt
146
186
  puts
147
187
  end
148
188
  end
149
189
  end
190
+
191
+ $shell.connections.each do |name, conn|
192
+ conn.close if conn.respond_to? :close rescue puts("failed to close connection #{name.inspect}: #{$!.class}: #{$!.message}")
193
+ end
@@ -40,10 +40,16 @@ module Completion
40
40
 
41
41
  Completor = lambda do |word|
42
42
  return unless word
43
- line = Readline.line_buffer if Readline.respond_to? :line_buffer
44
- append_char, candidates = RVC::Completion.complete word, line
45
- Readline.completion_append_character = append_char
46
- candidates
43
+ begin
44
+ line = Readline.line_buffer if Readline.respond_to? :line_buffer
45
+ append_char, candidates = RVC::Completion.complete word, line
46
+ Readline.completion_append_character = append_char
47
+ candidates
48
+ rescue RVC::Util::UserError
49
+ puts
50
+ puts $!.message
51
+ Readline.refresh_line
52
+ end
47
53
  end
48
54
 
49
55
  def self.install
@@ -58,25 +64,44 @@ module Completion
58
64
  end
59
65
 
60
66
  def self.complete word, line
61
- candidates = if line
62
- if line[' ']
63
- child_candidates(word)
64
- else
65
- cmd_candidates(word)
66
- end
67
+ line ||= ''
68
+ first_whitespace_index = line.index(' ')
69
+
70
+ if Readline.respond_to? :point
71
+ do_complete_cmd = !first_whitespace_index || first_whitespace_index >= Readline.point
72
+ do_complete_args = !do_complete_cmd
67
73
  else
68
- child_candidates(word) + cmd_candidates(word)
74
+ do_complete_cmd = true
75
+ do_complete_args = true
76
+ end
77
+
78
+ candidates = []
79
+
80
+ if do_complete_cmd
81
+ candidates.concat cmd_candidates(word)
69
82
  end
70
83
 
71
- candidates += mark_candidates(word)
84
+ if do_complete_args
85
+ mod, cmd, args = Shell.parse_input line
86
+ if mod and mod.completor_for cmd
87
+ candidates.concat RVC::complete_for_cmd(line, word)
88
+ else
89
+ candidates.concat(fs_candidates(word) +
90
+ long_option_candidates(mod, cmd, word))
91
+ end
92
+ end
72
93
 
73
- if candidates.size == 1 and cmd_candidates(word).member?(candidates[0])
74
- append_char = ' '
94
+ if candidates.size == 1
95
+ append_char = candidates[0][1]
75
96
  else
76
- append_char = '/'
97
+ append_char = '?' # should never be displayed
77
98
  end
78
99
 
79
- return append_char, candidates
100
+ return append_char, candidates.map(&:first)
101
+ end
102
+
103
+ def self.fs_candidates word
104
+ child_candidates(word) + mark_candidates(word)
80
105
  end
81
106
 
82
107
  def self.cmd_candidates word
@@ -86,7 +111,18 @@ module Completion
86
111
  m.commands.each { |s| ret << "#{name}.#{s}" }
87
112
  end
88
113
  ret.concat ALIASES.keys
89
- ret.sort.select { |e| e.match(prefix_regex) }
114
+ ret.grep(prefix_regex).sort.
115
+ map { |x| [x, ' '] }
116
+ end
117
+
118
+ def self.long_option_candidates mod, cmd, word
119
+ return [] unless mod and cmd
120
+ parser = mod.opts_for cmd
121
+ return [] unless parser.is_a? RVC::OptionParser
122
+ prefix_regex = /^#{Regexp.escape(word)}/
123
+ parser.specs.map { |k,v| "--#{v[:long]}" }.
124
+ grep(prefix_regex).sort.
125
+ map { |x| [x, ' '] }
90
126
  end
91
127
 
92
128
  # TODO convert to globbing
@@ -101,13 +137,15 @@ module Completion
101
137
  children.
102
138
  select { |k,v| k.gsub(' ', '\\ ') =~ /^#{Regexp.escape(last)}/ }.
103
139
  map { |k,v| (arcs+[k])*'/' }.
104
- map { |x| x.gsub ' ', '\\ ' }
140
+ map { |x| x.gsub ' ', '\\ ' }.
141
+ map { |x| [x, '/'] }
105
142
  end
106
143
 
107
144
  def self.mark_candidates word
108
145
  return [] unless word.empty? || word[0..0] == '~'
109
146
  prefix_regex = /^#{Regexp.escape(word[1..-1] || '')}/
110
- $shell.session.marks.sort.grep(prefix_regex).map { |x| "~#{x}" }
147
+ $shell.session.marks.grep(prefix_regex).sort.
148
+ map { |x| ["~#{x}", '/'] }
111
149
  end
112
150
  end
113
151
  end
@@ -25,8 +25,8 @@ class RbVmomi::VIM::ComputeResource
25
25
  pct_cpu_used = 100.0*stats[:usedCPU]/stats[:totalCPU]
26
26
  pct_mem_used = 100.0*stats[:usedMem]/stats[:totalMem]
27
27
  puts "name: #{name}"
28
- puts "cpu #{stats[:totalCPU]} GHz (#{pct_cpu_used.to_i}% used)"
29
- puts "memory #{stats[:totalMem]} GB (#{pct_mem_used.to_i}% used)"
28
+ puts "cpu: #{stats[:totalCPU]/1e3} GHz (#{pct_cpu_used.to_i}% used)"
29
+ puts "memory: #{stats[:totalMem]/1e3} GB (#{pct_mem_used.to_i}% used)"
30
30
  puts "hosts:"
31
31
  host.each do |h|
32
32
  puts " #{h.name}"
@@ -0,0 +1,108 @@
1
+ # Copyright (c) 2011 VMware, Inc. All Rights Reserved.
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
20
+
21
+ include RVC::Util
22
+
23
+ class RbVmomi::VIM::DVPortSetting
24
+ def dump_config vds, prefix, show_inheritance = true, show_uplinkinfo = true
25
+ @show_inheritance = show_inheritance
26
+
27
+ # map network respool to human-readable name
28
+ if self.networkResourcePoolKey
29
+ poolName = translate_respool vds, self.networkResourcePoolKey, show_inheritance
30
+ end
31
+ puts_policy "#{prefix}blocked:", self.blocked
32
+ puts_policy("#{prefix}vlan:", self.vlan, "", nil) { |v| translate_vlan v }
33
+ if self.networkResourcePoolKey
34
+ puts "#{prefix}network resource pool: #{poolName}"
35
+ end
36
+ p = self.inShapingPolicy
37
+ if p
38
+ puts "#{prefix}Rx Shaper: "
39
+ puts_policy "#{prefix} enabled:", p.enabled
40
+ avg_bw = p.averageBandwidth
41
+ puts_policy("#{prefix} average bw:", avg_bw, "b/sec"){|v|metric(v)}
42
+ puts_policy("#{prefix} peak bw:", p.peakBandwidth, "b/sec"){|v|metric(v)}
43
+ puts_policy("#{prefix} burst size:", p.burstSize, "B"){|v|metric(v)}
44
+ end
45
+ p = self.outShapingPolicy
46
+ if p
47
+ puts "#{prefix}Tx Shaper:"
48
+ puts_policy "#{prefix} enabled:", p.enabled
49
+ avg_bw = p.averageBandwidth
50
+ puts_policy("#{prefix} average bw:", avg_bw, "b/sec") { |v| metric(v) }
51
+ puts_policy("#{prefix} peak bw:", p.peakBandwidth, "b/sec") {|v| metric(v)}
52
+ puts_policy("#{prefix} burst size:", p.burstSize, "B") {|v| metric(v)}
53
+ end
54
+ if show_uplinkinfo
55
+ p = self.uplinkTeamingPolicy
56
+ if p
57
+ puts "#{prefix}Uplink Teaming Policy:"
58
+ puts_policy "#{prefix} policy:", p.policy #XXX map the strings values
59
+ puts_policy "#{prefix} reverse policy:", p.reversePolicy
60
+ puts_policy "#{prefix} notify switches:", p.notifySwitches
61
+ puts_policy "#{prefix} rolling order:", p.rollingOrder
62
+ c = p.failureCriteria
63
+ if c
64
+ puts "#{prefix} Failure Criteria: "
65
+ puts_policy "#{prefix} check speed:", c.checkSpeed
66
+ puts_policy("#{prefix} speed:", c.speed, "Mb/sec")# { |v| metric(v) }
67
+ puts_policy "#{prefix} check duplex:", c.checkDuplex
68
+ puts_policy "#{prefix} full duplex:", c.fullDuplex
69
+ puts_policy "#{prefix} check error percentage:", c.checkErrorPercent
70
+ puts_policy "#{prefix} max error percentage:", c.percentage, "%"
71
+ puts_policy "#{prefix} check beacon:", c.checkBeacon
72
+ end
73
+ o = p.uplinkPortOrder
74
+ if o
75
+ puts "#{prefix} Uplink Port Order:"
76
+ puts_policy("#{prefix} active:", o,"", :activeUplinkPort){|v|v.join(',')}
77
+ puts_policy("#{prefix} standby:",o,"",:standbyUplinkPort){|v|v.join(',')}
78
+ end
79
+ end
80
+ end
81
+ p = self.securityPolicy
82
+ if p
83
+ puts "#{prefix}Security:"
84
+ puts_policy "#{prefix} allow promiscuous mode:", p.allowPromiscuous
85
+ puts_policy "#{prefix} allow mac changes:", p.macChanges
86
+ puts_policy "#{prefix} allow forged transmits:", p.forgedTransmits
87
+ puts_policy "#{prefix}enable ipfix monitoring:", self.ipfixEnabled
88
+ puts_policy "#{prefix}forward all tx to uplink:", self.txUplink
89
+ end
90
+ end
91
+
92
+ def puts_policy prefix, policy, suffix = "", prop = :value, &b
93
+ b ||= lambda { |v| v }
94
+ if policy
95
+ if prop != nil
96
+ v = policy.send(prop)
97
+ else
98
+ v = policy
99
+ end
100
+ print "#{prefix} #{b.call(v)}#{suffix}"
101
+ if @show_inheritance and policy.inherited == false
102
+ puts "*"
103
+ else
104
+ puts ""
105
+ end
106
+ end
107
+ end
108
+ end
@@ -27,10 +27,25 @@ class RbVmomi::VIM::Datacenter
27
27
  vmFolder, datastoreFolder, networkFolder, hostFolder =
28
28
  collect *%w(vmFolder datastoreFolder networkFolder hostFolder)
29
29
  {
30
- 'vm' => vmFolder,
31
- 'datastore' => datastoreFolder,
32
- 'network' => networkFolder,
33
- 'host' => hostFolder,
30
+ 'vms' => vmFolder,
31
+ 'datastores' => datastoreFolder,
32
+ 'networks' => networkFolder,
33
+ 'computers' => hostFolder,
34
34
  }
35
35
  end
36
+
37
+ # For compatibility with previous RVC versions
38
+ def traverse_one arc
39
+ children = self.children
40
+ return children[arc] if children.member? arc
41
+ if arc == 'vm' then return vmFolder
42
+ elsif arc == 'datastore' then return datastoreFolder
43
+ elsif arc == 'network' then return networkFolder
44
+ elsif arc == 'host' then return hostFolder
45
+ end
46
+ end
47
+
48
+ def self.folder?
49
+ true
50
+ end
36
51
  end
@@ -23,10 +23,15 @@ class RbVmomi::VIM::Datastore
23
23
  s, info, = collect :summary, :info
24
24
  puts "type: #{s.type}"
25
25
  puts "url: #{s.accessible ? s.url : '<inaccessible>'}"
26
- puts "uuid: #{info.vmfs.uuid}"
27
26
  puts "multipleHostAccess: #{s.multipleHostAccess}"
28
27
  puts "capacity: %0.2fGB" % (s.capacity.to_f/10**9)
29
28
  puts "free space: %0.2fGB" % (s.freeSpace.to_f/10**9)
29
+ case info
30
+ when VIM::VmfsDatastoreInfo
31
+ puts "uuid: #{info.vmfs.uuid}"
32
+ when VIM::NasDatastoreInfo
33
+ puts "location: #{info.nas.remoteHost}:#{info.nas.remotePath}"
34
+ end
30
35
  end
31
36
 
32
37
  def self.ls_properties
@@ -0,0 +1,146 @@
1
+ # Copyright (c) 2011 VMware, Inc. All Rights Reserved.
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
20
+
21
+ class RbVmomi::VIM::DistributedVirtualPort
22
+ include RVC::InventoryObject
23
+
24
+ field 'ip' do
25
+ summary "The guest tools reported IP address."
26
+ property 'connectee'
27
+ block do |c|
28
+ ip = nil
29
+ vm = c.connectedEntity
30
+ if vm.is_a? VIM::VirtualMachine
31
+ info = vm.guest.net.reject { |info|
32
+ info.deviceConfigId.to_s != c.nicKey
33
+ }.first
34
+ if info != nil
35
+ #XXX deal with multiple ips?
36
+ ip = info.ipAddress[0]
37
+ end
38
+ end
39
+ ip
40
+ end
41
+ end
42
+
43
+ field 'mac' do
44
+ summary "The guest tools reported IP address."
45
+ property 'connectee'
46
+ block do |c|
47
+ mac = nil
48
+ vm = c.connectedEntity
49
+ if vm.is_a? VIM::VirtualMachine
50
+ info = vm.config.hardware.device.reject { |device|
51
+ !(device.class < VIM::VirtualEthernetCard &&
52
+ device.key.to_s == c.nicKey)
53
+ }.first
54
+ if info != nil
55
+ mac = info.macAddress
56
+ end
57
+ end
58
+ mac
59
+ end
60
+ end
61
+
62
+ def display_info
63
+ # if possible, get info about the connected VM
64
+ vm_name = ""
65
+ mac = ""
66
+ ip = ""
67
+ if self.connectee
68
+ vm = self.connectee.connectedEntity
69
+ if vm.class == VIM::VirtualMachine
70
+ vm_name = vm.name
71
+ mac = vm.config.hardware.device.reject { |device|
72
+ !(device.class < VIM::VirtualEthernetCard &&
73
+ device.key.to_s == self.connectee.nicKey)
74
+ }.first.macAddress
75
+ nicinfo = vm.guest.net.reject { |info|
76
+ info.deviceConfigId.to_s != self.connectee.nicKey.to_s
77
+ }.first
78
+
79
+ if nicinfo != nil
80
+ ip = nicinfo.ipAddress
81
+ if nicinfo.macAddress != nil and nicinfo.macAddress != ""
82
+ mac = nicinfo.macAddress
83
+ end
84
+ end
85
+ end
86
+ end
87
+
88
+ # if possible, get info about the port configuration
89
+ poolName = "-"
90
+ vlan = "-"
91
+ link_up = false
92
+ if self.state.runtimeInfo
93
+ vds = self.rvc_parent.config.distributedVirtualSwitch
94
+ poolName = translate_respool vds, self.config.setting.networkResourcePoolKey
95
+ vlan = translate_vlan self.state.runtimeInfo.vlanIds
96
+ link_up = self.state.runtimeInfo.linkUp
97
+ end
98
+
99
+
100
+ #puts "name: #{self.config.name}"
101
+ puts "link up: #{link_up}"
102
+ #puts "vds: #{vds.name}"
103
+ #puts "portgroup: #{self.rvc_parent.name}"
104
+ #puts "vlan: #{vlan}"
105
+ #puts "network resource pool: #{poolName}"
106
+ puts "name: #{self.config.name}"
107
+ puts "description: #{self.config.description}"
108
+ puts "host: #{if self.proxyHost then self.proxyHost.name end}"
109
+ puts "vm: #{vm_name}"
110
+ puts "mac: #{mac}"
111
+ puts "ip: #{ip}"
112
+ puts "Port Settings:"
113
+ #XXX scope?
114
+ self.config.setting.dump_config vds, " ", true, false
115
+ if self.state
116
+ if self.state.stats
117
+ puts "Statistics:"
118
+ stats = self.state.stats
119
+ # normally, i would explicitly write this out, but in this case
120
+ # the stats are pretty self explanatory, and require pretty much
121
+ # no formatting, so we just procedurally generate them
122
+ stats.class.full_props_desc.map { |stat|
123
+ stat = stat['name']
124
+ num = stats.send(stat)
125
+ # skip uninteresting properties
126
+ if !num.is_a?(Integer) then next end
127
+ # un-camelcase the name of the stat
128
+ stat = stat.gsub(/[A-Z]/) { |p| ' ' + p.downcase}
129
+ puts " #{stat}: #{num}"
130
+ }
131
+ end
132
+ end
133
+ end
134
+
135
+ def children
136
+ {
137
+ 'vm' => self.connectee.connectedEntity,
138
+ 'host' => self.proxyHost
139
+ }
140
+ end
141
+
142
+ def invalidate vds
143
+ port = vds.FetchDVPorts(:criteria => { :portKey => [self.key] }).first
144
+ @props = port.props
145
+ end
146
+ end