bosh_vsphere_cpi 0.4.9 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -13,8 +13,9 @@ module VSphereCloud
13
13
 
14
14
  def initialize(host, options = {})
15
15
  http_client = HTTPClient.new
16
- if options["soap_log"]
17
- log_file = File.open(options["soap_log"], "w")
16
+ log_path = options["soap_log"]
17
+ if log_path
18
+ log_file = File.open(log_path, "w")
18
19
  log_file.sync = true
19
20
  http_client.debug_dev = log_file
20
21
  end
@@ -1,7 +1,18 @@
1
+ require "rubygems"
2
+ require "membrane"
1
3
  require "ruby_vim_sdk"
4
+
2
5
  require "cloud/vsphere/client"
6
+ require "cloud/vsphere/config"
3
7
  require "cloud/vsphere/lease_updater"
4
8
  require "cloud/vsphere/resources"
9
+ require "cloud/vsphere/resources/cluster"
10
+ require "cloud/vsphere/resources/datacenter"
11
+ require "cloud/vsphere/resources/datastore"
12
+ require "cloud/vsphere/resources/folder"
13
+ require "cloud/vsphere/resources/resource_pool"
14
+ require "cloud/vsphere/resources/scorer"
15
+ require "cloud/vsphere/resources/util"
5
16
  require "cloud/vsphere/models/disk"
6
17
 
7
18
  module VSphereCloud
@@ -14,37 +25,17 @@ module VSphereCloud
14
25
  attr_accessor :client
15
26
 
16
27
  def initialize(options)
17
- @vcenters = options["vcenters"]
18
- raise "Invalid number of VCenters" unless @vcenters.size == 1
19
- @vcenter = @vcenters[0]
20
-
21
- @logger = Bosh::Clouds::Config.logger
22
-
23
- @agent_properties = options["agent"]
24
-
25
- @client = Client.new("https://#{@vcenter["host"]}/sdk/vimService", options)
26
- @client.login(@vcenter["user"], @vcenter["password"], "en")
27
-
28
- @rest_client = HTTPClient.new
29
- @rest_client.send_timeout = 14400 # 4 hours
30
- @rest_client.ssl_config.verify_mode = OpenSSL::SSL::VERIFY_NONE
31
-
32
- # HACK: read the session from the SOAP client so we don't leak sessions when using the REST client
33
- cookie_str = @client.stub.cookie
34
- @rest_client.cookie_manager.parse(cookie_str, URI.parse("https://#{@vcenter["host"]}"))
35
-
36
- mem_ratio = 1.0
37
- if options["mem_overcommit_ratio"]
38
- mem_ratio = options["mem_overcommit_ratio"].to_f
39
- end
40
-
41
- @resources = Resources.new(@client, @vcenter, mem_ratio)
28
+ Config.configure(options)
42
29
 
43
- # HACK: provide a way to copy the disks instead of moving them.
44
- # Used for extra data protection until we have proper backups
45
- @copy_disks = options["copy_disks"] || false
30
+ @logger = Config.logger
31
+ @client = Config.client
32
+ @rest_client = Config.rest_client
33
+ @resources = Resources.new
46
34
 
35
+ # Global lock
47
36
  @lock = Mutex.new
37
+
38
+ # Resource locks
48
39
  @locks = {}
49
40
  @locks_mutex = Mutex.new
50
41
 
@@ -76,12 +67,13 @@ module VSphereCloud
76
67
  @logger.info("Generated name: #{name}")
77
68
 
78
69
  # TODO: make stemcell friendly version of the calls below
79
- cluster, datastore = @resources.get_resources
70
+ stemcell_size = File.size(image) / (1024 * 1024)
71
+ cluster, datastore = @resources.place(0, stemcell_size, [])
80
72
  @logger.info("Deploying to: #{cluster.mob} / #{datastore.mob}")
81
73
 
