Add is_nest property for container_skel
The main purpose of that patch is to allow creation of "virtual" container_skel, that will not generate any containers in inventory, but will contain all containers of corresponsive hosts. That might be useful in usecases like AZs, or when deployer simply wants to create custom groups and include all bare metal hosts along with all containers on them to the same group. Such behaviour can be triggered when empty belongs_to is provided for container_skel along with is_nest property. Then container_skel item will contain host-containers and it's children. Change-Id: Ic5570bfe9f0f54d1ea1e067834c11e6c390a2686
This commit is contained in:
parent
90fdc6322f
commit
fb34651cc2
@ -150,6 +150,131 @@ following steps:
|
|||||||
|
|
||||||
.. _affinity:
|
.. _affinity:
|
||||||
|
|
||||||
|
Adding virtual nest groups
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
If you want to create a custom group for arbitrary grouping of hosts and
|
||||||
|
containers within these hosts but skip the generation of any new containers,
|
||||||
|
you should use ``is_nest`` property under container_skel and skip defining
|
||||||
|
``belongs_to`` structure. ``is_nest`` property will add host-containers as
|
||||||
|
children to such a group.
|
||||||
|
|
||||||
|
Example: Defining Availability Zones
|
||||||
|
------------------------------------
|
||||||
|
|
||||||
|
A good example of how ``is_nest`` property can be used is describing
|
||||||
|
Availability Zones. As when operating multiple AZs it's handy to define
|
||||||
|
AZ-specific variables, like AZ name, for all hosts in this AZ. And
|
||||||
|
leveraging group_vars is best way of ensuring that all hosts that belong
|
||||||
|
to same AZ have same configuration applied.
|
||||||
|
|
||||||
|
Let's assume you have 3 controllers and each of them is placed
|
||||||
|
in different Availability Zones. There is also a compute node in
|
||||||
|
each Availability Zone. And we want each host or container that is placed
|
||||||
|
physically in a specific AZ be part of it's own group (ie azN_all)
|
||||||
|
|
||||||
|
In order to achieve that we need:
|
||||||
|
|
||||||
|
#. Define host groups in conf.d or openstack_user_config.yml to assign hosts
|
||||||
|
accordingly to their Availability Zones:
|
||||||
|
|
||||||
|
.. code-block:: yaml
|
||||||
|
|
||||||
|
az1-infra_hosts: &infra_az1
|
||||||
|
az1-infra1:
|
||||||
|
ip: 172.39.123.11
|
||||||
|
|
||||||
|
az2-infra_hosts: &infra_az2
|
||||||
|
az2-infra2:
|
||||||
|
ip: 172.39.123.12
|
||||||
|
|
||||||
|
az3-infra_hosts: &infra_az3
|
||||||
|
az3-infra3:
|
||||||
|
ip: 172.39.123.13
|
||||||
|
|
||||||
|
shared-infra_hosts: &controllers
|
||||||
|
<<: *infra_az1
|
||||||
|
<<: *infra_az2
|
||||||
|
<<: *infra_az3
|
||||||
|
|
||||||
|
az1-compute_hosts: &computes_az1
|
||||||
|
az1-compute01:
|
||||||
|
ip: 172.39.123.100
|
||||||
|
|
||||||
|
az2-compute_hosts: &computes_az2
|
||||||
|
az2-compute01:
|
||||||
|
ip: 172.39.123.150
|
||||||
|
|
||||||
|
az3-compute_hosts: &computes_az3
|
||||||
|
az3-compute01:
|
||||||
|
ip: 172.39.123.200
|
||||||
|
|
||||||
|
compute_hosts:
|
||||||
|
<<: *computes_az1
|
||||||
|
<<: *computes_az2
|
||||||
|
<<: *computes_az3
|
||||||
|
|
||||||
|
az1_hosts:
|
||||||
|
<<: *computes_az1
|
||||||
|
<<: *infra_az1
|
||||||
|
|
||||||
|
az2_hosts:
|
||||||
|
<<: *computes_az2
|
||||||
|
<<: *infra_az2
|
||||||
|
|
||||||
|
az3_hosts:
|
||||||
|
<<: *computes_az3
|
||||||
|
<<: *infra_az3
|
||||||
|
|
||||||
|
#. Create ``env.d/az.yml`` file that will leverage ``is_nest`` property and allow
|
||||||
|
all infra containers to be part of the AZ group as well
|
||||||
|
|
||||||
|
.. code-block:: yaml
|
||||||
|
|
||||||
|
component_skel:
|
||||||
|
az1_containers:
|
||||||
|
belongs_to:
|
||||||
|
- az1_all
|
||||||
|
az1_hosts:
|
||||||
|
belongs_to:
|
||||||
|
- az1_all
|
||||||
|
|
||||||
|
az2_containers:
|
||||||
|
belongs_to:
|
||||||
|
- az2_all
|
||||||
|
az2_hosts:
|
||||||
|
belongs_to:
|
||||||
|
- az2_all
|
||||||
|
|
||||||
|
az3_containers:
|
||||||
|
belongs_to:
|
||||||
|
- az3_all
|
||||||
|
az3_hosts:
|
||||||
|
belongs_to:
|
||||||
|
- az3_all
|
||||||
|
|
||||||
|
container_skel:
|
||||||
|
az1_containers:
|
||||||
|
properties:
|
||||||
|
is_nest: True
|
||||||
|
az2_containers:
|
||||||
|
properties:
|
||||||
|
is_nest: True
|
||||||
|
az3_containers:
|
||||||
|
properties:
|
||||||
|
is_nest: True
|
||||||
|
|
||||||
|
#. Now you can leverage group_vars file to apply a variable to all
|
||||||
|
containers and bare metal hosts in AZ.
|
||||||
|
For example ``/etc/openstack_deploy/group_vars/az1_all.yml``:
|
||||||
|
|
||||||
|
.. code-block:: yaml
|
||||||
|
|
||||||
|
---
|
||||||
|
az_name: az1
|
||||||
|
cinder_storage_availability_zone: "{{ az_name }}"
|
||||||
|
|
||||||
|
|
||||||
Deploying 0 (or more than one) of component type per host
|
Deploying 0 (or more than one) of component type per host
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
@ -143,6 +143,22 @@ infrastructure hosts. To achieve this, implement
|
|||||||
|
|
||||||
.. literalinclude:: ../../../../etc/openstack_deploy/env.d/cinder-volume.yml.container.example
|
.. literalinclude:: ../../../../etc/openstack_deploy/env.d/cinder-volume.yml.container.example
|
||||||
|
|
||||||
|
You can also declare a custom group for each pod that will also include all
|
||||||
|
containers from hosts that belong to this pod. This might be handy if you want
|
||||||
|
to define some variable for all hosts in the pod using group_variables.
|
||||||
|
|
||||||
|
For that create ``/etc/openstack_deploy/env.d/pod.yml`` with the following content:
|
||||||
|
|
||||||
|
.. literalinclude:: ../../../../etc/openstack_deploy/env.d/pods.yml.example
|
||||||
|
|
||||||
|
Above example will create following groups:
|
||||||
|
|
||||||
|
* ``podN_hosts`` which will contain only bare metal nodes
|
||||||
|
* ``podN_containers`` that will contain all containers that are spawned on
|
||||||
|
bare metal nodes, that are part of the pod.
|
||||||
|
* ``podN_all`` that will contain `podN_hosts` and `podN_containers` members
|
||||||
|
|
||||||
|
|
||||||
User variables
|
User variables
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
|
44
etc/openstack_deploy/env.d/pods.yml.example
Normal file
44
etc/openstack_deploy/env.d/pods.yml.example
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
---
|
||||||
|
|
||||||
|
component_skel:
|
||||||
|
pod1_containers:
|
||||||
|
belongs_to:
|
||||||
|
- pod1_all
|
||||||
|
pod1_hosts:
|
||||||
|
belongs_to:
|
||||||
|
- pod1_all
|
||||||
|
|
||||||
|
pod2_containers:
|
||||||
|
belongs_to:
|
||||||
|
- pod2_all
|
||||||
|
pod2_hosts:
|
||||||
|
belongs_to:
|
||||||
|
- pod2_all
|
||||||
|
|
||||||
|
pod3_containers:
|
||||||
|
belongs_to:
|
||||||
|
- pod3_all
|
||||||
|
pod3_hosts:
|
||||||
|
belongs_to:
|
||||||
|
- pod3_all
|
||||||
|
|
||||||
|
pod4_containers:
|
||||||
|
belongs_to:
|
||||||
|
- pod3_all
|
||||||
|
pod4_hosts:
|
||||||
|
belongs_to:
|
||||||
|
- pod3_all
|
||||||
|
|
||||||
|
container_skel:
|
||||||
|
pod1_containers:
|
||||||
|
properties:
|
||||||
|
is_nest: True
|
||||||
|
pod2_containers:
|
||||||
|
properties:
|
||||||
|
is_nest: True
|
||||||
|
pod3_containers:
|
||||||
|
properties:
|
||||||
|
is_nest: True
|
||||||
|
pod4_containers:
|
||||||
|
properties:
|
||||||
|
is_nest: True
|
@ -270,76 +270,47 @@ global_overrides:
|
|||||||
### Infrastructure
|
### Infrastructure
|
||||||
###
|
###
|
||||||
|
|
||||||
pod1_hosts:
|
pod1_hosts: &pod1
|
||||||
infra1:
|
infra1:
|
||||||
ip: 172.29.236.10
|
ip: 172.29.236.10
|
||||||
log1:
|
|
||||||
ip: 172.29.236.11
|
|
||||||
|
|
||||||
pod2_hosts:
|
pod2_hosts: &pod2
|
||||||
infra2:
|
infra2:
|
||||||
ip: 172.29.239.10
|
ip: 172.29.239.10
|
||||||
|
|
||||||
pod3_hosts:
|
pod3_hosts: &pod3
|
||||||
infra3:
|
infra3:
|
||||||
ip: 172.29.242.10
|
ip: 172.29.242.10
|
||||||
|
|
||||||
pod4_hosts:
|
pod4_hosts: &pod4
|
||||||
compute1:
|
compute1:
|
||||||
ip: 172.29.245.10
|
ip: 172.29.245.10
|
||||||
compute2:
|
compute2:
|
||||||
ip: 172.29.245.11
|
ip: 172.29.245.11
|
||||||
|
|
||||||
# galera, memcache, rabbitmq, utility
|
# galera, memcache, rabbitmq, utility
|
||||||
shared-infra_hosts:
|
shared-infra_hosts: &controllers
|
||||||
infra1:
|
<<: *pod1
|
||||||
ip: 172.29.236.10
|
<<: *pod2
|
||||||
infra2:
|
<<: *pod3
|
||||||
ip: 172.29.239.10
|
|
||||||
infra3:
|
|
||||||
ip: 172.29.242.10
|
|
||||||
|
|
||||||
# repository (apt cache, python packages, etc)
|
# repository (apt cache, python packages, etc)
|
||||||
repo-infra_hosts:
|
repo-infra_hosts: *controllers
|
||||||
infra1:
|
|
||||||
ip: 172.29.236.10
|
|
||||||
infra2:
|
|
||||||
ip: 172.29.239.10
|
|
||||||
infra3:
|
|
||||||
ip: 172.29.242.10
|
|
||||||
|
|
||||||
# load balancer
|
# load balancer
|
||||||
# Ideally the load balancer should not use the Infrastructure hosts.
|
# Ideally the load balancer should not use the Infrastructure hosts.
|
||||||
# Dedicated hardware is best for improved performance and security.
|
# Dedicated hardware is best for improved performance and security.
|
||||||
haproxy_hosts:
|
haproxy_hosts: *controllers
|
||||||
infra1:
|
|
||||||
ip: 172.29.236.10
|
|
||||||
infra2:
|
|
||||||
ip: 172.29.239.10
|
|
||||||
infra3:
|
|
||||||
ip: 172.29.242.10
|
|
||||||
|
|
||||||
###
|
###
|
||||||
### OpenStack
|
### OpenStack
|
||||||
###
|
###
|
||||||
|
|
||||||
# keystone
|
# keystone
|
||||||
identity_hosts:
|
identity_hosts: *controllers
|
||||||
infra1:
|
|
||||||
ip: 172.29.236.10
|
|
||||||
infra2:
|
|
||||||
ip: 172.29.239.10
|
|
||||||
infra3:
|
|
||||||
ip: 172.29.242.10
|
|
||||||
|
|
||||||
# cinder api services
|
# cinder api services
|
||||||
storage-infra_hosts:
|
storage-infra_hosts: *controllers
|
||||||
infra1:
|
|
||||||
ip: 172.29.236.10
|
|
||||||
infra2:
|
|
||||||
ip: 172.29.239.10
|
|
||||||
infra3:
|
|
||||||
ip: 172.29.242.10
|
|
||||||
|
|
||||||
# glance
|
# glance
|
||||||
# The settings here are repeated for each infra host.
|
# The settings here are repeated for each infra host.
|
||||||
@ -376,81 +347,30 @@ image_hosts:
|
|||||||
options: "_netdev,auto"
|
options: "_netdev,auto"
|
||||||
|
|
||||||
# nova api, conductor, etc services
|
# nova api, conductor, etc services
|
||||||
compute-infra_hosts:
|
compute-infra_hosts: *controllers
|
||||||
infra1:
|
|
||||||
ip: 172.29.236.10
|
|
||||||
infra2:
|
|
||||||
ip: 172.29.239.10
|
|
||||||
infra3:
|
|
||||||
ip: 172.29.242.10
|
|
||||||
|
|
||||||
# heat
|
# heat
|
||||||
orchestration_hosts:
|
orchestration_hosts: *controllers
|
||||||
infra1:
|
|
||||||
ip: 172.29.236.10
|
|
||||||
infra2:
|
|
||||||
ip: 172.29.239.10
|
|
||||||
infra3:
|
|
||||||
ip: 172.29.242.10
|
|
||||||
|
|
||||||
# horizon
|
# horizon
|
||||||
dashboard_hosts:
|
dashboard_hosts: *controllers
|
||||||
infra1:
|
|
||||||
ip: 172.29.236.10
|
|
||||||
infra2:
|
|
||||||
ip: 172.29.239.10
|
|
||||||
infra3:
|
|
||||||
ip: 172.29.242.10
|
|
||||||
|
|
||||||
# neutron server, agents (L3, etc)
|
# neutron server, agents (L3, etc)
|
||||||
network_hosts:
|
network_hosts: *controllers
|
||||||
infra1:
|
|
||||||
ip: 172.29.236.10
|
|
||||||
infra2:
|
|
||||||
ip: 172.29.239.10
|
|
||||||
infra3:
|
|
||||||
ip: 172.29.242.10
|
|
||||||
|
|
||||||
# ceilometer (telemetry data collection)
|
# ceilometer (telemetry data collection)
|
||||||
metering-infra_hosts:
|
metering-infra_hosts: *controllers
|
||||||
infra1:
|
|
||||||
ip: 172.29.236.10
|
|
||||||
infra2:
|
|
||||||
ip: 172.29.239.10
|
|
||||||
infra3:
|
|
||||||
ip: 172.29.242.10
|
|
||||||
|
|
||||||
# aodh (telemetry alarm service)
|
# aodh (telemetry alarm service)
|
||||||
metering-alarm_hosts:
|
metering-alarm_hosts: *controllers
|
||||||
infra1:
|
|
||||||
ip: 172.29.236.10
|
|
||||||
infra2:
|
|
||||||
ip: 172.29.239.10
|
|
||||||
infra3:
|
|
||||||
ip: 172.29.242.10
|
|
||||||
|
|
||||||
# gnocchi (telemetry metrics storage)
|
# gnocchi (telemetry metrics storage)
|
||||||
metrics_hosts:
|
metrics_hosts: *controllers
|
||||||
infra1:
|
|
||||||
ip: 172.29.236.10
|
|
||||||
infra2:
|
|
||||||
ip: 172.29.239.10
|
|
||||||
infra3:
|
|
||||||
ip: 172.29.242.10
|
|
||||||
|
|
||||||
# nova hypervisors
|
# nova hypervisors
|
||||||
compute_hosts:
|
compute_hosts: *pod4
|
||||||
compute1:
|
|
||||||
ip: 172.29.245.10
|
|
||||||
compute2:
|
|
||||||
ip: 172.29.245.11
|
|
||||||
|
|
||||||
# ceilometer compute agent (telemetry data collection)
|
# ceilometer compute agent (telemetry data collection)
|
||||||
metering-compute_hosts:
|
metering-compute_hosts: *pod4
|
||||||
compute1:
|
|
||||||
ip: 172.29.245.10
|
|
||||||
compute2:
|
|
||||||
ip: 172.29.245.11
|
|
||||||
|
|
||||||
# cinder volume hosts (NFS-backed)
|
# cinder volume hosts (NFS-backed)
|
||||||
# The settings here are repeated for each infra host.
|
# The settings here are repeated for each infra host.
|
||||||
|
@ -712,8 +712,9 @@ def container_skel_load(container_skel, inventory, config):
|
|||||||
logger.debug("Loading container skeleton")
|
logger.debug("Loading container skeleton")
|
||||||
|
|
||||||
for key, value in container_skel.items():
|
for key, value in container_skel.items():
|
||||||
contains_in = value.get('contains', False)
|
contains_in = value.get('contains', list())
|
||||||
belongs_to_in = value.get('belongs_to', False)
|
belongs_to_in = value.get('belongs_to', list())
|
||||||
|
properties = value.get('properties', {})
|
||||||
|
|
||||||
if belongs_to_in:
|
if belongs_to_in:
|
||||||
_parse_belongs_to(
|
_parse_belongs_to(
|
||||||
@ -721,18 +722,25 @@ def container_skel_load(container_skel, inventory, config):
|
|||||||
belongs_to=value['belongs_to'],
|
belongs_to=value['belongs_to'],
|
||||||
inventory=inventory
|
inventory=inventory
|
||||||
)
|
)
|
||||||
|
if properties.get('is_nest', False):
|
||||||
|
physical_host_type = '{}_hosts'.format(key.split('_')[0])
|
||||||
|
for host_type in inventory[physical_host_type]['hosts']:
|
||||||
|
container_mapping = inventory[key]['children']
|
||||||
|
host_type_containers = '{}-host_containers'.format(host_type)
|
||||||
|
if host_type_containers in inventory:
|
||||||
|
du.append_if(array=container_mapping,
|
||||||
|
item=host_type_containers)
|
||||||
|
|
||||||
if contains_in or belongs_to_in:
|
for assignment in contains_in:
|
||||||
for assignment in value['contains']:
|
for container_type in belongs_to_in:
|
||||||
for container_type in value['belongs_to']:
|
_add_container_hosts(
|
||||||
_add_container_hosts(
|
assignment,
|
||||||
assignment,
|
config,
|
||||||
config,
|
key,
|
||||||
key,
|
container_type,
|
||||||
container_type,
|
inventory,
|
||||||
inventory,
|
properties
|
||||||
value.get('properties', {})
|
)
|
||||||
)
|
|
||||||
|
|
||||||
cidr_networks = config.get('cidr_networks')
|
cidr_networks = config.get('cidr_networks')
|
||||||
provider_queues = {}
|
provider_queues = {}
|
||||||
|
@ -1559,5 +1559,62 @@ class TestL3ProviderNetworkConfig(TestConfigCheckBase):
|
|||||||
self.assertNotIn('management_address', aio1_container_networks)
|
self.assertNotIn('management_address', aio1_container_networks)
|
||||||
|
|
||||||
|
|
||||||
|
class TestNestsGroups(TestConfigCheckBase):
|
||||||
|
def setUp(self):
|
||||||
|
super(TestNestsGroups, self).setUp()
|
||||||
|
self.nest_env_path = path.join(TARGET_DIR, 'env.d/az.yml')
|
||||||
|
self._create_nest_env()
|
||||||
|
self.add_config_key('nest_hosts', {})
|
||||||
|
self.add_host('nest_hosts', 'aio1', '172.29.236.100')
|
||||||
|
self.add_host('nest_hosts', 'aio2', '172.29.236.101')
|
||||||
|
self.add_host('compute_hosts', 'aio2', '172.29.236.101')
|
||||||
|
self.write_config()
|
||||||
|
self.inventory = get_inventory()
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
os.remove(self.nest_env_path)
|
||||||
|
os.rmdir(os.path.dirname(self.nest_env_path))
|
||||||
|
|
||||||
|
def _create_nest_env(self):
|
||||||
|
data = """
|
||||||
|
component_skel:
|
||||||
|
nest_containers:
|
||||||
|
belongs_to:
|
||||||
|
- nest_all
|
||||||
|
nest_hosts:
|
||||||
|
belongs_to:
|
||||||
|
- nest_all
|
||||||
|
|
||||||
|
container_skel:
|
||||||
|
nest_containers:
|
||||||
|
properties:
|
||||||
|
is_nest: True
|
||||||
|
"""
|
||||||
|
env = yaml.safe_load(data)
|
||||||
|
os.mkdir(os.path.dirname(self.nest_env_path))
|
||||||
|
with open(self.nest_env_path, 'w') as f:
|
||||||
|
f.write(yaml.safe_dump(env))
|
||||||
|
|
||||||
|
def test_nest_all_childrens(self):
|
||||||
|
nest_expected_children = set(['nest_containers', 'nest_hosts'])
|
||||||
|
nest_children = set(self.inventory['nest_all']['children'])
|
||||||
|
self.assertEqual(nest_expected_children, nest_children)
|
||||||
|
|
||||||
|
def test_nest_hosts(self):
|
||||||
|
nest_hosts_expected = set(['aio1', 'aio2'])
|
||||||
|
nest_hosts = set(self.inventory['nest_hosts']['hosts'])
|
||||||
|
self.assertEqual(nest_hosts_expected, nest_hosts)
|
||||||
|
|
||||||
|
def test_nest_containers(self):
|
||||||
|
host_containers_group = 'aio1-host_containers'
|
||||||
|
nest_containers_expected = set([host_containers_group])
|
||||||
|
nest_containers = set(self.inventory['nest_containers']['children'])
|
||||||
|
# Ensure we have only lxc_hosts in children
|
||||||
|
self.assertEqual(nest_containers_expected, nest_containers)
|
||||||
|
# Ensure that we have host-containers group generated
|
||||||
|
self.assertIn(host_containers_group, self.inventory)
|
||||||
|
# Ensure that host-containers group is not empty
|
||||||
|
self.assertTrue(len(self.inventory[host_containers_group]['hosts']) > 0)
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
unittest.main(catchbreak=True)
|
unittest.main(catchbreak=True)
|
||||||
|
Loading…
Reference in New Issue
Block a user