heat/heat/engine/resources/openstack/nova/host_aggregate.py

142 lines
4.9 KiB
Python

#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from heat.common.i18n import _
from heat.engine import constraints
from heat.engine import properties
from heat.engine import resource
from heat.engine import support
class HostAggregate(resource.Resource):
"""A resource for further partition an availability zone with hosts.
While availability zones are visible to users, host aggregates are only
visible to administrators. Host aggregates started out as a way to use
Xen hypervisor resource pools, but has been generalized to provide a
mechanism to allow administrators to assign key-value pairs to groups of
machines. Each node can have multiple aggregates, each aggregate can have
multiple key-value pairs, and the same key-value pair can be assigned to
multiple aggregate. This information can be used in the scheduler to
enable advanced scheduling, to set up xen hypervisor resources pools or to
define logical groups for migration.
"""
support_status = support.SupportStatus(version='6.0.0')
default_client_name = 'nova'
entity = 'aggregates'
required_service_extension = 'os-aggregates'
PROPERTIES = (
NAME, AVAILABILITY_ZONE, HOSTS, METADATA
) = (
'name', 'availability_zone', 'hosts', 'metadata'
)
properties_schema = {
NAME: properties.Schema(
properties.Schema.STRING,
_('Name for the aggregate.'),
required=True,
update_allowed=True,
),
AVAILABILITY_ZONE: properties.Schema(
properties.Schema.STRING,
_('Name for the availability zone.'),
update_allowed=True,
),
HOSTS: properties.Schema(
properties.Schema.LIST,
_('List of hosts to join aggregate.'),
update_allowed=True,
schema=properties.Schema(
properties.Schema.STRING,
constraints=[constraints.CustomConstraint('nova.host')],
),
),
METADATA: properties.Schema(
properties.Schema.MAP,
_('Arbitrary key/value metadata to store information '
'for aggregate.'),
update_allowed=True,
default={}
),
}
def _find_diff(self, update_prps, stored_prps):
add_prps = list(set(update_prps or []) - set(stored_prps or []))
remove_prps = list(set(stored_prps or []) - set(update_prps or []))
return add_prps, remove_prps
def handle_create(self):
name = self.properties[self.NAME]
availability_zone = self.properties[self.AVAILABILITY_ZONE]
hosts = self.properties[self.HOSTS] or []
metadata = self.properties[self.METADATA] or {}
aggregate = self.client().aggregates.create(
name=name, availability_zone=availability_zone
)
self.resource_id_set(aggregate.id)
if metadata:
aggregate.set_metadata(metadata)
for host in hosts:
aggregate.add_host(host)
def handle_update(self, json_snippet, tmpl_diff, prop_diff):
if prop_diff:
aggregate = self.client().aggregates.get(self.resource_id)
if self.HOSTS in prop_diff:
new_hosts = prop_diff.pop(self.HOSTS)
old_hosts = aggregate.hosts
add_hosts, remove_hosts = self._find_diff(new_hosts, old_hosts)
for host in add_hosts:
aggregate.add_host(host)
for host in remove_hosts:
aggregate.remove_host(host)
if self.METADATA in prop_diff:
metadata = prop_diff.pop(self.METADATA)
if metadata:
aggregate.set_metadata(metadata)
if prop_diff:
aggregate.update(prop_diff)
def handle_delete(self):
if self.resource_id is None:
return
with self.client_plugin().ignore_not_found:
aggregate = self.client().aggregates.get(self.resource_id)
for host in aggregate.hosts:
aggregate.remove_host(host)
super(HostAggregate, self).handle_delete()
def parse_live_resource_data(self, resource_properties, resource_data):
aggregate_reality = {}
for key in self.PROPERTIES:
aggregate_reality.update({key: resource_data.get(key)})
return aggregate_reality
def resource_mapping():
return {
'OS::Nova::HostAggregate': HostAggregate
}