82
- import_spec_result = import_ovf(name, ovf_file, cluster.resource_pool, datastore.mob)
83
- lease = obtain_nfc_lease(cluster.resource_pool, import_spec_result.import_spec,
84
- cluster.datacenter.template_folder)
74
+ import_spec_result = import_ovf(name, ovf_file, cluster.resource_pool.mob, datastore.mob)
75
+ lease = obtain_nfc_lease(cluster.resource_pool.mob, import_spec_result.import_spec,
76
+ cluster.datacenter.template_folder.mob)
85
77
  @logger.info("Waiting for NFC lease")
86
78
  state = wait_for_nfc_lease(lease)
87
79
  raise "Could not acquire HTTP NFC lease" unless state == Vim::HttpNfcLease::State::READY
@@ -115,7 +107,7 @@ module VSphereCloud
115
107
  Bosh::ThreadPool.new(:max_threads => 32, :logger => @logger).wrap do |pool|
116
108
  @resources.datacenters.each_value do |datacenter|
117
109
  @logger.info("Looking for stemcell replicas in: #{datacenter.name}")
118
- templates = client.get_property(datacenter.template_folder, Vim::Folder, "childEntity", :ensure_all => true)
110
+ templates = client.get_property(datacenter.template_folder.mob, Vim::Folder, "childEntity", :ensure_all => true)
119
111
  template_properties = client.get_properties(templates, Vim::VirtualMachine, ["name"])
120
112
  template_properties.each_value do |properties|
121
113
  template_name = properties["name"].gsub("%2f", "/")
@@ -133,29 +125,53 @@ module VSphereCloud
133
125
  end
134
126
  end
135
127
 
136
- def disk_spec(vm_disk, persistent_disks)
128
+ def disk_spec(persistent_disks)
137
129
  disks = []
138
- disks << {"size" => vm_disk, "persistent" => false}
139
-
140
- persistent_disks ||= {}
141
- persistent_disks.each do |disk_id|
142
- disk = Models::Disk[disk_id]
143
- disks << {"size" => disk.size, "persistent" => true, "datacenter" => disk.datacenter, "datastore" => disk.datastore}
130
+ if persistent_disks
131
+ persistent_disks.each do |disk_id|
132
+ disk = Models::Disk[disk_id]
133
+ disks << {
134
+ :size => disk.size,
135
+ :dc_name => disk.datacenter,
136
+ :ds_name => disk.datastore
137
+ }
138
+ end
144
139
  end
145
140
  disks
146
141
  end
147
142
 
143
+ def stemcell_vm(name)
144
+ dc = @resources.datacenters.values.first
145
+ client.find_by_inventory_path(
146
+ [dc.name, "vm", dc.template_folder.name, name])
147
+ end
148
+
148
149
  def create_vm(agent_id, stemcell, resource_pool, networks, disk_locality = nil, environment = nil)
149
150
  with_thread_name("create_vm(#{agent_id}, ...)") do
150
151
  memory = resource_pool["ram"]
151
152
  disk = resource_pool["disk"]
152
153
  cpu = resource_pool["cpu"]
153
154
 
154
- disks = disk_spec(disk, disk_locality)
155
- cluster, datastore = @resources.get_resources(memory, disks)
155
+ # Make sure number of cores is a power of 2. kb.vmware.com/kb/2003484
156
+ if cpu & cpu - 1 != 0
157
+ raise "Number of vCPUs: #{cpu} is not a power of 2."
158
+ end
159
+
160
+ stemcell_vm = stemcell_vm(stemcell)
161
+ raise "Could not find stemcell: #{stemcell}" if stemcell_vm.nil?
162
+
163
+ stemcell_size = client.get_property(
164
+ stemcell_vm, Vim::VirtualMachine, "summary.storage.committed",
165
+ :ensure_all => true)
166
+ stemcell_size /= 1024 * 1024
167
+
168
+ disks = disk_spec(disk_locality)
169
+ # need to include swap and linked clone log
170
+ ephemeral = disk + memory + stemcell_size
171
+ cluster, datastore = @resources.place(memory, ephemeral, disks)
156
172
 
