OpenStack Orchestration (Heat)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

142 lines
4.9KB

  1. #
  2. # Licensed under the Apache License, Version 2.0 (the "License"); you may
  3. # not use this file except in compliance with the License. You may obtain
  4. # a copy of the License at
  5. #
  6. # http://www.apache.org/licenses/LICENSE-2.0
  7. #
  8. # Unless required by applicable law or agreed to in writing, software
  9. # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  10. # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  11. # License for the specific language governing permissions and limitations
  12. # under the License.
  13. from heat.common.i18n import _
  14. from heat.engine import constraints
  15. from heat.engine import properties
  16. from heat.engine import resource
  17. from heat.engine import support
  18. class HostAggregate(resource.Resource):
  19. """A resource for further partition an availability zone with hosts.
  20. While availability zones are visible to users, host aggregates are only
  21. visible to administrators. Host aggregates started out as a way to use
  22. Xen hypervisor resource pools, but has been generalized to provide a
  23. mechanism to allow administrators to assign key-value pairs to groups of
  24. machines. Each node can have multiple aggregates, each aggregate can have
  25. multiple key-value pairs, and the same key-value pair can be assigned to
  26. multiple aggregate. This information can be used in the scheduler to
  27. enable advanced scheduling, to set up xen hypervisor resources pools or to
  28. define logical groups for migration.
  29. """
  30. support_status = support.SupportStatus(version='6.0.0')
  31. default_client_name = 'nova'
  32. entity = 'aggregates'
  33. required_service_extension = 'os-aggregates'
  34. PROPERTIES = (
  35. NAME, AVAILABILITY_ZONE, HOSTS, METADATA
  36. ) = (
  37. 'name', 'availability_zone', 'hosts', 'metadata'
  38. )
  39. properties_schema = {
  40. NAME: properties.Schema(
  41. properties.Schema.STRING,
  42. _('Name for the aggregate.'),
  43. required=True,
  44. update_allowed=True,
  45. ),
  46. AVAILABILITY_ZONE: properties.Schema(
  47. properties.Schema.STRING,
  48. _('Name for the availability zone.'),
  49. update_allowed=True,
  50. ),
  51. HOSTS: properties.Schema(
  52. properties.Schema.LIST,
  53. _('List of hosts to join aggregate.'),
  54. update_allowed=True,
  55. schema=properties.Schema(
  56. properties.Schema.STRING,
  57. constraints=[constraints.CustomConstraint('nova.host')],
  58. ),
  59. ),
  60. METADATA: properties.Schema(
  61. properties.Schema.MAP,
  62. _('Arbitrary key/value metadata to store information '
  63. 'for aggregate.'),
  64. update_allowed=True,
  65. default={}
  66. ),
  67. }
  68. def _find_diff(self, update_prps, stored_prps):
  69. add_prps = list(set(update_prps or []) - set(stored_prps or []))
  70. remove_prps = list(set(stored_prps or []) - set(update_prps or []))
  71. return add_prps, remove_prps
  72. def handle_create(self):
  73. name = self.properties[self.NAME]
  74. availability_zone = self.properties[self.AVAILABILITY_ZONE]
  75. hosts = self.properties[self.HOSTS] or []
  76. metadata = self.properties[self.METADATA] or {}
  77. aggregate = self.client().aggregates.create(
  78. name=name, availability_zone=availability_zone
  79. )
  80. self.resource_id_set(aggregate.id)
  81. if metadata:
  82. aggregate.set_metadata(metadata)
  83. for host in hosts:
  84. aggregate.add_host(host)
  85. def handle_update(self, json_snippet, tmpl_diff, prop_diff):
  86. if prop_diff:
  87. aggregate = self.client().aggregates.get(self.resource_id)
  88. if self.HOSTS in prop_diff:
  89. new_hosts = prop_diff.pop(self.HOSTS)
  90. old_hosts = aggregate.hosts
  91. add_hosts, remove_hosts = self._find_diff(new_hosts, old_hosts)
  92. for host in add_hosts:
  93. aggregate.add_host(host)
  94. for host in remove_hosts:
  95. aggregate.remove_host(host)
  96. if self.METADATA in prop_diff:
  97. metadata = prop_diff.pop(self.METADATA)
  98. if metadata:
  99. aggregate.set_metadata(metadata)
  100. if prop_diff:
  101. aggregate.update(prop_diff)
  102. def handle_delete(self):
  103. if self.resource_id is None:
  104. return
  105. with self.client_plugin().ignore_not_found:
  106. aggregate = self.client().aggregates.get(self.resource_id)
  107. for host in aggregate.hosts:
  108. aggregate.remove_host(host)
  109. super(HostAggregate, self).handle_delete()
  110. def parse_live_resource_data(self, resource_properties, resource_data):
  111. aggregate_reality = {}
  112. for key in self.PROPERTIES:
  113. aggregate_reality.update({key: resource_data.get(key)})
  114. return aggregate_reality
  115. def resource_mapping():
  116. return {
  117. 'OS::Nova::HostAggregate': HostAggregate
  118. }