bosh_vsphere_cpi 1.1868.0 → 1.1975.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,17 @@
1
+ module VSphereCloud
2
+ class FixedClusterPlacer
3
+ def initialize(cluster)
4
+ @cluster = cluster
5
+ end
6
+
7
+ def place(memory, ephemeral, persistent)
8
+ datastore = @cluster.pick_ephemeral(ephemeral)
9
+ if datastore
10
+ @cluster.allocate(memory)
11
+ datastore.allocate(ephemeral)
12
+ return [@cluster, datastore]
13
+ end
14
+ raise "No available resources"
15
+ end
16
+ end
17
+ end
@@ -1,18 +1,15 @@
1
- # Copyright (c) 2009-2012 VMware, Inc.
1
+ require 'cloud/vsphere/resources/datacenter'
2
2
 
3
3
  module VSphereCloud
4
-
5
- # Resources model.
6
4
  class Resources
7
5
  MEMORY_THRESHOLD = 128
8
6
  DISK_THRESHOLD = 1024
9
7
  STALE_TIMEOUT = 60
10
8
  BYTES_IN_MB = 1024 * 1024
11
9
 
12
- # Creates a new resources model.
13
- def initialize
14
- @client = Config.client
15
- @logger = Config.logger
10
+ def initialize(config)
11
+ @config = config
12
+ @logger = config.logger
16
13
  @last_update = 0
17
14
  @lock = Monitor.new
18
15
  end
@@ -100,7 +97,7 @@ module VSphereCloud
100
97
  locality.each do |cluster, _|
101
98
  persistent_sizes = persistent_sizes_for_cluster(cluster, persistent)
102
99
 
103
- scorer = Scorer.new(cluster, memory, ephemeral, persistent_sizes)
100
+ scorer = Scorer.new(@config, cluster, memory, ephemeral, persistent_sizes)
104
101
  if scorer.score > 0
105
102
  datastore = cluster.pick_ephemeral(ephemeral)
106
103
  if datastore
@@ -113,23 +110,23 @@ module VSphereCloud
113
110
 
114
111
  unless locality.empty?
115
112
  @logger.debug("Ignoring datastore locality as we could not find " +
116
- "any resources near disks: #{persistent.inspect}")
113
+ "any resources near disks: #{persistent.inspect}")
117
114
  end
118
115
 
119
116
  weighted_clusters = []
120
- datacenters.each_value do |datacenter|
121
- datacenter.clusters.each_value do |cluster|
122
- persistent_sizes = persistent_sizes_for_cluster(cluster, persistent)
123
- scorer = Scorer.new(cluster, memory, ephemeral, persistent_sizes)
124
- score = scorer.score
125
- @logger.debug("Score: #{cluster.name}: #{score}")
126
- weighted_clusters << [cluster, score] if score > 0
127
- end
117
+ datacenter = datacenters.first.last
118
+ datacenter.clusters.each_value do |cluster|
119
+ persistent_sizes = persistent_sizes_for_cluster(cluster, persistent)
120
+ scorer = Scorer.new(@config, cluster, memory, ephemeral, persistent_sizes)
121
+ score = scorer.score
122
+ @logger.debug("Score: #{cluster.name}: #{score}")
123
+ weighted_clusters << [cluster, score] if score > 0
128
124
  end
129
125
 
130
126
  raise "No available resources" if weighted_clusters.empty?
131
127
 
132
128
  cluster = Util.weighted_random(weighted_clusters)
129
+
133
130
  datastore = cluster.pick_ephemeral(ephemeral)
134
131
 
135
132
  if datastore
@@ -144,13 +141,14 @@ module VSphereCloud
144
141
 
145
142
  private
146
143
 
144
+ attr_reader :config
145
+
147
146
  # Updates the resource models from vSphere.
148
147
  # @return [void]
149
148
  def update
150
- @datacenters = {}
151
- Config.vcenter.datacenters.each_value do |config|
152
- @datacenters[config.name] = Datacenter.new(config)
153
- end
149
+ #datacenter_config = config.vcenter_datacenter
150
+ datacenter = Datacenter.new(config)
151
+ @datacenters = { datacenter.name => datacenter }
154
152
  @last_update = Time.now.to_i