157
173
  name = "vm-#{generate_unique_name}"
158
- @logger.info("Creating vm:: #{name} on #{cluster.mob} stored in #{datastore.mob}")
174
+ @logger.info("Creating vm: #{name} on #{cluster.mob} stored in #{datastore.mob}")
159
175
 
160
176
  replicated_stemcell_vm = replicate_stemcell(cluster, datastore, stemcell)
161
177
  replicated_stemcell_properties = client.get_properties(replicated_stemcell_vm, Vim::VirtualMachine,
@@ -194,7 +210,7 @@ module VSphereCloud
194
210
 
195
211
  @logger.info("Cloning vm: #{replicated_stemcell_vm} to #{name}")
196
212
 
197
- task = clone_vm(replicated_stemcell_vm, name, cluster.datacenter.vm_folder, cluster.resource_pool,
213
+ task = clone_vm(replicated_stemcell_vm, name, cluster.datacenter.vm_folder.mob, cluster.resource_pool.mob,
198
214
  :datastore => datastore.mob, :linked => true, :snapshot => snapshot.current_snapshot,
199
215
  :config => config)
200
216
  vm = client.wait_for_task(task)
@@ -421,7 +437,8 @@ module VSphereCloud
421
437
 
422
438
  def find_persistent_datastore(datacenter_name, host_info, disk_size)
423
439
  # Find datastore
424
- datastore = @resources.find_persistent_datastore(datacenter_name, host_info["cluster"], disk_size)
440
+ datastore = @resources.place_persistent_datastore(
441
+ datacenter_name, host_info["cluster"], disk_size)
425
442
 
426
443
  if datastore.nil?
427
444
  raise Bosh::Clouds::NoDiskSpace.new(true), "Not enough persistent space on cluster #{host_info["cluster"]}, #{disk_size}"
@@ -447,21 +464,18 @@ module VSphereCloud
447
464
 
448
465
  vm_properties = client.get_properties(vm, Vim::VirtualMachine, "config.hardware.device", :ensure_all => true)
449
466
  host_info = get_vm_host_info(vm)
450
- persistent_datastore = nil
451
467
 
452
468
  create_disk = false
453
469
  if disk.path
454
470
  if disk.datacenter == datacenter_name &&
455
471
  @resources.validate_persistent_datastore(datacenter_name, disk.datastore) &&
456
472
  host_info["datastores"].include?(disk.datastore)
457
- # Looks like we have a valid persistent data store
458
-
459
473
  @logger.info("Disk already in the right datastore #{datacenter_name} #{disk.datastore}")
460
- persistent_datastore = @resources.get_persistent_datastore(datacenter_name, host_info["cluster"],
461
- disk.datastore)
474
+ persistent_datastore = @resources.persistent_datastore(
475
+ datacenter_name, host_info["cluster"], disk.datastore)
476
+ @logger.debug("Datastore: #{persistent_datastore}")
462
477
  else
463
478
  @logger.info("Disk needs to move from #{datacenter_name} #{disk.datastore}")
464
-
465
479
  # Find the destination datastore
466
480
  persistent_datastore = find_persistent_datastore(datacenter_name, host_info, disk.size)
467
481
 
@@ -473,7 +487,7 @@ module VSphereCloud
473
487
  destination_path = "[#{persistent_datastore.name}] #{datacenter_disk_path}/#{disk.id}"
474
488
  @logger.info("Moving #{disk.datacenter}/#{source_path} to #{datacenter_name}/#{destination_path}")
475
489
 
476
- if @copy_disks
490
+ if Config.copy_disks
477
491
  client.copy_disk(source_datacenter, source_path, datacenter, destination_path)
478
492
  @logger.info("Copied disk successfully")
479
493
  else
@@ -576,7 +590,7 @@ module VSphereCloud
576
590
  disk = Models::Disk.new
577
591
  disk.size = size
578
592
  disk.save
579
- @logger.info("Created disk: #{disk.pretty_inspect}")
593
+ @logger.info("Created disk: #{disk.inspect}")
580
594
  disk.id.to_s
581
595
  end
582
596
  end
@@ -605,23 +619,27 @@ module VSphereCloud
605
619
  end
606
620
 
607
621
  def get_vm_by_cid(vm_cid)
608
- # TODO: fix when we go to multiple DCs
609
- datacenter = @resources.datacenters.values.first
610
- vm = client.find_by_inventory_path([datacenter.name, "vm", datacenter.vm_folder_name, vm_cid])
611
- raise Bosh::Clouds::VMNotFound, "VM `#{vm_cid}' not found" if vm.nil?
612
- vm
622
+ @resources.datacenters.each_value do |datacenter|
623
+ vm = client.find_by_inventory_path(
624
+ [datacenter.name, "vm", datacenter.vm_folder.name, vm_cid])
625
+ unless vm.nil?
626
+ return vm
627
+ end
628
+ end
629
+ raise Bosh::Clouds::VMNotFound, "VM `#{vm_cid}' not found"
613
630
  end
614
631
 
615
632
  def replicate_stemcell(cluster, datastore, stemcell)
633
+ # TODO: support more than a single datacenter
616
634
  stemcell_vm = client.find_by_inventory_path([cluster.datacenter.name, "vm",
617
- cluster.datacenter.template_folder_name, stemcell])
635
+ cluster.datacenter.template_folder.name, stemcell])
618
636
  raise "Could not find stemcell: #{stemcell}" if stemcell_vm.nil?
