Files
puppet-nova/lib/puppet/provider/nova_aggregate/nova.rb
Mike Dorman 2075c0fc9e Sort host_aggregate hosts list for comparison
Sort the list of hosts in the aggregate, both from the
provider/nova API as well as from the resource definition
in the manifest.  This allows for more accurate comparison
to determine if the resource really needs to be updated or
not.

Change-Id: I10a1995eb58e4bcd492bb7d6f94453a29cb31097
Closes-bug: 1534845
2016-01-15 15:58:36 -07:00

174 lines
5.1 KiB
Ruby

require File.join(File.dirname(__FILE__), '..','..','..',
'puppet/provider/nova')
Puppet::Type.type(:nova_aggregate).provide(
:nova,
:parent => Puppet::Provider::Nova
) do
desc "Manage nova aggregations"
commands :nova => 'nova'
mk_resource_methods
def self.instances
nova_aggregate_resources_ids().collect do |el|
attrs = nova_aggregate_resources_attr(el['Id'])
new(
:ensure => :present,
:name => attrs['Name'],
:id => attrs['Id'],
:availability_zone => attrs['Availability Zone'],
:metadata => attrs['Metadata'],
:hosts => attrs['Hosts'].sort
)
end
end
def self.prefetch(resources)
instances_ = instances
resources.keys.each do |name|
if provider = instances_.find{ |instance| instance.name == name }
resources[name].provider = provider
end
end
end
def exists?
@property_hash[:ensure] == :present
end
def destroy
#delete hosts first
if not @property_hash[:hosts].nil?
@property_hash[:hosts].each do |h|
auth_nova("aggregate-remove-host", name, h)
end
end
#now delete aggregate
auth_nova("aggregate-delete", name)
@property_hash[:ensure] = :absent
end
def create
extras = Array.new
#check for availability zone
if not @resource[:availability_zone].nil? and not @resource[:availability_zone].empty?
extras << "#{@resource[:availability_zone]}"
end
#run the command
result = auth_nova("aggregate-create", resource[:name], extras)
#get Id by Name
#force a refresh of the aggregate list on creation
id = self.class.nova_aggregate_resources_get_name_by_id(resource[:name], true)
@property_hash = {
:ensure => :present,
:name => resource[:name],
:id => id,
:availability_zone => resource[:availability_zone]
}
#add metadata
if not @resource[:metadata].nil? and not @resource[:metadata].empty?
@resource[:metadata].each do |key, value|
set_metadata_helper(id, key, value)
end
@property_hash[:metadata] = resource[:metadata]
end
#add hosts - This throws an error if the host is already attached to another aggregate!
if not @resource[:hosts].nil? and not @resource[:hosts].empty?
@resource[:hosts].each do |host|
# make sure the host exists in nova, or nova will fail the call
# this solves weird ordering issues with a compute node that's
# not 100% up being added to the host aggregate
if is_host_in_nova?(host)
auth_nova("aggregate-add-host", id, "#{host}")
else
warning("Cannot add #{host} to host aggregate, it's not available yet in nova host-list")
end
end
@property_hash[:hosts] = resource[:hosts]
end
end
def is_host_in_nova?(host)
return host==self.class.nova_get_host_by_name_and_type(host, "compute")
end
def hosts=(val)
#get current hosts
id = self.class.nova_aggregate_resources_get_name_by_id(name)
attrs = self.class.nova_aggregate_resources_attr(id)
#remove all hosts which are not in new value list
attrs['Hosts'].each do |h|
if not val.include? h
auth_nova("aggregate-remove-host", id, "#{h}")
end
end
#add hosts from the value list
val.each do |h|
if not attrs['Hosts'].include? h
if is_host_in_nova?(h)
auth_nova("aggregate-add-host", id, "#{h}")
else
warning("Cannot add #{h} to host aggregate, it's not available yet in nova host-list")
end
end
end
end
def set_metadata_helper(agg_id, key, value)
auth_nova("aggregate-set-metadata", agg_id, "#{key}=#{value}")
end
def metadata
#get current metadata
id = self.class.nova_aggregate_resources_get_name_by_id(name)
attrs = self.class.nova_aggregate_resources_attr(id)
#just ignore the availability_zone. that's handled directly by nova
attrs['Metadata'].delete('availability_zone')
return attrs['Metadata']
end
def metadata=(val)
#get current metadata
id = self.class.nova_aggregate_resources_get_name_by_id(name)
attrs = self.class.nova_aggregate_resources_attr(id)
#get keys which are in current metadata but not in val. Make sure it has data first!
if attrs['Metadata'].length > 0
obsolete_keys = attrs['Metadata'].keys - val.keys
end
# clear obsolete keys. If there are any!
if obsolete_keys
obsolete_keys.each do |key|
if not key.include? 'availability_zone'
auth_nova("aggregate-set-metadata", id, "#{key}")
end
end
#handle keys (with obsolete keys)
new_keys = val.keys - obsolete_keys
else
#handle keys (without obsolete keys)
new_keys = val.keys
end
#set new metadata if value changed
new_keys.each do |key|
if val[key] != attrs['Metadata'][key.to_s]
value = val[key]
set_metadata_helper(id, key, value)
end
end
end
def availability_zone=(val)
id = self.class.nova_aggregate_resources_get_name_by_id(name)
auth_nova("aggregate-set-metadata", id, "availability_zone=#{val}")
end
end