155
153
  end
156
154
 
@@ -212,7 +210,7 @@ module VSphereCloud
212
210
  # @return [Array<Hash>] filtered out disk specs.
213
211
  def persistent_sizes_for_cluster(cluster, disks)
214
212
  disks.select { |disk| disk[:cluster] != cluster }.
215
- collect { |disk| disk[:size] }
213
+ collect { |disk| disk[:size] }
216
214
  end
217
215
  end
218
216
  end
@@ -1,51 +1,35 @@
1
- # Copyright (c) 2009-2012 VMware, Inc.
2
-
3
1
  module VSphereCloud
4
2
  class Resources
5
-
6
- # Cluster resource.
7
3
  class Cluster
8
4
  include VimSdk
9
5
 
10
6
  PROPERTIES = %w(name datastore resourcePool host)
11
7
  HOST_PROPERTIES = %w(hardware.memorySize runtime.inMaintenanceMode)
12
- HOST_COUNTERS = %w(cpu.usage.average mem.usage.average)
8
+ HOST_COUNTERS = %w(mem.usage.average)
13
9
 
14
10
  # @!attribute mob
15
11
  # @return [Vim::ClusterComputeResource] cluster vSphere MOB.
16
- attr_accessor :mob
17
-
18
- # @!attribute config
19
- # @return [ClusterConfig] cluster config.
20
- attr_accessor :config
12
+ attr_reader :mob
21
13
 
22
14
  # @!attribute datacenter
23
15
  # @return [Datacenter] parent datacenter.
24
- attr_accessor :datacenter
16
+ attr_reader :datacenter
25
17
 
26
18
  # @!attribute resource_pool
27
19
  # @return [ResourcePool] resource pool.
28
- attr_accessor :resource_pool
20
+ attr_reader :resource_pool
29
21
 
30
22
  # @!attribute ephemeral_datastores
31
23
  # @return [Hash<String, Datastore>] ephemeral datastores.
32
- attr_accessor :ephemeral_datastores
24
+ attr_reader :ephemeral_datastores
33
25
 
34
26
  # @!attribute persistent_datastores
35
27
  # @return [Hash<String, Datastore>] persistent datastores.
36
- attr_accessor :persistent_datastores
28
+ attr_reader :persistent_datastores
37
29
 
38
30
  # @!attribute shared_datastores
39
31
  # @return [Hash<String, Datastore>] shared datastores.
40
- attr_accessor :shared_datastores
41
-
42
- # @!attribute idle_cpu
43
- # @return [Float] idle cpu ratio.
44
- attr_accessor :idle_cpu
45
-
46
- # @!attribute total_memory
47
- # @return [Integer] memory capacity in MB.
48
- attr_accessor :total_memory
32
+ attr_reader :shared_datastores
49
33
 
50
34
  # @!attribute synced_free_memory
51
35
  # @return [Integer] cached memory utilization in MB.
@@ -58,60 +42,34 @@ module VSphereCloud
58
42
  # Creates a new Cluster resource from the specified datacenter, cluster
59
43
  # configuration, and prefetched properties.
60
44
  #
61
- # @param [Datacenter] datacenter parent datacenter.
45
+ # @param [CloudConfig] VSphereCloud::Config
62
46
  # @param [ClusterConfig] config cluster configuration as specified by the
63
47
  # operator.
64
48
  # @param [Hash] properties prefetched vSphere properties for the cluster.
65
- def initialize(datacenter, config, properties)
66
- @logger = Config.logger
67
- @client = Config.client
68
-
49
+ def initialize(datacenter, cloud_config, cluster_config, properties)
69
50
  @datacenter = datacenter
