rvc 1.5.0 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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