bosh_vsphere_cpi 0.4.9 → 0.5.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.
@@ -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