70
- @config = config
71
- @mob = properties[:obj]
72
- @resource_pool = ResourcePool.new(self, properties["resourcePool"])
51
+ @logger = cloud_config.logger
52
+ @client = cloud_config.client
53
+ @properties = properties
54
+
55
+ @config = cluster_config
56
+ @cloud_config = cloud_config
57
+ @mob = properties['obj']
58
+ @resource_pool = ResourcePool.new(cloud_config, cluster_config, properties["resourcePool"])
73
59
 
74
60
  @allocated_after_sync = 0
75
61
  @ephemeral_datastores = {}
76
62
  @persistent_datastores = {}
77
63
  @shared_datastores = {}
78
64
 
79
- datastores_properties = @client.get_properties(
80
- properties["datastore"], Vim::Datastore, Datastore::PROPERTIES)
81
- datastores_properties.each_value do |datastore_properties|
82
- name = datastore_properties["name"]
83
- datastore_config = datacenter.config.datastores
84
- ephemeral = !!(name =~ datastore_config.ephemeral_pattern)
85
- persistent = !!(name =~ datastore_config.persistent_pattern)
86
-
87
- if ephemeral && persistent &&
88
- !datastore_config.allow_mixed
89
- raise "Datastore patterns are not mutually exclusive: #{name}"
90
- end
91
-
92
- if ephemeral || persistent
93
- datastore = Datastore.new(datastore_properties)
94
- if ephemeral && persistent
95
- @shared_datastores[datastore.name] = datastore
96
- elsif ephemeral
97
- @ephemeral_datastores[datastore.name] = datastore
98
- else
99
- @persistent_datastores[datastore.name] = datastore
100
- end
101
- end
102
- end
103
-
104
- @logger.debug(
105
- "Datastores - ephemeral: #{@ephemeral_datastores.keys.inspect}, " +
106
- "persistent: #{@persistent_datastores.keys.inspect}, " +
107
- "shared: #{@shared_datastores.keys.inspect}.")
65
+ setup_datastores
108
66
 
109
67
  # Have to use separate mechanisms for fetching utilization depending on
110
68
  # whether we're using resource pools or raw clusters.
111
69
  if @config.resource_pool.nil?
112
- fetch_cluster_utilization(properties["host"])
70
+ fetch_cluster_utilization(properties['host'])
113
71
  else
114
- fetch_res_pool_utilization
72
+ fetch_resource_pool_utilization
115
73
  end
116
74
  end
117
75
 
@@ -122,15 +80,24 @@ module VSphereCloud
122
80
  # @return [Datastore, nil] the requested persistent datastore.
123
81
  def persistent(datastore_name)
124
82
  @persistent_datastores[datastore_name] ||
125
- @shared_datastores[datastore_name]
83
+ @shared_datastores[datastore_name]
126
84
  end
127
85
 
128
86
  # @return [Integer] amount of free memory in the cluster
129
87
  def free_memory
130
88
  @synced_free_memory -
131
- (@allocated_after_sync * Config.mem_overcommit).to_i
89
+ (@allocated_after_sync * cloud_config.mem_overcommit).to_i
132
90
  end
133
91
 
92
+ # Marks the memory reservation against the cached utilization data.
93
+ #
94
+ # @param [Integer] memory size of memory reservation.
95
+ # @return [void]
96
+ def allocate(memory)
97
+ @allocated_after_sync += memory
98
+ end
99
+
100
+
134
101
  # Picks the best datastore for the specified persistent disk.
135
102
  #
136
103
  # @param [Integer] size persistent disk size.
@@ -149,26 +116,55 @@ module VSphereCloud
149
116
  pick_store(size, :ephemeral)
150
117
  end
151
118
 
152
- # Marks the memory reservation against the cached utilization data.
153
- #
154
- # @param [Integer] memory size of memory reservation.
155
- # @return [void]
156
- def allocate(memory)
157
- @allocated_after_sync += memory
158
- end
159
-
160
119
  # @return [String] cluster name.
161
120
  def name
162
- @config.name
121
+ config.name
163
122
  end
164
123
 
165
124
  # @return [String] debug cluster information.
166
125
  def inspect
167
- "<Cluster: #@mob / #{@config.name}>"
126
+ "<Cluster: #{mob} / #{config.name}>"
168
127
  end
