rvc 1.0.3 → 1.1.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.
data/Rakefile CHANGED
@@ -7,7 +7,7 @@ begin
7
7
  gem.email = "rlane@vmware.com"
8
8
  #gem.homepage = ""
9
9
  gem.authors = ["Rich Lane"]
10
- gem.add_dependency 'rbvmomi', '>= 1.2.2'
10
+ gem.add_dependency 'rbvmomi', '>= 1.2.3'
11
11
  gem.add_dependency 'trollop', '>= 1.16.2'
12
12
  gem.add_dependency 'backports', '>= 1.18.2'
13
13
  #gem.add_dependency 'ffi', '>= 1.0.7'
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.0.3
1
+ 1.1.0
@@ -21,6 +21,7 @@
21
21
  class RbVmomi::VIM::VirtualMachine
22
22
  def display_info
23
23
  config, runtime, guest = collect :config, :runtime, :guest
24
+ err "Information currently unavailable" unless config and runtime and guest
24
25
 
25
26
  puts "name: #{config.name}"
26
27
  puts "note: #{config.annotation}" if config.annotation and !config.annotation.empty?
@@ -27,3 +27,68 @@ end
27
27
  def reboot hosts, opts
28
28
  tasks hosts, :RebootHost, :force => opts[:force]
29
29
  end
30
+
31
+
32
+ opts :evacuate do
33
+ summary "vMotion all VMs away from this host (experimental)"
34
+ arg :src, nil, :lookup => VIM::HostSystem
35
+ arg :dst, nil, :lookup => VIM::ComputeResource, :multi => true
36
+ opt :num, "Maximum concurrent vMotions", :default => 4
37
+ end
38
+
39
+ def evacuate src, dsts, opts
40
+ vim = src._connection
41
+ vms = src.vm
42
+ dst_hosts = dsts.map(&:host).flatten
43
+ checks = ['cpu', 'software']
44
+
45
+ dst_hosts.reject! { |host| host == src ||
46
+ host.runtime.connectionState != 'connected' ||
47
+ host.runtime.inMaintenanceMode }
48
+
49
+ candidates = {}
50
+ vms.each do |vm|
51
+ required_datastores = vm.datastore
52
+ result = vim.serviceInstance.QueryVMotionCompatibility(:vm => vm,
53
+ :host => dst_hosts,
54
+ :compatibility => checks)
55
+ result.reject! { |x| x.compatibility != checks ||
56
+ x.host.datastore & required_datastores != required_datastores }
57
+ candidates[vm] = result.map { |x| x.host }
58
+ end
59
+
60
+ if candidates.any? { |vm,hosts| hosts.empty? }
61
+ puts "The following VMs have no compatible vMotion destination:"
62
+ candidates.select { |vm,hosts| hosts.empty? }.each { |vm,hosts| puts " #{vm.name}" }
63
+ return
64
+ end
65
+
66
+ tasks = candidates.map do |vm,hosts|
67
+ host = hosts[rand(hosts.size)]
68
+ vm.MigrateVM_Task(:host => host, :priority => :defaultPriority)
69
+ end
70
+
71
+ progress tasks
72
+ end
73
+
74
+
75
+ opts :enter_maintenance_mode do
76
+ summary "Put hosts into maintenance mode"
77
+ arg :host, nil, :lookup => VIM::HostSystem, :multi => true
78
+ opt :timeout, "Timeout", :default => 0
79
+ end
80
+
81
+ def enter_maintenance_mode hosts, opts
82
+ tasks hosts, :EnterMaintenanceMode, :timeout => opts[:timeout]
83
+ end
84
+
85
+
86
+ opts :exit_maintenance_mode do
87
+ summary "Take hosts out of maintenance mode"
88
+ arg :host, nil, :lookup => VIM::HostSystem, :multi => true
89
+ opt :timeout, "Timeout", :default => 0
90
+ end
91
+
92
+ def exit_maintenance_mode hosts, opts
93
+ tasks hosts, :ExitMaintenanceMode, :timeout => opts[:timeout]
94
+ end
@@ -538,16 +538,25 @@ opts :clone do
538
538
  arg :dst, "Path to new VM"
539
539
  opt :pool, "Resource pool", :short => 'p', :type => :string, :lookup => VIM::ResourcePool
540
540
  opt :host, "Host", :short => 'h', :type => :string, :lookup => VIM::HostSystem
541
- opt :template, "Create a template"
541
+ opt :template, "Create a template", :short => 't'
542
+ opt :linked, "Create a linked clone", :short => 'l'
542
543
  opt :powerOn, "Power on VM after clone"
