Class: VSphereCloud::Resources

Inherits:
Object
  • Object
show all
Defined in:
lib/cloud/vsphere/resources.rb,
lib/cloud/vsphere/resources/util.rb,
lib/cloud/vsphere/resources/folder.rb,
lib/cloud/vsphere/resources/scorer.rb,
lib/cloud/vsphere/resources/cluster.rb,
lib/cloud/vsphere/resources/datastore.rb,
lib/cloud/vsphere/resources/datacenter.rb,
lib/cloud/vsphere/resources/resource_pool.rb

Defined Under Namespace

Classes: Cluster, Datacenter, Datastore, Folder, ResourcePool, Scorer, Util

Constant Summary collapse

MEMORY_THRESHOLD =
128
DISK_THRESHOLD =
1024
STALE_TIMEOUT =
60
BYTES_IN_MB =
1024 * 1024

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(config) ⇒ Resources

Returns a new instance of Resources.



12
13
14
15
16
17
18
# File 'lib/cloud/vsphere/resources.rb', line 12

def initialize(config)
  @config = config
  @logger = config.logger
  @last_update = 0
  @lock = Monitor.new
  @drs_rules = []
end

Instance Attribute Details

#drs_rulesObject (readonly)

Returns the value of attribute drs_rules.



10
11
12
# File 'lib/cloud/vsphere/resources.rb', line 10

def drs_rules
  @drs_rules
end

Instance Method Details

#datacentersList<Resources::Datacenter>

Returns the list of datacenters available for placement.

Will lazily load them and reload the data when it’s stale.

Returns:



25
26
27
28
29
30
# File 'lib/cloud/vsphere/resources.rb', line 25

def datacenters
  @lock.synchronize do
    update if Time.now.to_i - @last_update > STALE_TIMEOUT
  end
  @datacenters
end

#persistent_datastore(dc_name, cluster_name, datastore_name) ⇒ Resources::Datastore

Returns the persistent datastore for the requested context.

Parameters:

  • dc_name (String)

    datacenter name.

  • cluster_name (String)

    cluster name.

  • datastore_name (String)

    datastore name.

Returns:



38
39
40
41
42
43
44
# File 'lib/cloud/vsphere/resources.rb', line 38

def persistent_datastore(dc_name, cluster_name, datastore_name)
  datacenter = datacenters[dc_name]
  return nil if datacenter.nil?
  cluster = datacenter.clusters[cluster_name]
  return nil if cluster.nil?
  cluster.persistent(datastore_name)
end

#place(memory, ephemeral, persistent) ⇒ Array

Find a place for the requested resources.

Parameters:

  • memory (Integer)

    requested memory.

  • ephemeral (Integer)

    requested ephemeral storage.

  • persistent (Array<Hash>)

    requested persistent storage.

Returns:

  • (Array)

    an array/tuple of Cluster and Datastore if the resources were placed successfully, otherwise exception.



91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
# File 'lib/cloud/vsphere/resources.rb', line 91

def place(memory, ephemeral, persistent)
  populate_resources(persistent)

  # calculate locality to prioritizing clusters that contain the most
  # persistent data.
  locality = cluster_locality(persistent)
  locality.sort! { |a, b| b[1] <=> a[1] }

  @lock.synchronize do
    locality.each do |cluster, _|
      persistent_sizes = persistent_sizes_for_cluster(cluster, persistent)

      scorer = Scorer.new(@config, cluster, memory, ephemeral, persistent_sizes)
      if scorer.score > 0
        datastore = cluster.pick_ephemeral(ephemeral)
        if datastore
          cluster.allocate(memory)
          datastore.allocate(ephemeral)
          return [cluster, datastore]
        end
      end
    end

    unless locality.empty?
      @logger.debug("Ignoring datastore locality as we could not find " +
                      "any resources near disks: #{persistent.inspect}")
    end

    weighted_clusters = []
    datacenter = datacenters.first.last
    datacenter.clusters.each_value do |cluster|
      persistent_sizes = persistent_sizes_for_cluster(cluster, persistent)
      scorer = Scorer.new(@config, cluster, memory, ephemeral, persistent_sizes)
      score = scorer.score
      @logger.debug("Score: #{cluster.name}: #{score}")
      weighted_clusters << [cluster, score] if score > 0
    end

    raise "No available resources" if weighted_clusters.empty?

    cluster = Util.weighted_random(weighted_clusters)

    datastore = cluster.pick_ephemeral(ephemeral)

    if datastore
      cluster.allocate(memory)
      datastore.allocate(ephemeral)
      return [cluster, datastore]
    end

    raise "No available resources"
  end
end

#place_persistent_datastore(dc_name, cluster_name, disk_space) ⇒ Datastore?

Place the persistent datastore in the given datacenter and cluster with the requested disk space.

Parameters:

  • dc_name (String)

    datacenter name.

  • cluster_name (String)

    cluster name.

  • disk_space (Integer)

    disk space.

Returns:

  • (Datastore?)

    datastore if it was placed succesfuly.



71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/cloud/vsphere/resources.rb', line 71

def place_persistent_datastore(dc_name, cluster_name, disk_space)
  @lock.synchronize do
    datacenter = datacenters[dc_name]
    return nil if datacenter.nil?
    cluster = datacenter.clusters[cluster_name]
    return nil if cluster.nil?
    datastore = cluster.pick_persistent(disk_space)
    return nil if datastore.nil?
    datastore.allocate(disk_space)
    return datastore
  end
end

#validate_persistent_datastore(dc_name, datastore_name) ⇒ true, false

Validate that the persistent datastore is still valid so we don’t have to move the disk.

Parameters:

  • dc_name (String)

    datacenter name.

  • datastore_name (String)

    datastore name.

Returns:

  • (true, false)

    true iff the datastore still exists and is in the persistent pool.



53
54
55
56
57
58
59
60
61
62
# File 'lib/cloud/vsphere/resources.rb', line 53

def validate_persistent_datastore(dc_name, datastore_name)
  datacenter = datacenters[dc_name]
  if datacenter.nil?
    raise "Invalid datacenter #{dc_name} #{datacenters.inspect}"
  end
  datacenter.clusters.each_value do |cluster|
    return true unless cluster.persistent(datastore_name).nil?
  end
  false
end