169
128
 
170
129
  private
171
130
 
131
+ attr_reader :cloud_config, :config, :client, :properties, :logger
132
+
133
+ def setup_datastores
134
+ datastores_properties = client.get_properties(properties['datastore'], Vim::Datastore, Datastore::PROPERTIES)
135
+
136
+ datastores_properties.each_value do |datastore_properties|
137
+ name = datastore_properties["name"]
138
+
139
+ ephemeral = !!(name =~ cloud_config.datacenter_datastore_pattern)
140
+ persistent = !!(name =~ cloud_config.datacenter_persistent_datastore_pattern)
141
+
142
+ if ephemeral && persistent && !cloud_config.datacenter_allow_mixed_datastores
143
+ raise "Datastore patterns are not mutually exclusive: #{name}"
144
+ end
145
+
146
+ if ephemeral || persistent
147
+ place_datastore(datastore_properties, ephemeral, persistent)
148
+ end
149
+ end
150
+
151
+ logger.debug(
152
+ "Datastores - ephemeral: #{@ephemeral_datastores.keys.inspect}, " +
153
+ "persistent: #{@persistent_datastores.keys.inspect}, " +
154
+ "shared: #{@shared_datastores.keys.inspect}.")
155
+ end
156
+
157
+ def place_datastore(datastore_properties, ephemeral, persistent)
158
+ datastore = Datastore.new(datastore_properties)
159
+ if ephemeral && persistent
160
+ @shared_datastores[datastore.name] = datastore
161
+ elsif ephemeral
162
+ @ephemeral_datastores[datastore.name] = datastore
163
+ else
164
+ @persistent_datastores[datastore.name] = datastore
165
+ end
166
+ end
167
+
172
168
  # Picks the best datastore for the specified disk size and type.
173
169
  #
174
170
  # First the exclusive datastore pool is used. If it's empty or doesn't
@@ -181,7 +177,7 @@ module VSphereCloud
181
177
  def pick_store(size, type)
182
178
  weighted_datastores = []
183
179
  datastores =
184
- type == :persistent ? @persistent_datastores : @ephemeral_datastores
180
+ type == :persistent ? @persistent_datastores : @ephemeral_datastores
185
181
  datastores.each_value do |datastore|
186
182
  if datastore.free_space - size >= DISK_THRESHOLD
187
183
  weighted_datastores << [datastore, datastore.free_space]
@@ -205,45 +201,42 @@ module VSphereCloud
205
201
  # individual host capacity and its utilization using the performance
206
202
  # manager.
207
203
  #
208
- # @param [Array<Vim::HostSystem>] host_mobs cluster hosts.
204
+ # @param [Array<Vim::HostSystem>] cluster_host_systems cluster hosts.
209
205
  # @return [void]
210
- def fetch_cluster_utilization(host_mobs)
206
+ def fetch_cluster_utilization(cluster_host_systems)
211
207
  hosts_properties = @client.get_properties(
212
- host_mobs, Vim::HostSystem, HOST_PROPERTIES, :ensure_all => true)
213
- host_mobs = filter_inactive_hosts(hosts_properties)
208
+ cluster_host_systems, Vim::HostSystem, HOST_PROPERTIES, ensure_all: true)
209
+ active_host_mobs = select_active_host_mobs(hosts_properties)
214
210
 
215
- if host_mobs.empty?
216
- @idle_cpu = 0
217
- @total_memory = 0
218
- @synced_free_memory = 0
219
- return
220
- end
211
+ @synced_free_memory = 0
212
+ return if active_host_mobs.empty?
221
213
 
222
- samples = 0
223
- cluster_total_memory = 0
224
214
  cluster_free_memory = 0
225
- cluster_cpu_usage = 0
226
215
 
227
- counters = @client.get_perf_counters(
228
- host_mobs, HOST_COUNTERS, :max_sample => 5)
216
+ counters = @client.get_perf_counters(active_host_mobs, HOST_COUNTERS, max_sample: 5)
229
217
  counters.each do |host_mob, counter|