543
544
  end
544
545
 
545
546
  def clone src, dst, opts
546
547
  folder = lookup! File.dirname(dst), VIM::Folder
548
+ diskMoveType = nil
549
+
550
+ if opts[:linked]
551
+ deltaize_disks src
552
+ diskMoveType = :moveChildMostDiskBacking
553
+ end
554
+
547
555
  task = src.CloneVM_Task(:folder => folder,
548
556
  :name => File.basename(dst),
549
557
  :spec => {
550
558
  :location => {
559
+ :diskMoveType => diskMoveType,
551
560
  :host => opts[:host],
552
561
  :pool => opts[:pool],
553
562
  },
@@ -558,6 +567,27 @@ def clone src, dst, opts
558
567
  end
559
568
 
560
569
 
570
+ def deltaize_disks vm
571
+ real_disks = vm.config.hardware.device.grep(VIM::VirtualDisk).select { |x| x.backing.parent == nil }
572
+ unless real_disks.empty?
573
+ puts "Reconfiguring source VM to use delta disks..."
574
+ deviceChange = []
575
+ real_disks.each do |disk|
576
+ deviceChange << { :operation => :remove, :device => disk }
577
+ deviceChange << {
578
+ :operation => :add,
579
+ :fileOperation => :create,
580
+ :device => disk.dup.tap { |x|
581
+ x.backing = x.backing.dup
582
+ x.backing.fileName = "[#{disk.backing.datastore.name}]"
583
+ x.backing.parent = disk.backing
584
+ }
585
+ }
586
+ end
587
+ progress [vm.ReconfigVM_Task(:spec => { :deviceChange => deviceChange })]
588
+ end
589
+ end
590
+
561
591
  def find_vmx_files ds
562
592
  datastorePath = "[#{ds.name}] /"
563
593
  searchSpec = {
@@ -22,7 +22,11 @@ require 'tmpdir'
22
22
 
23
23
  VMRC_NAME = "vmware-vmrc-linux-x86-3.0.0"
24
24
  VMRC_PKGVER = 1
25
- VMRC_URL = "https://github.com/downloads/vmware/rvc/#{VMRC_NAME}.#{VMRC_PKGVER}.tar.bz2"
25
+ VMRC_BASENAME = "#{VMRC_NAME}.#{VMRC_PKGVER}.tar.bz2"
26
+ VMRC_URL = "http://cloud.github.com/downloads/vmware/rvc/#{VMRC_BASENAME}"
27
+ VMRC_SHA256 = "cda9ba0b0078aee9a7b9704d720ef4c7d74ae2028efb71815d0eb91a5de75921"
28
+
29
+ CURL = ENV['CURL'] || 'curl'
26
30
 
27
31
  def find_local_vmrc
28
32
  path = File.join(Dir.tmpdir, VMRC_NAME, 'plugins', 'vmware-vmrc')
@@ -51,8 +55,10 @@ def view vms
51
55
  host = vm._connection._host
52
56
  fork do
53
57
  ENV['https_proxy'] = ENV['HTTPS_PROXY'] = ''
54
- $stderr.reopen("#{ENV['HOME']||'.'}/.rvc-vmrc.log", "w")
58
+ $stderr.reopen("#{ENV['HOME']||'.'}/.rvc-vmrc.log", "a")
55
59
  $stderr.puts Time.now
60
+ $stderr.puts "Using VMRC #{vmrc}"
61
+ $stderr.flush
56
62
  Process.setpgrp
57
63
  exec vmrc, '-M', moref,
58
64
  '-h', host,
@@ -66,7 +72,18 @@ opts :install do
66
72
  end
67
73
 
68
74
  def install
75
+ system "which #{CURL} > /dev/null" or err "curl not found"
76
+ system "which sha256sum > /dev/null" or err "sha256sum not found"
77
+ puts "Downloading VMRC..."
78
+ dir = Dir.mktmpdir
79
+ vmrc_file = "#{dir}/#{VMRC_BASENAME}"
80
+ checksum_file = "#{dir}/sha256sums"
81
+ system "#{CURL} -L #{VMRC_URL} -o #{vmrc_file}" or err "download failed"
82
+ puts "Checking integrity..."
83
+ File.open(checksum_file, 'w') { |io| io.puts "#{VMRC_SHA256} *#{vmrc_file}" }
84
+ system "sha256sum -c #{checksum_file}" or err "integrity check failed"
69
85
  puts "Installing VMRC..."
70
- system "curl -L #{VMRC_URL} | tar -xj -C #{Dir.tmpdir}" or err("VMRC installation failed")
86
+ system "tar -xj -f #{vmrc_file} -C #{Dir.tmpdir}" or err("VMRC installation failed")
71
87
  puts "VMRC was installed successfully."
88
+ FileUtils.rm_r dir
72
89
  end
metadata CHANGED
@@ -1,13 +1,8 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rvc
3
3
  version: !ruby/object:Gem::Version
4
- hash: 17
5
4
  prerelease:
6
- segments:
7
- - 1
8
- - 0
9
- - 3
10
- version: 1.0.3
5
+ version: 1.1.0
11
6
  platform: ruby
12
7
  authors:
13
8
  - Rich Lane
@@ -15,7 +10,7 @@ autorequire:
15
10
  bindir: bin
16
11
  cert_chain: []
17
12
 
18
- date: 2011-03-28 00:00:00 -07:00
13
+ date: 2011-04-05 00:00:00 -07:00
19
14
  default_executable: rvc
20
15
  dependencies:
21
16
  - !ruby/object:Gem::Dependency
@@ -26,12 +21,7 @@ dependencies:
26
21
  requirements:
27
22
  - - ">="
28
23
  - !ruby/object:Gem::Version
29
- hash: 27
30
- segments:
31
- - 1
32
- - 2
33
- - 2
34
- version: 1.2.2
24
+ version: 1.2.3
35
25
  type: :runtime
36
26
  version_requirements: *id001
37
27
  - !ruby/object:Gem::Dependency
@@ -42,11 +32,6 @@ dependencies:
42
32
  requirements:
43
33
  - - ">="
44
34
  - !ruby/object:Gem::Version
45
- hash: 83
46
- segments:
47
- - 1
48
- - 16
49
- - 2
50
35
  version: 1.16.2
51
36
  type: :runtime
52
37
  version_requirements: *id002
@@ -58,11 +43,6 @@ dependencies:
58
43
  requirements:
59
44
  - - ">="
60
45
  - !ruby/object:Gem::Version
61
- hash: 91
62
- segments:
63
- - 1
64
- - 18
65
- - 2
66
46
  version: 1.18.2
67
47
  type: :runtime
68
48
  version_requirements: *id003
@@ -117,8 +97,6 @@ files:
117
97
  - test/inventory_fixtures.rb
118
98
  - test/test_fs.rb
119
99
  - test/test_parse_path.rb
120
- - test/_test_completion.rb
121
- - test/_test_option_parser.rb
122
100
  has_rdoc: true
123
101
  homepage:
124
102
  licenses: []
@@ -133,29 +111,21 @@ required_ruby_version: !ruby/object:Gem::Requirement
133
111
  requirements:
134
112
  - - ">="
135
113
  - !ruby/object:Gem::Version
136
- hash: 3
137
- segments:
138
- - 0
139
114
  version: "0"
140
115
  required_rubygems_version: !ruby/object:Gem::Requirement
141
116
  none: false
142
117
  requirements:
143
118
  - - ">="
144
119
  - !ruby/object:Gem::Version
145
- hash: 3
146
- segments:
147
- - 0
148
120
  version: "0"
149
121
  requirements: []
150
122
 
151
123
  rubyforge_project:
152
- rubygems_version: 1.4.2
124
+ rubygems_version: 1.6.2
153
125
  signing_key:
154
126
  specification_version: 3
155
127
  summary: vSphere console UI
156
128
  test_files:
157
- - test/_test_completion.rb
158
- - test/_test_option_parser.rb
159
129
  - test/inventory_fixtures.rb
160
130
  - test/test_fs.rb
161
131
  - test/test_parse_path.rb
@@ -1,27 +0,0 @@
1
- require 'test/unit'
2
- require 'rvc'
3
- require 'inventory_fixtures'
4
-
5
- class CompletionTest < Test::Unit::TestCase
6
- NodeBaz = FixtureNode.new
7
- NodeBar = FixtureNode.new
8
- NodeFoo = FixtureNode.new('bar' => NodeBar, 'baz' => NodeBaz)
9
- Root = FixtureNode.new('foo' => NodeFoo)
10
-
11
- def check word, expected
12
- got = RVC::Completion::Completor[word]
13
- assert_equal expected, got
14
- end
15
-
16
- def setup
17
- @context = RVC::Context.new Root
18
- end
19
-
20
- def teardown
21
- @context = nil
22
- end
23
-
24
- def test_simple
25
- check
26
- end
27
- end
@@ -1,6 +0,0 @@
1
- require 'test/unit'
2
- require 'rvc'
3
- require 'inventory_fixtures'
4
-
5
- class OptionParserTest < Test::Unit::TestCase
6
- end