619
637
  stemcell_datastore = client.get_property(stemcell_vm, Vim::VirtualMachine, "datastore", :ensure_all => true)
620
638
 
621
639
  if stemcell_datastore != datastore.mob
622
640
  @logger.info("Stemcell lives on a different datastore, looking for a local copy of: #{stemcell}.")
623
641
  local_stemcell_name = "#{stemcell} / #{datastore.mob.__mo_id__}"
624
- local_stemcell_path = [cluster.datacenter.name, "vm", cluster.datacenter.template_folder_name,
642
+ local_stemcell_path = [cluster.datacenter.name, "vm", cluster.datacenter.template_folder.name,
625
643
  local_stemcell_name]
626
644
  replicated_stemcell_vm = client.find_by_inventory_path(local_stemcell_path)
627
645
 
@@ -639,8 +657,8 @@ module VSphereCloud
639
657
  replicated_stemcell_vm = client.find_by_inventory_path(local_stemcell_path)
640
658
  if replicated_stemcell_vm.nil?
641
659
  @logger.info("Replicating #{stemcell} (#{stemcell_vm}) to #{local_stemcell_name}")
642
- task = clone_vm(stemcell_vm, local_stemcell_name, cluster.datacenter.template_folder,
643
- cluster.resource_pool, :datastore => datastore.mob)
660
+ task = clone_vm(stemcell_vm, local_stemcell_name, cluster.datacenter.template_folder.mob,
661
+ cluster.resource_pool.mob, :datastore => datastore.mob)
644
662
  replicated_stemcell_vm = client.wait_for_task(task)
645
663
  @logger.info("Replicated #{stemcell} (#{stemcell_vm}) to " +
646
664
  "#{local_stemcell_name} (#{replicated_stemcell_vm})")
@@ -711,7 +729,7 @@ module VSphereCloud
711
729
  env["agent_id"] = agent_id
712
730
  env["networks"] = networking_env
713
731
  env["disks"] = disk_env
714
- env.merge!(@agent_properties)
732
+ env.merge!(Config.agent)
715
733
  env
716
734
  end
717
735
 
@@ -737,7 +755,7 @@ module VSphereCloud
737
755
  end
738
756
  end
739
757
 
740
- {:datacenter => datacenter_name, :datastore =>datastore_name, :vm =>vm_name}
758
+ {:datacenter => datacenter_name, :datastore => datastore_name, :vm => vm_name}
741
759
  end
742
760
 
743
761
  def get_primary_datastore(devices)
@@ -826,7 +844,7 @@ module VSphereCloud
826
844
 
827
845
  def fetch_file(datacenter_name, datastore_name, path)
828
846
  retry_block do
829
- url = "https://#{@vcenter["host"]}/folder/#{path}?dcPath=#{URI.escape(datacenter_name)}" +
847
+ url = "https://#{Config.vcenter.host}/folder/#{path}?dcPath=#{URI.escape(datacenter_name)}" +
830
848
  "&dsName=#{URI.escape(datastore_name)}"
831
849
 
832
850
  response = @rest_client.get(url)
@@ -843,7 +861,7 @@ module VSphereCloud
843
861
 
844
862
  def upload_file(datacenter_name, datastore_name, path, contents)
845
863
  retry_block do
846
- url = "https://#{@vcenter["host"]}/folder/#{path}?dcPath=#{URI.escape(datacenter_name)}" +
864
+ url = "https://#{Config.vcenter.host}/folder/#{path}?dcPath=#{URI.escape(datacenter_name)}" +
847
865
  "&dsName=#{URI.escape(datastore_name)}"
848
866
  response = @rest_client.put(url, contents, {"Content-Type" => "application/octet-stream",
849
867
  "Content-Length" => contents.length})
@@ -1052,34 +1070,5 @@ module VSphereCloud
1052
1070
  sleep(1.0)
1053
1071
  end
1054
1072
  end
1055
-
1056
- def delete_all_vms
1057
- Bosh::ThreadPool.new(:max_threads => 32, :logger => @logger).wrap do |pool|
1058
- index = 0
1059
-
1060
- @resources.datacenters.each_value do |datacenter|
1061
- vm_folder_path = [datacenter.name, "vm", datacenter.vm_folder_name]
1062
- vm_folder = client.find_by_inventory_path(vm_folder_path)
1063
- vms = client.get_managed_objects(Vim::VirtualMachine, :root => vm_folder)
1064
- next if vms.empty?
1065
-
1066
- vm_properties = client.get_properties(vms, Vim::VirtualMachine, ["name"])
1067
-
1068
- vm_properties.each do |_, properties|
1069
- pool.process do
1070
- @lock.synchronize {index += 1}
1071
- vm = properties["name"]
1072
- @logger.debug("Deleting #{index}/#{vms.size}: #{vm}")
1073
- begin
1074
- delete_vm(vm)
1075
- rescue Exception => e
1076
- @logger.info("#{e} - #{e.backtrace.join("\n")}")
1077
- end
1078
- end
1079
- end
1080
- end
1081
- end
1082
- end
1083
-
1084
1073
  end
1085
1074
  end
@@ -0,0 +1,254 @@
1
+ # Copyright (c) 2009-2012 VMware, Inc.
2
+
3
+ module VSphereCloud
4
+
5
+ # vSphere CPI Config
6
+ class Config
7
+
8
+ # Membrane schema for the provided config.
9
+ @schema = Membrane::SchemaParser.parse do
10
+ {
11
+ "agent" => dict(String, Object), # passthrough to the agent
12
+ optional("cpi_log") => String,
13
+ optional("soap_log") => String,
14
+ optional("mem_overcommit_ratio") => Numeric,
15
+ optional("copy_disks") => bool,
16
+ "vcenters" => [{
17
+ "host" => String,
18
+ "user" => String,
19
+ "password" => String,
20
+ "datacenters" => [{
21
+ "name" => String,
22
+ "vm_folder" => String,
23
+ "template_folder" => String,
24
+ optional("use_sub_folder") => bool,
25
+ "disk_path" => String,
26
+ "datastore_pattern" => String,
27
+ "persistent_datastore_pattern" => String,
28
+ optional("allow_mixed_datastores") => bool,
29
+ "clusters" => [enum(String,
30
+ dict(String, {"resource_pool" => String}))]
31
+ }]
32
+ }]
33
+ }
34
+ end
35
+
36
+ # vCenter config.
37
+ class VCenterConfig
38
+
39
+ # @!attribute host
40
+ # @return [String] vCenter host.
41
+ attr_accessor :host
42
+
43
+ # @!attribute user
44
+ # @return [String] vCenter user.
45
+ attr_accessor :user
46
+
47
+ # @!attribute password
48
+ # @return [String] vCenter password.
49
+ attr_accessor :password
50
+
51
+ # @!attribute datacenters
52
+ # @return [Hash<String, DatacenterConfig>] child datacenters.
53
+ attr_accessor :datacenters
54
+
55
+ # Creates a new vCenter Config model from parsed YAML.
56
+ #
57
+ # @param [Hash] config parsed YAML.
58
+ def initialize(config)
59
+ @host = config["host"]
60
+ @user = config["user"]
61
+ @password = config["password"]
62
+ @datacenters = {}
63
+
64
+ # TODO: current limitation to support a single vDC.
65
+ # Primarily due to stemcell replication logic calling CloneVM_Task which
66
+ # does not copy across datacenters. Should use CopyDatastoreFile_Task /
67
+ # CopyVirtualDisk_Task.
68
+ unless config["datacenters"].size == 1
69
+ raise "vSphere CPI only supports a single datacenter."
70
+ end
71
+
72
+ config["datacenters"].each do |dc|
73
+ dc_config = DatacenterConfig.new(dc)
74
+ @datacenters[dc_config.name] = dc_config
75
+ end
76
+ end
77
+ end
78
+
79
+ # Folder config.
80
+ class FolderConfig
81
+ # @!attribute vm
82
+ # @return [String] vm folder path.
83
+ attr_accessor :vm
84
+
85
+ # @!attribute template
86
+ # @return [String] template/stemcell folder path.
87
+ attr_accessor :template
88
+
89
+ # @!attribute shared
90
+ # @return [true, false] boolean indicating shared folders, so an
91
+ # additional namespace should be used.
92
+ attr_accessor :shared
93
+ end
94
+
95
+ # Datastore config.
96
+ class DatastoreConfig
97
+
98
+ # @!attribute ephemeral_pattern
99
+ # @return [Regexp] regexp pattern for ephemeral datastores.
100
+ attr_accessor :ephemeral_pattern
101
+
102
+ # @!attribute persistent_pattern
103
+ # @return [Regexp] regexp pattern for persistent datastores.
104
+ attr_accessor :persistent_pattern
105
+
106
+ # @!attribute disk_path
107
+ # @return [String] VMDK datastore path.
108
+ attr_accessor :disk_path
109
+
110
+ # @!attribute allow_mixed
111
+ # @return [true, false] boolean indicating whether persistent and
112
+ # ephemeral datastores can overlap..
113
+ attr_accessor :allow_mixed
114
+ end
115
+
116
+ # Datacenter config.
117
+ class DatacenterConfig
118
+
119
+ # @!attribute name
120
+ # @return [String] datacenter name.
121
+ attr_accessor :name
122
+
123
+ # @!attribute folders
124
+ # @return [FolderConfig] folder config.
125
+ attr_accessor :folders
126
+
127
+ # @!attribute datastores
128
+ # @return [DatastoreConfig] datastore config.
129
+ attr_accessor :datastores
130
+
131
+ # @!attribute clusters
132
+ # @return [Hash<String, ClusterConfig>] child clusters.
133
+ attr_accessor :clusters
134
+
135
+ # Creates a new Datacenter Config model from parsed YAML.
136
+ #
137
+ # @param [Hash] config parsed YAML.
138
+ def initialize(config)
139
+ @name = config["name"]
140
+
141
+ @folders = FolderConfig.new
142
+ @folders.template = config["template_folder"]
143
+ @folders.vm = config["vm_folder"]
144
+ @folders.shared = !!config["use_sub_folder"]
145
+
146
+ @datastores = DatastoreConfig.new
147
+ @datastores.ephemeral_pattern = Regexp.new(config["datastore_pattern"])
148
+ @datastores.persistent_pattern = Regexp.new(
149
+ config["persistent_datastore_pattern"])
150
+ @datastores.disk_path = config["disk_path"]
151
+ @datastores.allow_mixed = !!config["allow_mixed_datastores"]
152
+
153
+ @clusters = {}
154
+ config["clusters"].each do |cluster|
155
+ cluster_config = ClusterConfig.new(cluster)
156
+ @clusters[cluster_config.name] = cluster_config
157
+ end
158
+
159
+ if @clusters.any? { |_, cluster| cluster.resource_pool }
160
+ @folders.shared = true
161
+ end
162
+ end
163
+ end
164
+
165
+ # Cluster config.
166
+ class ClusterConfig
167
+
168
+ # @!attribute name
169
+ # @return [String] cluster name.
170
+ attr_accessor :name
171
+
172
+ # @!attribute resource_pool
173
+ # @return [String?] optional resource pool to use instead of root.
174
+ attr_accessor :resource_pool
175
+
176
+ # Creates a new Cluster Config model from parsed YAML.
177
+ #
178
+ # @param [Hash] config parsed YAML.
179
+ def initialize(config)
180
+ case config
181
+ when String
182
+ @name = config
183
+ else
184
+ @name = config.keys.first
185
+ @resource_pool = config[@name]["resource_pool"]
186
+ end
187
+ end
188
+ end
189
+
190
+ class << self
191
+
192
+ CONFIG_OPTIONS = [
193
+ :logger,
194
+ :client,
195
+ :rest_client,
196
+ :agent,
197
+ :copy_disks,
198
+ :vcenter,
199
+ :mem_overcommit,
200
+ ]
201
+
202
+ CONFIG_OPTIONS.each do |option|
203
+ attr_accessor option
204
+ end
205
+
206
+ # Clear all of the properties.
207
+ #
208
+ # Used by unit tests.
209
+ # @return [void]
210
+ def clear
211
+ CONFIG_OPTIONS.each do |option|
212
+ self.instance_variable_set("@#{option}".to_sym, nil)
213
+ end
214
+ end
215
+
216
+ # Setup the Config context based on the parsed YAML.
217
+ #
218
+ # @return [void]
219
+ def configure(config)
220
+ @logger = Bosh::Clouds::Config.logger
221
+ @schema.validate(config)
222
+ @agent = config["agent"]
223
+
224
+ unless config["vcenters"].size == 1
225
+ raise "vSphere CPI only supports a single vCenter."
226
+ end
227
+ @vcenter = VCenterConfig.new(config["vcenters"].first)
228
+
229
+ @client = Client.new("https://#{@vcenter.host}/sdk/vimService", {
230
+ "soap_log" => config["soap_log"] || config["cpi_log"]
231
+ })
232
+ @client.login(@vcenter.user, @vcenter.password, "en")
233
+
234
+ @rest_client = HTTPClient.new
235
+ @rest_client.send_timeout = 14400 # 4 hours, for stemcell uploads
236
+ @rest_client.ssl_config.verify_mode = OpenSSL::SSL::VERIFY_NONE
237
+
238
+ # HACK: read the session from the SOAP client so we don't leak sessions
239
+ # when using the REST client
240
+ cookie_str = @client.stub.cookie
241
+ @rest_client.cookie_manager.parse(
242
+ cookie_str, URI.parse("https://#{@vcenter.host}"))
243
+
244
+ if config["mem_overcommit_ratio"]
245
+ @mem_overcommit = config["mem_overcommit_ratio"].to_f
246
+ else
247
+ @mem_overcommit = 1.0
248
+ end
249
+
250
+ @copy_disks = !!config["copy_disks"]
251
+ end
252
+ end
253
+ end
254
+ end