230
218
  host_properties = hosts_properties[host_mob]
231
219
  total_memory = host_properties["hardware.memorySize"].to_i
232
220
  percent_used = Util.average_csv(counter["mem.usage.average"]) / 10000
233
221
  free_memory = ((1.0 - percent_used) * total_memory).to_i
234
222
 
235
- samples += 1
236
- cluster_total_memory += total_memory
237
223
  cluster_free_memory += free_memory
238
- cluster_cpu_usage +=
239
- Util.average_csv(counter["cpu.usage.average"]) / 100
240
224
  end
241
225
 
242
- @idle_cpu = (100 - cluster_cpu_usage / samples) / 100
243
- @total_memory = cluster_total_memory / BYTES_IN_MB
244
226
  @synced_free_memory = cluster_free_memory / BYTES_IN_MB
245
227
  end
246
228
 
229
+ # Filters out the hosts that are in maintenance mode.
230
+ #
231
+ # @param [Hash] host_properties host properties that already fetched
232
+ # inMaintenanceMode from vSphere.
233
+ # @return [Array<Vim::HostSystem>] list of hosts that are active
234
+ def select_active_host_mobs(host_properties)
235
+ host_properties.values.
236
+ select { |p| p['runtime.inMaintenanceMode'] != 'true' }.
237
+ collect { |p| p['obj'] }
238
+ end
239
+
247
240
  # Fetches the resource pool utilization from vSphere.
248
241
  #
249
242
  # We can only rely on the vSphere data if the resource pool is healthy.
@@ -253,42 +246,22 @@ module VSphereCloud
253
246
  # so we can't use it for the raw clusters.
254
247
  #
255
248
  # @return [void]
256
- def fetch_res_pool_utilization
257
- properties = @client.get_properties(
258
- @resource_pool.mob, Vim::ResourcePool, %w(summary))
259
- if properties.nil?
260
- raise "Failed to get utilization for resource pool #{resource_pool}"
261
- end
249
+ def fetch_resource_pool_utilization
250
+ properties = @client.get_properties(resource_pool.mob, Vim::ResourcePool, 'summary')
251
+ raise "Failed to get utilization for resource pool #{resource_pool}" if properties.nil?
262
252
 
263
253
  runtime_info = properties["summary"].runtime
254
+
264
255
  if runtime_info.overall_status == "green"
265
- cpu = runtime_info.cpu
266
- @idle_cpu = 1 - (cpu.overall_usage.to_f / cpu.max_usage)
267
256
  memory = runtime_info.memory
268
- @total_memory = memory.max_usage / BYTES_IN_MB
269
- @synced_free_memory =
270
- (memory.max_usage - memory.overall_usage) / BYTES_IN_MB
257
+ @synced_free_memory = (memory.max_usage - memory.overall_usage) / BYTES_IN_MB
271
258
  else
272
- @logger.warn("Ignoring cluster: #{config.name} resource_pool: " +
273
- "#{@resource_pool.mob} as its state is " +
274
- "unreliable: #{runtime_info.overall_status}")
275
- # resource pool is in an unreliable state
276
- @idle_cpu = 0
277
- @total_memory = 0
259
+ logger.warn("Ignoring cluster: #{config.name} resource_pool: " +
260
+ "#{resource_pool.mob} as its state is " +
261
+ "unreliable: #{runtime_info.overall_status}")
278
262
  @synced_free_memory = 0
279
263
  end
280
264
  end
281
-
282
- # Filters out the hosts that are in maintenance mode.
283
- #
284
- # @param [Hash] host_properties host properties that already fetched
285
- # inMaintenanceMode from vSphere.
286
- # @return [Array<Vim::HostSystem>] list of hosts that are active
287
- def filter_inactive_hosts(host_properties)
288
- host_properties.values.
289
- select { |p| p["runtime.inMaintenanceMode"] != "true" }.
290
- collect { |p| p[:obj] }
291
- end
292
265
  end
293
266
  end
294
- end
267
+ end