1207 lines
50 KiB
Python
1207 lines
50 KiB
Python
# Copyright (c) 2017 NTT.
|
|
#
|
|
# 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.
|
|
|
|
import datetime
|
|
import uuid
|
|
|
|
import mock
|
|
import six
|
|
|
|
from blazar import context
|
|
from blazar.db import api as db_api
|
|
from blazar.db import utils as db_utils
|
|
from blazar.manager import exceptions as mgr_exceptions
|
|
from blazar.plugins import instances
|
|
from blazar.plugins.instances import instance_plugin
|
|
from blazar.plugins import oshosts
|
|
from blazar import tests
|
|
from blazar.utils.openstack import nova
|
|
from oslo_config import cfg
|
|
from oslo_config import fixture as conf_fixture
|
|
|
|
CONF = cfg.CONF
|
|
|
|
|
|
class TestVirtualInstancePlugin(tests.TestCase):
|
|
|
|
def setUp(self):
|
|
super(TestVirtualInstancePlugin, self).setUp()
|
|
|
|
def test_configuration(self):
|
|
self.cfg = self.useFixture(conf_fixture.Config(CONF))
|
|
self.cfg.config(os_admin_username='fake-user')
|
|
self.cfg.config(os_admin_password='fake-passwd')
|
|
self.cfg.config(os_admin_user_domain_name='fake-user-domain')
|
|
self.cfg.config(os_admin_project_name='fake-pj-name')
|
|
self.cfg.config(os_admin_project_domain_name='fake-pj-domain')
|
|
plugin = instance_plugin.VirtualInstancePlugin()
|
|
self.assertEqual("fake-user", plugin.username)
|
|
self.assertEqual("fake-passwd", plugin.password)
|
|
self.assertEqual("fake-user-domain", plugin.user_domain_name)
|
|
self.assertEqual("fake-pj-name", plugin.project_name)
|
|
self.assertEqual("fake-pj-domain", plugin.project_domain_name)
|
|
|
|
def get_input_values(self, vcpus, memory, disk, amount, affinity,
|
|
start, end, lease_id, resource_properties):
|
|
values = {'vcpus': vcpus, 'memory_mb': memory, 'disk_gb': disk,
|
|
'amount': amount, 'affinity': affinity, 'start_date': start,
|
|
'end_date': end, 'lease_id': lease_id,
|
|
'resource_properties': resource_properties}
|
|
return values
|
|
|
|
def generate_host_info(self, id, vcpus, memory, disk):
|
|
return {'id': id, 'vcpus': vcpus,
|
|
'memory_mb': memory, 'local_gb': disk}
|
|
|
|
def generate_event(self, id, lease_id, event_type, time, status='UNDONE'):
|
|
return {
|
|
'id': id,
|
|
'lease_id': lease_id,
|
|
'event_type': event_type,
|
|
'time': time,
|
|
'status': status
|
|
}
|
|
|
|
def get_uuid(self):
|
|
return six.text_type(str(uuid.uuid4()))
|
|
|
|
def generate_basic_events(self, lease_id, start, before_end, end):
|
|
return [
|
|
self.generate_event(self.get_uuid(), lease_id, 'start_lease',
|
|
datetime.datetime.strptime(start,
|
|
'%Y-%m-%d %H:%M')),
|
|
self.generate_event(self.get_uuid(), lease_id, 'before_end_lease',
|
|
datetime.datetime.strptime(before_end,
|
|
'%Y-%m-%d %H:%M')),
|
|
self.generate_event(self.get_uuid(), lease_id, 'end_lease',
|
|
datetime.datetime.strptime(end,
|
|
'%Y-%m-%d %H:%M')),
|
|
]
|
|
|
|
def test_reserve_resource(self):
|
|
plugin = instance_plugin.VirtualInstancePlugin()
|
|
mock_pickup_hosts = self.patch(plugin, 'pickup_hosts')
|
|
mock_pickup_hosts.return_value = {'added': ['host1', 'host2'],
|
|
'removed': []}
|
|
|
|
mock_inst_create = self.patch(db_api, 'instance_reservation_create')
|
|
fake_instance_reservation = {'id': 'instance-reservation-id1'}
|
|
mock_inst_create.return_value = fake_instance_reservation
|
|
|
|
mock_alloc_create = self.patch(db_api, 'host_allocation_create')
|
|
|
|
mock_create_resources = self.patch(plugin, '_create_resources')
|
|
mock_flavor = mock.MagicMock(id=1)
|
|
mock_group = mock.MagicMock(id=2)
|
|
mock_pool = mock.MagicMock(id=3)
|
|
mock_create_resources.return_value = (mock_flavor,
|
|
mock_group, mock_pool)
|
|
|
|
mock_inst_update = self.patch(db_api, 'instance_reservation_update')
|
|
|
|
inputs = self.get_input_values(2, 4018, 10, 1, False,
|
|
'2030-01-01 08:00', '2030-01-01 08:00',
|
|
'lease-1', '')
|
|
|
|
expected_ret = 'instance-reservation-id1'
|
|
|
|
ret = plugin.reserve_resource('res_id1', inputs)
|
|
|
|
self.assertEqual(expected_ret, ret)
|
|
pickup_hosts_value = {}
|
|
for key in ['vcpus', 'memory_mb', 'disk_gb', 'amount', 'affinity',
|
|
'lease_id', 'start_date', 'end_date',
|
|
'resource_properties']:
|
|
pickup_hosts_value[key] = inputs[key]
|
|
mock_pickup_hosts.assert_called_once_with('res_id1',
|
|
pickup_hosts_value)
|
|
|
|
mock_alloc_create.assert_any_call({'compute_host_id': 'host1',
|
|
'reservation_id': 'res_id1'})
|
|
mock_alloc_create.assert_any_call({'compute_host_id': 'host2',
|
|
'reservation_id': 'res_id1'})
|
|
mock_create_resources.assert_called_once_with(
|
|
fake_instance_reservation)
|
|
mock_inst_update.assert_called_once_with('instance-reservation-id1',
|
|
{'flavor_id': 1,
|
|
'server_group_id': 2,
|
|
'aggregate_id': 3})
|
|
|
|
def test_error_with_affinity(self):
|
|
plugin = instance_plugin.VirtualInstancePlugin()
|
|
inputs = self.get_input_values(2, 4018, 10, 1, True,
|
|
'2030-01-01 08:00', '2030-01-01 08:00',
|
|
'lease-1', '')
|
|
self.assertRaises(mgr_exceptions.MalformedParameter,
|
|
plugin.reserve_resource, 'reservation_id', inputs)
|
|
self.assertRaises(mgr_exceptions.MalformedParameter,
|
|
plugin.update_reservation, 'reservation_id', inputs)
|
|
|
|
def test_filter_hosts_by_reservation_with_exclude(self):
|
|
def fake_get_reservation_by_host(host_id, start, end):
|
|
if host_id == 'host-1':
|
|
return [
|
|
{'id': '1',
|
|
'resource_type': instances.RESOURCE_TYPE}]
|
|
else:
|
|
return []
|
|
|
|
hosts_list = [self.generate_host_info('host-1', 4, 4096, 1000),
|
|
self.generate_host_info('host-2', 4, 4096, 1000),
|
|
self.generate_host_info('host-3', 4, 4096, 1000)]
|
|
mock_get_reservations = self.patch(db_utils,
|
|
'get_reservations_by_host_id')
|
|
|
|
mock_get_reservations.side_effect = fake_get_reservation_by_host
|
|
free = [{'host': hosts_list[0], 'reservations': None},
|
|
{'host': hosts_list[1], 'reservations': None},
|
|
{'host': hosts_list[2], 'reservations': None}]
|
|
non_free = []
|
|
|
|
plugin = instance_plugin.VirtualInstancePlugin()
|
|
ret = plugin.filter_hosts_by_reservation(hosts_list,
|
|
'2030-01-01 08:00',
|
|
'2030-01-01 12:00', ['1'])
|
|
self.assertEqual(free, ret[0])
|
|
self.assertEqual(non_free, ret[1])
|
|
|
|
def test_pickup_host_from_reserved_hosts(self):
|
|
def fake_max_usages(host, reservations):
|
|
if host['id'] == 'host-1':
|
|
return 4, 4096, 2000
|
|
else:
|
|
return 0, 0, 0
|
|
|
|
def fake_get_reservation_by_host(host_id, start, end):
|
|
return [
|
|
{'id': '1', 'resource_type': instances.RESOURCE_TYPE},
|
|
{'id': '2', 'resource_type': instances.RESOURCE_TYPE}]
|
|
|
|
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', 4, 4096, 1000),
|
|
self.generate_host_info('host-2', 4, 4096, 1000),
|
|
self.generate_host_info('host-3', 4, 4096, 1000)]
|
|
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
|
|
plugin.max_usages = fake_max_usages
|
|
|
|
mock_reservation_get = self.patch(db_api, 'reservation_get')
|
|
mock_reservation_get.return_value = {
|
|
'status': 'pending'
|
|
}
|
|
|
|
values = {
|
|
'vcpus': 1,
|
|
'memory_mb': 1024,
|
|
'disk_gb': 20,
|
|
'amount': 2,
|
|
'resource_properties': '',
|
|
'start_date': datetime.datetime(2030, 1, 1, 8, 00),
|
|
'end_date': datetime.datetime(2030, 1, 1, 12, 00)
|
|
}
|
|
expected = {'added': set(['host-2', 'host-3']), 'removed': set([])}
|
|
ret = plugin.pickup_hosts('reservation-id1', values)
|
|
|
|
self.assertEqual(expected, ret)
|
|
expected_query = ['vcpus >= 1', 'memory_mb >= 1024', 'local_gb >= 20']
|
|
mock_host_get_query.assert_called_once_with(expected_query)
|
|
|
|
def test_pickup_host_from_free_hosts(self):
|
|
def fake_get_reservation_by_host(host_id, start, end):
|
|
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', 4, 4096, 1000),
|
|
self.generate_host_info('host-2', 4, 4096, 1000),
|
|
self.generate_host_info('host-3', 4, 4096, 1000)]
|
|
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_reservation_get = self.patch(db_api, 'reservation_get')
|
|
mock_reservation_get.return_value = {
|
|
'status': 'pending'
|
|
}
|
|
|
|
values = {
|
|
'vcpus': 1,
|
|
'memory_mb': 1024,
|
|
'disk_gb': 20,
|
|
'amount': 2,
|
|
'resource_properties': '',
|
|
'start_date': datetime.datetime(2030, 1, 1, 8, 00),
|
|
'end_date': datetime.datetime(2030, 1, 1, 12, 00),
|
|
}
|
|
expected = {'added': set(['host-1', 'host-2']), 'removed': set([])}
|
|
ret = plugin.pickup_hosts('reservation-id1', values)
|
|
|
|
self.assertEqual(expected, ret)
|
|
expected_query = ['vcpus >= 1', 'memory_mb >= 1024', 'local_gb >= 20']
|
|
mock_host_get_query.assert_called_once_with(expected_query)
|
|
|
|
def test_pickup_host_from_free_and_reserved_host(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', 4, 4096, 1000),
|
|
self.generate_host_info('host-2', 4, 4096, 1000),
|
|
self.generate_host_info('host-3', 4, 4096, 1000)]
|
|
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': 1,
|
|
'memory_mb': 1024,
|
|
'disk_gb': 20,
|
|
'amount': 2,
|
|
'resource_properties': '',
|
|
'start_date': datetime.datetime(2030, 1, 1, 8, 00),
|
|
'end_date': datetime.datetime(2030, 1, 1, 12, 00)
|
|
}
|
|
|
|
expected = {'added': set(['host-1', 'host-3']), 'removed': set([])}
|
|
ret = plugin.pickup_hosts('reservation-id1', params)
|
|
|
|
self.assertEqual(expected, ret)
|
|
expected_query = ['vcpus >= 1', 'memory_mb >= 1024', 'local_gb >= 20']
|
|
mock_host_get_query.assert_called_once_with(expected_query)
|
|
|
|
def test_pickup_host_from_less_hosts(self):
|
|
def fake_get_reservation_by_host(host_id, start, end):
|
|
if host_id in ['host-1', 'host-3']:
|
|
return [
|
|
{'id': '1',
|
|
'resource_type': oshosts.RESOURCE_TYPE},
|
|
{'id': '2',
|
|
'resource_type': instances.RESOURCE_TYPE}
|
|
]
|
|
else:
|
|
return [
|
|
{'id': '1',
|
|
'resource_type': instances.RESOURCE_TYPE},
|
|
{'id': '2',
|
|
'resource_type': instances.RESOURCE_TYPE}
|
|
]
|
|
|
|
plugin = instance_plugin.VirtualInstancePlugin()
|
|
|
|
mock_host_get_query = self.patch(db_api,
|
|
'reservable_host_get_all_by_queries')
|
|
hosts_list = [self.generate_host_info('host-1', 4, 4096, 1000),
|
|
self.generate_host_info('host-2', 4, 4096, 1000),
|
|
self.generate_host_info('host-3', 4, 4096, 1000)]
|
|
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_host_allocation_get = self.patch(
|
|
db_api, 'host_allocation_get_all_by_values')
|
|
mock_host_allocation_get.return_value = []
|
|
|
|
mock_max_usages = self.patch(plugin, 'max_usages')
|
|
mock_max_usages.return_value = (1, 1024, 100)
|
|
|
|
values = {
|
|
'vcpus': 1,
|
|
'memory_mb': 1024,
|
|
'disk_gb': 20,
|
|
'amount': 2,
|
|
'resource_properties': '',
|
|
'start_date': datetime.datetime(2030, 1, 1, 8, 00),
|
|
'end_date': datetime.datetime(2030, 1, 1, 12, 00)
|
|
}
|
|
|
|
hosts = plugin.pickup_hosts('reservation-id1', values)
|
|
self.assertTrue((len(hosts['added']) - len(hosts['removed']))
|
|
< values['amount'])
|
|
|
|
def test_max_usage_with_serial_reservation(self):
|
|
def fake_event_get(sort_key, sort_dir, filters):
|
|
if filters['lease_id'] == 'lease-1':
|
|
return self.generate_basic_events('lease-1',
|
|
'2030-01-01 08:00',
|
|
'2030-01-01 10:00',
|
|
'2030-01-01 11:00')
|
|
elif filters['lease_id'] == 'lease-2':
|
|
return self.generate_basic_events('lease-2',
|
|
'2030-01-01 12:00',
|
|
'2030-01-01 13:00',
|
|
'2030-01-01 14:00')
|
|
|
|
plugin = instance_plugin.VirtualInstancePlugin()
|
|
reservations = [
|
|
{
|
|
'lease_id': 'lease-1',
|
|
'instance_reservations': {
|
|
'vcpus': 2, 'memory_mb': 3072, 'disk_gb': 20}},
|
|
{
|
|
'lease_id': 'lease-2',
|
|
'instance_reservations': {
|
|
'vcpus': 3, 'memory_mb': 2048, 'disk_gb': 30}}
|
|
]
|
|
|
|
mock_event_get = self.patch(db_api, 'event_get_all_sorted_by_filters')
|
|
mock_event_get.side_effect = fake_event_get
|
|
|
|
expected = (3, 3072, 30)
|
|
ret = plugin.max_usages('fake-host', reservations)
|
|
|
|
self.assertEqual(expected, ret)
|
|
|
|
def test_max_usage_with_parallel_reservation(self):
|
|
def fake_event_get(sort_key, sort_dir, filters):
|
|
if filters['lease_id'] == 'lease-1':
|
|
return self.generate_basic_events('lease-1',
|
|
'2030-01-01 08:00',
|
|
'2030-01-01 10:00',
|
|
'2030-01-01 11:00')
|
|
elif filters['lease_id'] == 'lease-2':
|
|
return self.generate_basic_events('lease-2',
|
|
'2030-01-01 10:00',
|
|
'2030-01-01 13:00',
|
|
'2030-01-01 14:00')
|
|
|
|
plugin = instance_plugin.VirtualInstancePlugin()
|
|
reservations = [
|
|
{
|
|
'lease_id': 'lease-1',
|
|
'instance_reservations': {
|
|
'vcpus': 2, 'memory_mb': 3072, 'disk_gb': 20}},
|
|
{
|
|
'lease_id': 'lease-2',
|
|
'instance_reservations': {
|
|
'vcpus': 3, 'memory_mb': 2048, 'disk_gb': 30}},
|
|
]
|
|
|
|
mock_event_get = self.patch(db_api, 'event_get_all_sorted_by_filters')
|
|
mock_event_get.side_effect = fake_event_get
|
|
|
|
expected = (5, 5120, 50)
|
|
ret = plugin.max_usages('fake-host', reservations)
|
|
|
|
self.assertEqual(expected, ret)
|
|
|
|
def test_max_usage_with_multi_reservation(self):
|
|
def fake_event_get(sort_key, sort_dir, filters):
|
|
if filters['lease_id'] == 'lease-1':
|
|
return self.generate_basic_events('lease-1',
|
|
'2030-01-01 08:00',
|
|
'2030-01-01 10:00',
|
|
'2030-01-01 11:00')
|
|
|
|
plugin = instance_plugin.VirtualInstancePlugin()
|
|
reservations = [
|
|
{
|
|
'lease_id': 'lease-1',
|
|
'instance_reservations': {
|
|
'vcpus': 2, 'memory_mb': 3072, 'disk_gb': 20}},
|
|
{
|
|
'lease_id': 'lease-1',
|
|
'instance_reservations': {
|
|
'vcpus': 3, 'memory_mb': 2048, 'disk_gb': 30}},
|
|
]
|
|
|
|
mock_event_get = self.patch(db_api, 'event_get_all_sorted_by_filters')
|
|
mock_event_get.side_effect = fake_event_get
|
|
|
|
expected = (5, 5120, 50)
|
|
ret = plugin.max_usages('fake-host', reservations)
|
|
|
|
self.assertEqual(expected, ret)
|
|
|
|
def test_max_usage_with_decrease_reservation(self):
|
|
def fake_event_get(sort_key, sort_dir, filters):
|
|
if filters['lease_id'] == 'lease-1':
|
|
return self.generate_basic_events('lease-1',
|
|
'2030-01-01 08:00',
|
|
'2030-01-01 10:00',
|
|
'2030-01-01 11:00')
|
|
elif filters['lease_id'] == 'lease-2':
|
|
return self.generate_basic_events('lease-2',
|
|
'2030-01-01 10:00',
|
|
'2030-01-01 13:00',
|
|
'2030-01-01 14:00')
|
|
elif filters['lease_id'] == 'lease-3':
|
|
return self.generate_basic_events('lease-3',
|
|
'2030-01-01 15:00',
|
|
'2030-01-01 16:00',
|
|
'2030-01-01 17:00')
|
|
|
|
plugin = instance_plugin.VirtualInstancePlugin()
|
|
reservations = [
|
|
{
|
|
'lease_id': 'lease-1',
|
|
'instance_reservations': {
|
|
'vcpus': 2, 'memory_mb': 3072, 'disk_gb': 20}},
|
|
{
|
|
'lease_id': 'lease-2',
|
|
'instance_reservations': {
|
|
'vcpus': 1, 'memory_mb': 1024, 'disk_gb': 10}},
|
|
{
|
|
'lease_id': 'lease-3',
|
|
'instance_reservations': {
|
|
'vcpus': 4, 'memory_mb': 2048, 'disk_gb': 40
|
|
}},
|
|
]
|
|
|
|
mock_event_get = self.patch(db_api, 'event_get_all_sorted_by_filters')
|
|
mock_event_get.side_effect = fake_event_get
|
|
|
|
expected = (4, 4096, 40)
|
|
ret = plugin.max_usages('fake-host', reservations)
|
|
|
|
self.assertEqual(expected, ret)
|
|
|
|
def test_create_resources(self):
|
|
instance_reservation = {
|
|
'reservation_id': 'reservation-id1',
|
|
'vcpus': 2,
|
|
'memory_mb': 1024,
|
|
'disk_gb': 20,
|
|
'affinity': False
|
|
}
|
|
|
|
plugin = instance_plugin.VirtualInstancePlugin()
|
|
|
|
fake_client = mock.MagicMock()
|
|
mock_nova_client = self.patch(nova, 'NovaClientWrapper')
|
|
mock_nova_client.return_value = fake_client
|
|
fake_server_group = mock.MagicMock(id='server_group_id1')
|
|
fake_client.nova.server_groups.create.return_value = \
|
|
fake_server_group
|
|
|
|
self.set_context(context.BlazarContext(project_id='fake-project',
|
|
auth_token='fake-token'))
|
|
fake_flavor = mock.MagicMock(method='set_keys',
|
|
flavorid='reservation-id1')
|
|
mock_nova = mock.MagicMock()
|
|
type(plugin).nova = mock_nova
|
|
mock_nova.nova.flavors.create.return_value = fake_flavor
|
|
|
|
fake_pool = mock.MagicMock(id='pool-id1')
|
|
fake_agg = mock.MagicMock()
|
|
fake_pool.create.return_value = fake_agg
|
|
mock_pool = self.patch(nova, 'ReservationPool')
|
|
mock_pool.return_value = fake_pool
|
|
|
|
expected = (fake_flavor, fake_server_group, fake_agg)
|
|
|
|
ret = plugin._create_resources(instance_reservation)
|
|
|
|
self.assertEqual(expected, ret)
|
|
|
|
fake_client.nova.server_groups.create.assert_called_once_with(
|
|
'reservation:reservation-id1', 'anti-affinity')
|
|
mock_nova.nova.flavors.create.assert_called_once_with(
|
|
flavorid='reservation-id1',
|
|
name='reservation:reservation-id1',
|
|
vcpus=2, ram=1024, disk=20, is_public=False)
|
|
fake_flavor.set_keys.assert_called_once_with(
|
|
{'aggregate_instance_extra_specs:reservation': 'reservation-id1',
|
|
'affinity_id': 'server_group_id1'})
|
|
fake_pool.create.assert_called_once_with(
|
|
name='reservation-id1',
|
|
metadata={'reservation': 'reservation-id1',
|
|
'filter_tenant_id': 'fake-project',
|
|
'affinity_id': 'server_group_id1'})
|
|
|
|
def test_pickup_hosts_for_update(self):
|
|
reservation = {'id': 'reservation-id1', 'status': 'pending'}
|
|
plugin = instance_plugin.VirtualInstancePlugin()
|
|
|
|
mock_alloc_get = self.patch(db_api,
|
|
'host_allocation_get_all_by_values')
|
|
mock_alloc_get.return_value = [
|
|
{'compute_host_id': 'host-id1'}, {'compute_host_id': 'host-id2'},
|
|
{'compute_host_id': 'host-id3'}]
|
|
mock_query_available = self.patch(plugin, 'query_available_hosts')
|
|
mock_query_available.return_value = [
|
|
self.generate_host_info('host-id2', 2, 2024, 1000),
|
|
self.generate_host_info('host-id3', 2, 2024, 1000),
|
|
self.generate_host_info('host-id4', 2, 2024, 1000)]
|
|
|
|
mock_reservation_get = self.patch(db_api, 'reservation_get')
|
|
mock_reservation_get.return_value = reservation
|
|
|
|
# case: new amount is less than old amount
|
|
values = self.get_input_values(1, 1024, 10, 1, False,
|
|
'2020-07-01 10:00', '2020-07-01 11:00',
|
|
'lease-1', '')
|
|
expect = {'added': set([]),
|
|
'removed': set(['host-id1', 'host-id2', 'host-id3'])}
|
|
ret = plugin.pickup_hosts(reservation['id'], values)
|
|
self.assertEqual(expect['added'], ret['added'])
|
|
self.assertEqual(2, len(ret['removed']))
|
|
self.assertTrue(all([h in expect['removed'] for h in ret['removed']]))
|
|
query_params = {
|
|
'cpus': 1, 'memory': 1024, 'disk': 10,
|
|
'resource_properties': '',
|
|
'start_date': '2020-07-01 10:00',
|
|
'end_date': '2020-07-01 11:00',
|
|
'excludes_res': ['reservation-id1']
|
|
}
|
|
mock_query_available.assert_called_with(**query_params)
|
|
|
|
# case: new amount is same but change allocations
|
|
values = self.get_input_values(1, 1024, 10, 3, False,
|
|
'2020-07-01 10:00', '2020-07-01 11:00',
|
|
'lease-1', '["==", "key1", "value1"]')
|
|
expect = {'added': set(['host-id4']), 'removed': set(['host-id1'])}
|
|
ret = plugin.pickup_hosts(reservation['id'], values)
|
|
self.assertEqual(expect['added'], ret['added'])
|
|
self.assertEqual(expect['removed'], ret['removed'])
|
|
query_params = {
|
|
'cpus': 1, 'memory': 1024, 'disk': 10,
|
|
'resource_properties': '["==", "key1", "value1"]',
|
|
'start_date': '2020-07-01 10:00',
|
|
'end_date': '2020-07-01 11:00',
|
|
'excludes_res': ['reservation-id1']
|
|
}
|
|
mock_query_available.assert_called_with(**query_params)
|
|
|
|
# case: new amount is greater than old amount
|
|
mock_query_available.return_value = [
|
|
self.generate_host_info('host-id1', 2, 2024, 1000),
|
|
self.generate_host_info('host-id2', 2, 2024, 1000),
|
|
self.generate_host_info('host-id3', 2, 2024, 1000),
|
|
self.generate_host_info('host-id4', 2, 2024, 1000)]
|
|
|
|
values = self.get_input_values(1, 1024, 10, 4, False,
|
|
'2020-07-01 10:00', '2020-07-01 11:00',
|
|
'lease-1', '')
|
|
expect = {'added': set(['host-id4']), 'removed': set([])}
|
|
ret = plugin.pickup_hosts(reservation['id'], values)
|
|
self.assertEqual(expect['added'], ret['added'])
|
|
self.assertEqual(expect['removed'], ret['removed'])
|
|
query_params = {
|
|
'cpus': 1, 'memory': 1024, 'disk': 10,
|
|
'resource_properties': '',
|
|
'start_date': '2020-07-01 10:00',
|
|
'end_date': '2020-07-01 11:00',
|
|
'excludes_res': ['reservation-id1']
|
|
}
|
|
mock_query_available.assert_called_with(**query_params)
|
|
|
|
def test_update_resources(self):
|
|
reservation = {
|
|
'id': 'reservation-id1',
|
|
'status': 'pending',
|
|
'vcpus': 2, 'memory_mb': 1024,
|
|
'disk_gb': 10, 'server_group_id': 'group-1'}
|
|
mock_reservation_get = self.patch(db_api, 'reservation_get')
|
|
mock_reservation_get.return_value = reservation
|
|
fake_client = mock.MagicMock()
|
|
mock_nova_client = self.patch(nova, 'NovaClientWrapper')
|
|
mock_nova_client.return_value = fake_client
|
|
self.set_context(context.BlazarContext(project_id='fake-project',
|
|
auth_token='fake-token'))
|
|
plugin = instance_plugin.VirtualInstancePlugin()
|
|
fake_flavor = mock.MagicMock(method='set_keys',
|
|
flavorid='reservation-id1')
|
|
mock_nova = mock.MagicMock()
|
|
type(plugin).nova = mock_nova
|
|
mock_nova.nova.flavors.create.return_value = fake_flavor
|
|
|
|
plugin.update_resources('reservation-id1')
|
|
|
|
mock_reservation_get.assert_called_once_with('reservation-id1')
|
|
mock_nova.nova.flavors.delete.assert_called_once_with(
|
|
'reservation-id1')
|
|
mock_nova.nova.flavors.create.assert_called_once_with(
|
|
flavorid='reservation-id1',
|
|
name='reservation:reservation-id1',
|
|
vcpus=2, ram=1024, disk=10, is_public=False)
|
|
fake_flavor.set_keys.assert_called_once_with(
|
|
{'aggregate_instance_extra_specs:reservation': 'reservation-id1',
|
|
'affinity_id': 'group-1'})
|
|
|
|
def test_update_resources_in_active(self):
|
|
def fake_host_get(host_id):
|
|
return {'service_name': 'host' + host_id[-1]}
|
|
|
|
reservation = {
|
|
'id': 'reservation-id1',
|
|
'status': 'active',
|
|
'vcpus': 2, 'memory_mb': 1024,
|
|
'disk_gb': 10, 'aggregate_id': 'aggregate-1'}
|
|
|
|
mock_reservation_get = self.patch(db_api, 'reservation_get')
|
|
mock_reservation_get.return_value = reservation
|
|
self.set_context(context.BlazarContext(project_id='fake-project'))
|
|
plugin = instance_plugin.VirtualInstancePlugin()
|
|
|
|
fake_pool = mock.MagicMock()
|
|
mock_pool = self.patch(nova, 'ReservationPool')
|
|
mock_pool.return_value = fake_pool
|
|
|
|
mock_alloc_get = self.patch(db_api,
|
|
'host_allocation_get_all_by_values')
|
|
mock_alloc_get.return_value = [
|
|
{'compute_host_id': 'host-id1'}, {'compute_host_id': 'host-id2'},
|
|
{'compute_host_id': 'host-id3'}]
|
|
|
|
mock_host_get = self.patch(db_api, 'host_get')
|
|
mock_host_get.side_effect = fake_host_get
|
|
|
|
plugin.update_resources('reservation-id1')
|
|
|
|
mock_reservation_get.assert_called_once_with('reservation-id1')
|
|
for i in range(3):
|
|
fake_pool.add_computehost.assert_any_call('aggregate-1',
|
|
'host' + str(i + 1),
|
|
stay_in=True)
|
|
|
|
def test_update_reservation(self):
|
|
plugin = instance_plugin.VirtualInstancePlugin()
|
|
|
|
old_reservation = {
|
|
'id': 'reservation-id1',
|
|
'status': 'pending',
|
|
'lease_id': 'lease-id1',
|
|
'resource_id': 'instance-reservation-id1',
|
|
'vcpus': 2, 'memory_mb': 1024, 'disk_gb': 100,
|
|
'amount': 2, 'affinity': False,
|
|
'resource_properties': ''}
|
|
mock_reservation_get = self.patch(db_api, 'reservation_get')
|
|
mock_reservation_get.return_value = old_reservation
|
|
|
|
mock_lease_get = self.patch(db_api, 'lease_get')
|
|
mock_lease_get.return_value = {'start_date': '2020-07-07 18:00',
|
|
'end_date': '2020-07-07 19:00'}
|
|
|
|
mock_pickup_hosts = self.patch(plugin, 'pickup_hosts')
|
|
mock_pickup_hosts.return_value = {
|
|
'added': set(['host-id1']), 'removed': set(['host-id2'])}
|
|
|
|
mock_inst_update = self.patch(db_api, 'instance_reservation_update')
|
|
mock_inst_update.return_value = {
|
|
'vcpus': 4, 'memory_mb': 1024, 'disk_gb': 200,
|
|
'amount': 2, 'affinity': False}
|
|
|
|
mock_update_alloc = self.patch(plugin, 'update_host_allocations')
|
|
|
|
mock_update_resource = self.patch(plugin, 'update_resources')
|
|
|
|
new_values = {'vcpus': 4, 'disk_gb': 200}
|
|
plugin.update_reservation('reservation-id1', new_values)
|
|
|
|
mock_pickup_hosts.assert_called_once_with(
|
|
'reservation-id1',
|
|
{'vcpus': 4, 'memory_mb': 1024, 'disk_gb': 200,
|
|
'amount': 2, 'affinity': False, 'resource_properties': ''})
|
|
mock_inst_update.assert_called_once_with(
|
|
'instance-reservation-id1',
|
|
{'vcpus': 4, 'memory_mb': 1024, 'disk_gb': 200,
|
|
'amount': 2, 'affinity': False, 'resource_properties': ''})
|
|
mock_update_alloc.assert_called_once_with(set(['host-id1']),
|
|
set(['host-id2']),
|
|
'reservation-id1')
|
|
mock_update_resource.assert_called_once_with('reservation-id1')
|
|
|
|
def test_update_reservation_not_enough_hosts(self):
|
|
plugin = instance_plugin.VirtualInstancePlugin()
|
|
|
|
old_reservation = {
|
|
'id': 'reservation-id1',
|
|
'status': 'pending',
|
|
'lease_id': 'lease-id1',
|
|
'resource_id': 'instance-reservation-id1',
|
|
'vcpus': 2, 'memory_mb': 1024, 'disk_gb': 100,
|
|
'amount': 2, 'affinity': False,
|
|
'resource_properties': ''}
|
|
mock_reservation_get = self.patch(db_api, 'reservation_get')
|
|
mock_reservation_get.return_value = old_reservation
|
|
|
|
mock_lease_get = self.patch(db_api, 'lease_get')
|
|
mock_lease_get.return_value = {'start_date': '2020-07-07 18:00',
|
|
'end_date': '2020-07-07 19:00'}
|
|
|
|
mock_pickup_hosts = self.patch(plugin, 'pickup_hosts')
|
|
mock_pickup_hosts.return_value = {
|
|
'added': set(), 'removed': set(['host-id2'])}
|
|
|
|
new_values = {'vcpus': 4, 'disk_gb': 200}
|
|
self.assertRaises(mgr_exceptions.NotEnoughHostsAvailable,
|
|
plugin.update_reservation, 'reservation-id1',
|
|
new_values)
|
|
|
|
def test_update_flavor_in_active(self):
|
|
plugin = instance_plugin.VirtualInstancePlugin()
|
|
|
|
old_reservation = {
|
|
'id': 'reservation-id1',
|
|
'status': 'active',
|
|
'lease_id': 'lease-id1',
|
|
'resource_id': 'instance-reservation-id1',
|
|
'vcpus': 2, 'memory_mb': 1024, 'disk_gb': 100,
|
|
'amount': 2, 'affinity': False}
|
|
mock_reservation_get = self.patch(db_api, 'reservation_get')
|
|
mock_reservation_get.return_value = old_reservation
|
|
|
|
mock_lease_get = self.patch(db_api, 'lease_get')
|
|
mock_lease_get.return_value = {'start_date': '2020-07-07 18:00',
|
|
'end_date': '2020-07-07 19:00'}
|
|
|
|
new_values = {'vcpus': 4, 'disk_gb': 200}
|
|
self.assertRaises(mgr_exceptions.InvalidStateUpdate,
|
|
plugin.update_reservation,
|
|
'reservation-id1', new_values)
|
|
|
|
def test_update_host_allocations(self):
|
|
mock_alloc_get = self.patch(db_api,
|
|
'host_allocation_get_all_by_values')
|
|
mock_alloc_get.return_value = [
|
|
{'id': 'id10', 'compute_host_id': 'host-id10'},
|
|
{'id': 'id11', 'compute_host_id': 'host-id11'},
|
|
{'id': 'id12', 'compute_host_id': 'host-id12'}]
|
|
|
|
mock_alloc_destroy = self.patch(db_api, 'host_allocation_destroy')
|
|
mock_alloc_create = self.patch(db_api, 'host_allocation_create')
|
|
|
|
plugin = instance_plugin.VirtualInstancePlugin()
|
|
|
|
added_host = ['host-id1', 'host-id2']
|
|
removed_host = ['host-id10', 'host-id11']
|
|
|
|
removed_calls = [mock.call('id10'), mock.call('id11')]
|
|
added_calls = [
|
|
mock.call({'compute_host_id': 'host-id1',
|
|
'reservation_id': 'reservation-id1'}),
|
|
mock.call({'compute_host_id': 'host-id2',
|
|
'reservation_id': 'reservation-id1'})]
|
|
|
|
plugin.update_host_allocations(added_host, removed_host,
|
|
'reservation-id1')
|
|
|
|
mock_alloc_destroy.assert_has_calls(removed_calls)
|
|
mock_alloc_create.assert_has_calls(added_calls)
|
|
|
|
def test_on_start(self):
|
|
def fake_host_get(host_id):
|
|
return {'service_name': 'host' + host_id[-1]}
|
|
|
|
self.set_context(context.BlazarContext(project_id='fake-project'))
|
|
plugin = instance_plugin.VirtualInstancePlugin()
|
|
|
|
mock_inst_get = self.patch(db_api, 'instance_reservation_get')
|
|
mock_inst_get.return_value = {'reservation_id': 'reservation-id1',
|
|
'aggregate_id': 'aggregate-id1'}
|
|
|
|
mock_nova = mock.MagicMock()
|
|
type(plugin).nova = mock_nova
|
|
|
|
fake_pool = mock.MagicMock()
|
|
mock_pool = self.patch(nova, 'ReservationPool')
|
|
mock_pool.return_value = fake_pool
|
|
|
|
mock_alloc_get = self.patch(db_api,
|
|
'host_allocation_get_all_by_values')
|
|
mock_alloc_get.return_value = [
|
|
{'compute_host_id': 'host-id1'}, {'compute_host_id': 'host-id2'},
|
|
{'compute_host_id': 'host-id3'}]
|
|
|
|
mock_host_get = self.patch(db_api, 'host_get')
|
|
mock_host_get.side_effect = fake_host_get
|
|
|
|
plugin.on_start('resource-id1')
|
|
|
|
mock_nova.flavor_access.add_tenant_access.assert_called_once_with(
|
|
'reservation-id1', 'fake-project')
|
|
for i in range(3):
|
|
fake_pool.add_computehost.assert_any_call('aggregate-id1',
|
|
'host' + str(i + 1),
|
|
stay_in=True)
|
|
|
|
def test_on_end(self):
|
|
self.set_context(context.BlazarContext(project_id='fake-project-id'))
|
|
|
|
plugin = instance_plugin.VirtualInstancePlugin()
|
|
|
|
fake_instance_reservation = {'reservation_id': 'reservation-id1'}
|
|
mock_inst_get = self.patch(db_api, 'instance_reservation_get')
|
|
mock_inst_get.return_value = fake_instance_reservation
|
|
|
|
mock_alloc_get = self.patch(db_api,
|
|
'host_allocation_get_all_by_values')
|
|
mock_alloc_get.return_value = [{'id': 'host-alloc-id1'},
|
|
{'id': 'host-alloc-id2'}]
|
|
|
|
self.patch(db_api, 'host_allocation_destroy')
|
|
|
|
fake_servers = [mock.MagicMock(method='delete') for i in range(5)]
|
|
mock_nova = mock.MagicMock()
|
|
type(plugin).nova = mock_nova
|
|
mock_nova.servers.list.return_value = fake_servers
|
|
|
|
mock_cleanup_resources = self.patch(plugin, 'cleanup_resources')
|
|
|
|
plugin.on_end('resource-id1')
|
|
|
|
mock_nova.flavor_access.remove_tenant_access.assert_called_once_with(
|
|
'reservation-id1', 'fake-project-id')
|
|
|
|
mock_nova.servers.list.assert_called_once_with(
|
|
search_opts={'flavor': 'reservation-id1', 'all_tenants': 1},
|
|
detailed=False)
|
|
for fake in fake_servers:
|
|
fake.delete.assert_called_once()
|
|
mock_cleanup_resources.assert_called_once_with(
|
|
fake_instance_reservation)
|
|
|
|
def test_heal_reservations_before_start_and_resources_changed(self):
|
|
plugin = instance_plugin.VirtualInstancePlugin()
|
|
failed_host = {'id': '1'}
|
|
dummy_reservation = {
|
|
'id': 'rsrv-1',
|
|
'resource_type': instances.RESOURCE_TYPE,
|
|
'lease_id': 'lease-1',
|
|
'status': 'pending',
|
|
'vcpus': 2,
|
|
'memory_mb': 1024,
|
|
'disk_gb': 256,
|
|
'aggregate_id': 'agg-1',
|
|
'affinity': False,
|
|
'amount': 3,
|
|
'resource_properties': '',
|
|
'computehost_allocations': [{
|
|
'id': 'alloc-1', 'compute_host_id': failed_host['id'],
|
|
'reservation_id': 'rsrv-1'
|
|
}]
|
|
}
|
|
get_reservations = self.patch(db_utils,
|
|
'get_reservations_by_host_ids')
|
|
get_reservations.return_value = [dummy_reservation]
|
|
reallocate = self.patch(plugin, '_reallocate')
|
|
reallocate.return_value = True
|
|
|
|
result = plugin.heal_reservations(
|
|
[failed_host],
|
|
datetime.datetime(2020, 1, 1, 12, 00),
|
|
datetime.datetime(2020, 1, 1, 13, 00))
|
|
reallocate.assert_called_once_with(
|
|
dummy_reservation['computehost_allocations'][0])
|
|
self.assertEqual({}, result)
|
|
|
|
def test_heal_reservations_before_start_and_missing_resources(self):
|
|
plugin = instance_plugin.VirtualInstancePlugin()
|
|
failed_host = {'id': '1'}
|
|
dummy_reservation = {
|
|
'id': 'rsrv-1',
|
|
'resource_type': instances.RESOURCE_TYPE,
|
|
'lease_id': 'lease-1',
|
|
'status': 'pending',
|
|
'vcpus': 2,
|
|
'memory_mb': 1024,
|
|
'disk_gb': 256,
|
|
'aggregate_id': 'agg-1',
|
|
'affinity': False,
|
|
'amount': 3,
|
|
'resource_properties': '',
|
|
'computehost_allocations': [{
|
|
'id': 'alloc-1', 'compute_host_id': failed_host['id'],
|
|
'reservation_id': 'rsrv-1'
|
|
}]
|
|
}
|
|
get_reservations = self.patch(db_utils,
|
|
'get_reservations_by_host_ids')
|
|
get_reservations.return_value = [dummy_reservation]
|
|
reallocate = self.patch(plugin, '_reallocate')
|
|
reallocate.return_value = False
|
|
|
|
result = plugin.heal_reservations(
|
|
[failed_host],
|
|
datetime.datetime(2020, 1, 1, 12, 00),
|
|
datetime.datetime(2020, 1, 1, 13, 00))
|
|
reallocate.assert_called_once_with(
|
|
dummy_reservation['computehost_allocations'][0])
|
|
self.assertEqual(
|
|
{dummy_reservation['id']: {'missing_resources': True}},
|
|
result)
|
|
|
|
def test_heal_active_reservations_and_resources_changed(self):
|
|
plugin = instance_plugin.VirtualInstancePlugin()
|
|
failed_host = {'id': '1'}
|
|
dummy_reservation = {
|
|
'id': 'rsrv-1',
|
|
'resource_type': instances.RESOURCE_TYPE,
|
|
'lease_id': 'lease-1',
|
|
'status': 'active',
|
|
'vcpus': 2,
|
|
'memory_mb': 1024,
|
|
'disk_gb': 256,
|
|
'aggregate_id': 'agg-1',
|
|
'affinity': False,
|
|
'amount': 3,
|
|
'computehost_allocations': [{
|
|
'id': 'alloc-1', 'compute_host_id': failed_host['id'],
|
|
'reservation_id': 'rsrv-1'
|
|
}]
|
|
}
|
|
get_reservations = self.patch(db_utils,
|
|
'get_reservations_by_host_ids')
|
|
get_reservations.return_value = [dummy_reservation]
|
|
reallocate = self.patch(plugin, '_reallocate')
|
|
reallocate.return_value = True
|
|
|
|
result = plugin.heal_reservations(
|
|
[failed_host],
|
|
datetime.datetime(2020, 1, 1, 12, 00),
|
|
datetime.datetime(2020, 1, 1, 13, 00))
|
|
reallocate.assert_called_once_with(
|
|
dummy_reservation['computehost_allocations'][0])
|
|
self.assertEqual(
|
|
{dummy_reservation['id']: {'resources_changed': True}},
|
|
result)
|
|
|
|
def test_heal_active_reservations_and_missing_resources(self):
|
|
plugin = instance_plugin.VirtualInstancePlugin()
|
|
failed_host = {'id': '1'}
|
|
dummy_reservation = {
|
|
'id': 'rsrv-1',
|
|
'resource_type': instances.RESOURCE_TYPE,
|
|
'lease_id': 'lease-1',
|
|
'status': 'active',
|
|
'vcpus': 2,
|
|
'memory_mb': 1024,
|
|
'disk_gb': 256,
|
|
'aggregate_id': 'agg-1',
|
|
'affinity': False,
|
|
'amount': 3,
|
|
'computehost_allocations': [{
|
|
'id': 'alloc-1', 'compute_host_id': failed_host['id'],
|
|
'reservation_id': 'rsrv-1'
|
|
}]
|
|
}
|
|
get_reservations = self.patch(db_utils,
|
|
'get_reservations_by_host_ids')
|
|
get_reservations.return_value = [dummy_reservation]
|
|
reallocate = self.patch(plugin, '_reallocate')
|
|
reallocate.return_value = False
|
|
|
|
result = plugin.heal_reservations(
|
|
[failed_host],
|
|
datetime.datetime(2020, 1, 1, 12, 00),
|
|
datetime.datetime(2020, 1, 1, 13, 00))
|
|
reallocate.assert_called_once_with(
|
|
dummy_reservation['computehost_allocations'][0])
|
|
self.assertEqual(
|
|
{dummy_reservation['id']: {'missing_resources': True}},
|
|
result)
|
|
|
|
def test_reallocate_before_start(self):
|
|
plugin = instance_plugin.VirtualInstancePlugin()
|
|
failed_host = {'id': '1'}
|
|
new_host = {'id': '2'}
|
|
dummy_allocation = {
|
|
'id': 'alloc-1',
|
|
'compute_host_id': failed_host['id'],
|
|
'reservation_id': 'rsrv-1'
|
|
}
|
|
dummy_reservation = {
|
|
'id': 'rsrv-1',
|
|
'resource_type': instances.RESOURCE_TYPE,
|
|
'lease_id': 'lease-1',
|
|
'status': 'pending',
|
|
'vcpus': 2,
|
|
'memory_mb': 1024,
|
|
'disk_gb': 256,
|
|
'aggregate_id': 'agg-1',
|
|
'affinity': False,
|
|
'amount': 3,
|
|
'resource_properties': ''
|
|
}
|
|
dummy_lease = {
|
|
'name': 'lease-name',
|
|
'start_date': datetime.datetime(2020, 1, 1, 12, 00),
|
|
'end_date': datetime.datetime(2020, 1, 2, 12, 00),
|
|
'trust_id': 'trust-1'
|
|
}
|
|
reservation_get = self.patch(db_api, 'reservation_get')
|
|
reservation_get.return_value = dummy_reservation
|
|
lease_get = self.patch(db_api, 'lease_get')
|
|
lease_get.return_value = dummy_lease
|
|
pickup_hosts = self.patch(plugin, 'pickup_hosts')
|
|
pickup_hosts.return_value = {'added': [new_host['id']], 'removed': []}
|
|
alloc_update = self.patch(db_api, 'host_allocation_update')
|
|
|
|
with mock.patch.object(datetime, 'datetime',
|
|
mock.Mock(wraps=datetime.datetime)) as patched:
|
|
patched.utcnow.return_value = datetime.datetime(
|
|
2020, 1, 1, 11, 00)
|
|
result = plugin._reallocate(dummy_allocation)
|
|
|
|
pickup_hosts.assert_called_once()
|
|
alloc_update.assert_called_once_with(
|
|
dummy_allocation['id'],
|
|
{'compute_host_id': new_host['id']})
|
|
self.assertEqual(True, result)
|
|
|
|
def test_reallocate_active(self):
|
|
plugin = instance_plugin.VirtualInstancePlugin()
|
|
failed_host = {'id': '1',
|
|
'service_name': 'compute-1'}
|
|
new_host = {'id': '2',
|
|
'service_name': 'compute-2'}
|
|
dummy_allocation = {
|
|
'id': 'alloc-1',
|
|
'compute_host_id': failed_host['id'],
|
|
'reservation_id': 'rsrv-1'
|
|
}
|
|
dummy_reservation = {
|
|
'id': 'rsrv-1',
|
|
'resource_type': instances.RESOURCE_TYPE,
|
|
'lease_id': 'lease-1',
|
|
'status': 'active',
|
|
'vcpus': 2,
|
|
'memory_mb': 1024,
|
|
'disk_gb': 256,
|
|
'aggregate_id': 'agg-1',
|
|
'affinity': False,
|
|
'amount': 3,
|
|
'resource_properties': ''}
|
|
dummy_lease = {
|
|
'name': 'lease-name',
|
|
'start_date': datetime.datetime(2020, 1, 1, 12, 00),
|
|
'end_date': datetime.datetime(2020, 1, 2, 12, 00),
|
|
'trust_id': 'trust-1'
|
|
}
|
|
reservation_get = self.patch(db_api, 'reservation_get')
|
|
reservation_get.return_value = dummy_reservation
|
|
lease_get = self.patch(db_api, 'lease_get')
|
|
lease_get.return_value = dummy_lease
|
|
host_get = self.patch(db_api, 'host_get')
|
|
host_get.return_value = failed_host
|
|
fake_pool = mock.MagicMock()
|
|
mock_pool = self.patch(nova, 'ReservationPool')
|
|
mock_pool.return_value = fake_pool
|
|
pickup_hosts = self.patch(plugin, 'pickup_hosts')
|
|
pickup_hosts.return_value = {'added': [new_host['id']], 'removed': []}
|
|
alloc_update = self.patch(db_api, 'host_allocation_update')
|
|
|
|
with mock.patch.object(datetime, 'datetime',
|
|
mock.Mock(wraps=datetime.datetime)) as patched:
|
|
patched.utcnow.return_value = datetime.datetime(
|
|
2020, 1, 1, 13, 00)
|
|
result = plugin._reallocate(dummy_allocation)
|
|
|
|
fake_pool.remove_computehost.assert_called_once_with(
|
|
dummy_reservation['aggregate_id'],
|
|
failed_host['service_name'])
|
|
pickup_hosts.assert_called_once()
|
|
alloc_update.assert_called_once_with(
|
|
dummy_allocation['id'],
|
|
{'compute_host_id': new_host['id']})
|
|
fake_pool.add_computehost.assert_called_once_with(
|
|
dummy_reservation['aggregate_id'],
|
|
failed_host['service_name'],
|
|
stay_in=True)
|
|
self.assertEqual(True, result)
|
|
|
|
def test_reallocate_missing_resources(self):
|
|
plugin = instance_plugin.VirtualInstancePlugin()
|
|
failed_host = {'id': '1',
|
|
'service_name': 'compute-1'}
|
|
dummy_allocation = {
|
|
'id': 'alloc-1',
|
|
'compute_host_id': failed_host['id'],
|
|
'reservation_id': 'rsrv-1'
|
|
}
|
|
dummy_reservation = {
|
|
'id': 'rsrv-1',
|
|
'resource_type': instances.RESOURCE_TYPE,
|
|
'lease_id': 'lease-1',
|
|
'status': 'pending',
|
|
'vcpus': 2,
|
|
'memory_mb': 1024,
|
|
'disk_gb': 256,
|
|
'aggregate_id': 'agg-1',
|
|
'affinity': False,
|
|
'amount': 3,
|
|
'resource_properties': ''
|
|
}
|
|
dummy_lease = {
|
|
'name': 'lease-name',
|
|
'start_date': datetime.datetime(2020, 1, 1, 12, 00),
|
|
'end_date': datetime.datetime(2020, 1, 2, 12, 00),
|
|
'trust_id': 'trust-1'
|
|
}
|
|
reservation_get = self.patch(db_api, 'reservation_get')
|
|
reservation_get.return_value = dummy_reservation
|
|
lease_get = self.patch(db_api, 'lease_get')
|
|
lease_get.return_value = dummy_lease
|
|
pickup_hosts = self.patch(plugin, 'pickup_hosts')
|
|
pickup_hosts.return_value = {'added': [], 'removed': []}
|
|
alloc_destroy = self.patch(db_api, 'host_allocation_destroy')
|
|
|
|
with mock.patch.object(datetime, 'datetime',
|
|
mock.Mock(wraps=datetime.datetime)) as patched:
|
|
patched.utcnow.return_value = datetime.datetime(
|
|
2020, 1, 1, 11, 00)
|
|
result = plugin._reallocate(dummy_allocation)
|
|
|
|
pickup_hosts.assert_called_once()
|
|
alloc_destroy.assert_called_once_with(dummy_allocation['id'])
|
|
self.assertEqual(False, result)
|