Only create a server group when affinity is set
Also adds docs so a user can find this behaviour easily. Closes-Bug: #2071832 Change-Id: Iea3c4164f3e893c355ec21653f2e8f0e848941f0
This commit is contained in:
parent
3999bf1fb7
commit
c80d519998
@ -317,7 +317,8 @@ class VirtualInstancePlugin(base.BasePlugin, nova.NovaClientWrapper):
|
|||||||
|
|
||||||
return {'added': added_host_ids, 'removed': removed_host_ids}
|
return {'added': added_host_ids, 'removed': removed_host_ids}
|
||||||
|
|
||||||
def _create_flavor(self, reservation_id, vcpus, memory, disk, group_id):
|
def _create_flavor(self, reservation_id, vcpus, memory, disk,
|
||||||
|
group_id=None):
|
||||||
flavor_details = {
|
flavor_details = {
|
||||||
'flavorid': reservation_id,
|
'flavorid': reservation_id,
|
||||||
'name': RESERVATION_PREFIX + ":" + reservation_id,
|
'name': RESERVATION_PREFIX + ":" + reservation_id,
|
||||||
@ -333,9 +334,10 @@ class VirtualInstancePlugin(base.BasePlugin, nova.NovaClientWrapper):
|
|||||||
reservation_rc = "resources:CUSTOM_RESERVATION_" + rsv_id_rc_format
|
reservation_rc = "resources:CUSTOM_RESERVATION_" + rsv_id_rc_format
|
||||||
extra_specs = {
|
extra_specs = {
|
||||||
FLAVOR_EXTRA_SPEC: reservation_id,
|
FLAVOR_EXTRA_SPEC: reservation_id,
|
||||||
"affinity_id": group_id,
|
|
||||||
reservation_rc: "1"
|
reservation_rc: "1"
|
||||||
}
|
}
|
||||||
|
if group_id is not None:
|
||||||
|
extra_specs["affinity_id"] = group_id
|
||||||
reserved_flavor.set_keys(extra_specs)
|
reserved_flavor.set_keys(extra_specs)
|
||||||
|
|
||||||
return reserved_flavor
|
return reserved_flavor
|
||||||
@ -346,23 +348,31 @@ class VirtualInstancePlugin(base.BasePlugin, nova.NovaClientWrapper):
|
|||||||
ctx = context.current()
|
ctx = context.current()
|
||||||
user_client = nova.NovaClientWrapper()
|
user_client = nova.NovaClientWrapper()
|
||||||
|
|
||||||
reserved_group = user_client.nova.server_groups.create(
|
flavor_args = {
|
||||||
RESERVATION_PREFIX + ':' + reservation_id,
|
'reservation_id': reservation_id,
|
||||||
'affinity' if inst_reservation['affinity'] else 'anti-affinity'
|
'vcpus': inst_reservation['vcpus'],
|
||||||
)
|
'memory': inst_reservation['memory_mb'],
|
||||||
|
'disk': inst_reservation['disk_gb']
|
||||||
|
}
|
||||||
|
|
||||||
reserved_flavor = self._create_flavor(reservation_id,
|
|
||||||
inst_reservation['vcpus'],
|
|
||||||
inst_reservation['memory_mb'],
|
|
||||||
inst_reservation['disk_gb'],
|
|
||||||
reserved_group.id)
|
|
||||||
|
|
||||||
pool = nova.ReservationPool()
|
|
||||||
pool_metadata = {
|
pool_metadata = {
|
||||||
RESERVATION_PREFIX: reservation_id,
|
RESERVATION_PREFIX: reservation_id,
|
||||||
'filter_tenant_id': ctx.project_id,
|
'filter_tenant_id': ctx.project_id,
|
||||||
'affinity_id': reserved_group.id
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if inst_reservation['affinity'] is not None:
|
||||||
|
reserved_group = user_client.nova.server_groups.create(
|
||||||
|
RESERVATION_PREFIX + ':' + reservation_id,
|
||||||
|
'affinity' if inst_reservation['affinity'] else 'anti-affinity'
|
||||||
|
)
|
||||||
|
flavor_args['group_id'] = reserved_group.id
|
||||||
|
pool_metadata['affinity_id'] = reserved_group.id
|
||||||
|
else:
|
||||||
|
reserved_group = None
|
||||||
|
|
||||||
|
reserved_flavor = self._create_flavor(**flavor_args)
|
||||||
|
|
||||||
|
pool = nova.ReservationPool()
|
||||||
agg = pool.create(name=reservation_id, metadata=pool_metadata)
|
agg = pool.create(name=reservation_id, metadata=pool_metadata)
|
||||||
|
|
||||||
self.placement_client.create_reservation_class(reservation_id)
|
self.placement_client.create_reservation_class(reservation_id)
|
||||||
@ -483,9 +493,10 @@ class VirtualInstancePlugin(base.BasePlugin, nova.NovaClientWrapper):
|
|||||||
self.cleanup_resources(instance_reservation)
|
self.cleanup_resources(instance_reservation)
|
||||||
raise mgr_exceptions.NovaClientError()
|
raise mgr_exceptions.NovaClientError()
|
||||||
|
|
||||||
|
server_group_id = group.id if group is not None else None
|
||||||
db_api.instance_reservation_update(instance_reservation['id'],
|
db_api.instance_reservation_update(instance_reservation['id'],
|
||||||
{'flavor_id': flavor.id,
|
{'flavor_id': flavor.id,
|
||||||
'server_group_id': group.id,
|
'server_group_id': server_group_id,
|
||||||
'aggregate_id': pool.id})
|
'aggregate_id': pool.id})
|
||||||
|
|
||||||
return instance_reservation['id']
|
return instance_reservation['id']
|
||||||
|
@ -410,6 +410,61 @@ class TestVirtualInstancePlugin(tests.TestCase):
|
|||||||
expected_query = ['vcpus >= 2', 'memory_mb >= 2048', 'local_gb >= 100']
|
expected_query = ['vcpus >= 2', 'memory_mb >= 2048', 'local_gb >= 100']
|
||||||
mock_host_get_query.assert_called_once_with(expected_query)
|
mock_host_get_query.assert_called_once_with(expected_query)
|
||||||
|
|
||||||
|
def test_pickup_host_with_anti_affinity(self):
|
||||||
|
def fake_get_reservation_by_host(host_id, start, end):
|
||||||
|
if host_id in ['host-1', 'host-3']:
|
||||||
|
return [
|
||||||
|
{'id': '1',
|
||||||
|
'resource_type': instances.RESOURCE_TYPE},
|
||||||
|
{'id': '2',
|
||||||
|
'resource_type': instances.RESOURCE_TYPE}
|
||||||
|
]
|
||||||
|
else:
|
||||||
|
return []
|
||||||
|
|
||||||
|
plugin = instance_plugin.VirtualInstancePlugin()
|
||||||
|
|
||||||
|
mock_host_allocation_get = self.patch(
|
||||||
|
db_api, 'host_allocation_get_all_by_values')
|
||||||
|
mock_host_allocation_get.return_value = []
|
||||||
|
|
||||||
|
mock_host_get_query = self.patch(db_api,
|
||||||
|
'reservable_host_get_all_by_queries')
|
||||||
|
hosts_list = [self.generate_host_info('host-1', 8, 8192, 1000),
|
||||||
|
self.generate_host_info('host-2', 2, 2048, 500)]
|
||||||
|
mock_host_get_query.return_value = hosts_list
|
||||||
|
|
||||||
|
mock_get_reservations = self.patch(db_utils,
|
||||||
|
'get_reservations_by_host_id')
|
||||||
|
|
||||||
|
mock_get_reservations.side_effect = fake_get_reservation_by_host
|
||||||
|
|
||||||
|
mock_max_usages = self.patch(plugin, 'max_usages')
|
||||||
|
mock_max_usages.return_value = (0, 0, 0)
|
||||||
|
|
||||||
|
mock_reservation_get = self.patch(db_api, 'reservation_get')
|
||||||
|
mock_reservation_get.return_value = {
|
||||||
|
'status': 'pending'
|
||||||
|
}
|
||||||
|
|
||||||
|
params = {
|
||||||
|
'vcpus': 2,
|
||||||
|
'memory_mb': 2048,
|
||||||
|
'disk_gb': 100,
|
||||||
|
'amount': 2,
|
||||||
|
'affinity': False,
|
||||||
|
'resource_properties': '',
|
||||||
|
'start_date': datetime.datetime(2030, 1, 1, 8, 00),
|
||||||
|
'end_date': datetime.datetime(2030, 1, 1, 12, 00)
|
||||||
|
}
|
||||||
|
|
||||||
|
expected = {'added': ['host-1', 'host-2'], 'removed': []}
|
||||||
|
ret = plugin.pickup_hosts('reservation-id1', params)
|
||||||
|
|
||||||
|
self.assertEqual(expected, ret)
|
||||||
|
expected_query = ['vcpus >= 2', 'memory_mb >= 2048', 'local_gb >= 100']
|
||||||
|
mock_host_get_query.assert_called_once_with(expected_query)
|
||||||
|
|
||||||
@ddt.data('None', 'none', None)
|
@ddt.data('None', 'none', None)
|
||||||
def test_pickup_host_with_no_affinity(self, value):
|
def test_pickup_host_with_no_affinity(self, value):
|
||||||
def fake_get_reservation_by_host(host_id, start, end):
|
def fake_get_reservation_by_host(host_id, start, end):
|
||||||
|
@ -166,3 +166,20 @@ Result:
|
|||||||
openstack server create --flavor db83d6fd-c69c-4259-92cf-012db2e55a58 --image <image> --network <network> <server-name>
|
openstack server create --flavor db83d6fd-c69c-4259-92cf-012db2e55a58 --image <image> --network <network> <server-name>
|
||||||
|
|
||||||
..
|
..
|
||||||
|
|
||||||
|
|
||||||
|
Affinity
|
||||||
|
--------
|
||||||
|
|
||||||
|
A lease can be created with the optional ``--affinity`` parameter. This
|
||||||
|
provides the following behavior:
|
||||||
|
|
||||||
|
* ``affinity=True``: Instances will be deployed on the same host for this
|
||||||
|
reservation, by adding them to a server group with an affinity policy.
|
||||||
|
|
||||||
|
* ``affinity=False``: Instances will be deployed on different hosts for this
|
||||||
|
reservation, by adding them to a server group with an anti-affinity policy.
|
||||||
|
|
||||||
|
* ``affinity=None`` (default): Instances can be deployed on any host,
|
||||||
|
regardless of other instances in this reservation. No server group is
|
||||||
|
created.
|
||||||
|
@ -0,0 +1,14 @@
|
|||||||
|
---
|
||||||
|
upgrade:
|
||||||
|
- |
|
||||||
|
Instance reservations will no longer create a server group when the
|
||||||
|
``affinity`` parameter is not set. This means that instances can be
|
||||||
|
deployed on any host. To achieve the old behaviour, you must now explicity
|
||||||
|
set ``--affinity=false``.
|
||||||
|
`LP#2071832 <https://launchpad.net/bugs/2071832>`__
|
||||||
|
fixes:
|
||||||
|
- |
|
||||||
|
Instance reservations will no longer create a server group when the
|
||||||
|
``affinity`` parameter is not set. This means that instances can be
|
||||||
|
deployed on any host.
|
||||||
|
`LP#2071832 <https://launchpad.net/bugs/2071832>`__
|
Loading…
Reference in New Issue
Block a user