Implement Flavor synchronization in Kingbird.
Flavor Synchronization sync multiple flavors from one region to multiple target regions. Only admin can perform flavor-sync.Currently, when a user requests to sync a flavor kingbird syncs extra specs of the source resource. Added Test-cases for the same. Implements:blueprint resource-syncing Change-Id: Id289cf93bb9c30ea699223e232025285a29042de
This commit is contained in:
parent
2f6dab7fc1
commit
fd6b4cba10
|
@ -142,4 +142,64 @@ class NovaClient(base.DriverBase):
|
|||
except exceptions.ResourceNotFound():
|
||||
LOG.error('Exception Occurred: Source Flavor %s not available',
|
||||
res_id)
|
||||
|
||||
def get_flavor_access_tenant(self, res_id):
|
||||
"""Get tenant which has access to the Flavor."""
|
||||
try:
|
||||
access_tenants = [access.tenant_id for access in
|
||||
self.nova_client.
|
||||
flavor_access.list(flavor=res_id)]
|
||||
LOG.info("Access to only : %s", access_tenants)
|
||||
return access_tenants
|
||||
except exceptions.InternalError():
|
||||
LOG.error('Exception Occurred couldnot find access tenants.')
|
||||
pass
|
||||
|
||||
def check_and_delete_flavor_in_target_region(self, flavor,
|
||||
resource_flavor):
|
||||
"""Check for the flavor and then delete it."""
|
||||
try:
|
||||
target_flavor = self.nova_client.flavors.get(flavor.id)
|
||||
if target_flavor:
|
||||
resource_flavor.pop("flavorid", None)
|
||||
flavor_list = self.nova_client.flavors.list(is_public=None)
|
||||
for target_region_flavor in flavor_list:
|
||||
if target_region_flavor.name == flavor.name:
|
||||
self.nova_client.flavors.delete(
|
||||
target_region_flavor.id)
|
||||
LOG.info("Deleted Flavor: %s", flavor.name)
|
||||
break
|
||||
except Exception:
|
||||
LOG.error('Exception Occurred: %s not available', flavor.id)
|
||||
pass
|
||||
|
||||
def create_flavor(self, force, flavor, access_tenants=None):
|
||||
"""Create Flavor in target regions."""
|
||||
resource_flavor = flavor._info.copy()
|
||||
resource_flavor.update({'flavorid': resource_flavor['id']})
|
||||
resource_flavor.pop("links", None)
|
||||
resource_flavor.pop("OS-FLV-DISABLED:disabled", None)
|
||||
resource_flavor.pop("OS-FLV-EXT-DATA:ephemeral", None)
|
||||
resource_flavor.pop("os-flavor-access:is_public", None)
|
||||
resource_flavor.pop("id", None)
|
||||
if not resource_flavor['swap']:
|
||||
resource_flavor.pop("swap", None)
|
||||
if not flavor.is_public:
|
||||
resource_flavor.update({'is_public': False})
|
||||
if force:
|
||||
self.check_and_delete_flavor_in_target_region(
|
||||
flavor, resource_flavor)
|
||||
target_flavor = self.nova_client.flavors.create(**resource_flavor)
|
||||
target_flavor_properties = flavor.get_keys()
|
||||
if target_flavor_properties:
|
||||
try:
|
||||
target_flavor.set_keys(target_flavor_properties)
|
||||
except Exception as e:
|
||||
LOG.error(_("Failed to set flavor property: %s"), e)
|
||||
if access_tenants:
|
||||
for tenant in access_tenants:
|
||||
self.nova_client.flavor_access.add_tenant_access(
|
||||
target_flavor.id, tenant)
|
||||
LOG.info('%(flavor)s Access Granted to %(tenant)s'
|
||||
% {'flavor': target_flavor.name, 'tenant': tenant})
|
||||
return target_flavor
|
||||
|
|
|
@ -0,0 +1,118 @@
|
|||
# Copyright 2017 Ericsson AB.
|
||||
#
|
||||
# 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 threading
|
||||
|
||||
from oslo_log import log as logging
|
||||
|
||||
from kingbird.common import consts
|
||||
from kingbird.common.endpoint_cache import EndpointCache
|
||||
from kingbird.common import exceptions
|
||||
from kingbird.db.sqlalchemy import api as db_api
|
||||
from kingbird.drivers.openstack.nova_v2 import NovaClient
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class FlavorSyncManager(object):
|
||||
"""Manages tasks related to resource management."""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(FlavorSyncManager, self).__init__()
|
||||
|
||||
def create_resources_in_region(self, job_id, force, target_regions,
|
||||
source_flavor, session, context,
|
||||
access_tenants=None):
|
||||
"""Create Region specific threads."""
|
||||
regions_thread = list()
|
||||
for region in target_regions:
|
||||
thread = threading.Thread(target=self.create_resources,
|
||||
args=(job_id, force, region,
|
||||
source_flavor, session,
|
||||
context, access_tenants))
|
||||
regions_thread.append(thread)
|
||||
thread.start()
|
||||
for region_thread in regions_thread:
|
||||
region_thread.join()
|
||||
|
||||
def create_resources(self, job_id, force, region, source_flavor,
|
||||
session, context, access_tenants=None):
|
||||
"""Create resources using threads."""
|
||||
target_nova_client = NovaClient(region, session)
|
||||
try:
|
||||
target_nova_client.create_flavor(force, source_flavor,
|
||||
access_tenants)
|
||||
LOG.info('Flavor %(flavor)s created in %(region)s'
|
||||
% {'flavor': source_flavor.name, 'region': region})
|
||||
try:
|
||||
db_api.resource_sync_update(context, job_id, region,
|
||||
source_flavor.id,
|
||||
consts.JOB_SUCCESS)
|
||||
except exceptions.JobNotFound():
|
||||
raise
|
||||
except Exception as exc:
|
||||
LOG.error('Exception Occurred: %(msg)s in %(region)s'
|
||||
% {'msg': exc.message, 'region': region})
|
||||
try:
|
||||
db_api.resource_sync_update(context, job_id, region,
|
||||
source_flavor.id,
|
||||
consts.JOB_FAILURE)
|
||||
except exceptions.JobNotFound():
|
||||
raise
|
||||
pass
|
||||
|
||||
def resource_sync(self, context, job_id, payload):
|
||||
"""Create resources in target regions.
|
||||
|
||||
:param context: request context object.
|
||||
:param job_id: ID of the job which triggered image_sync.
|
||||
:payload: request payload.
|
||||
"""
|
||||
LOG.info("Triggered Flavor Sync.")
|
||||
flavors_thread = list()
|
||||
access_tenants = None
|
||||
target_regions = payload['target']
|
||||
force = eval(str(payload.get('force', False)))
|
||||
resource_ids = payload.get('resources')
|
||||
source_region = payload['source']
|
||||
session = EndpointCache().get_session_from_token(
|
||||
context.auth_token, context.project)
|
||||
# Create Source Region object
|
||||
source_nova_client = NovaClient(source_region, session)
|
||||
for flavor in resource_ids:
|
||||
source_flavor = source_nova_client.get_flavor(flavor)
|
||||
if not source_flavor.is_public:
|
||||
access_tenants = source_nova_client.\
|
||||
get_flavor_access_tenant(flavor)
|
||||
thread = threading.Thread(target=self.create_resources_in_region,
|
||||
args=(job_id, force, target_regions,
|
||||
source_flavor, session,
|
||||
context, access_tenants))
|
||||
flavors_thread.append(thread)
|
||||
thread.start()
|
||||
for flavor_thread in flavors_thread:
|
||||
flavor_thread.join()
|
||||
try:
|
||||
resource_sync_details = db_api.\
|
||||
resource_sync_status(context, job_id)
|
||||
except exceptions.JobNotFound:
|
||||
raise
|
||||
result = consts.JOB_SUCCESS
|
||||
if consts.JOB_FAILURE in resource_sync_details:
|
||||
result = consts.JOB_FAILURE
|
||||
try:
|
||||
db_api.sync_job_update(context, job_id, result)
|
||||
except exceptions.JobNotFound:
|
||||
raise
|
|
@ -23,6 +23,7 @@ from kingbird.common import context
|
|||
from kingbird.common import exceptions
|
||||
from kingbird.common.i18n import _
|
||||
from kingbird.common import messaging as rpc_messaging
|
||||
from kingbird.engine.flavor_sync_manager import FlavorSyncManager
|
||||
from kingbird.engine.image_sync_manager import ImageSyncManager
|
||||
from kingbird.engine.keypair_sync_manager import KeypairSyncManager
|
||||
from kingbird.engine.quota_manager import QuotaManager
|
||||
|
@ -76,6 +77,7 @@ class EngineService(service.Service):
|
|||
self.qm = None
|
||||
self.ksm = None
|
||||
self.ism = None
|
||||
self.fsm = None
|
||||
|
||||
def init_tgm(self):
|
||||
self.TG = scheduler.ThreadGroupManager()
|
||||
|
@ -89,12 +91,16 @@ class EngineService(service.Service):
|
|||
def init_ism(self):
|
||||
self.ism = ImageSyncManager()
|
||||
|
||||
def init_fsm(self):
|
||||
self.fsm = FlavorSyncManager()
|
||||
|
||||
def start(self):
|
||||
self.engine_id = uuidutils.generate_uuid()
|
||||
self.init_tgm()
|
||||
self.init_qm()
|
||||
self.init_ksm()
|
||||
self.init_ism()
|
||||
self.init_fsm()
|
||||
target = oslo_messaging.Target(version=self.rpc_api_version,
|
||||
server=self.host,
|
||||
topic=self.topic)
|
||||
|
@ -169,6 +175,11 @@ class EngineService(service.Service):
|
|||
# Image Sync triggered by KB_API.
|
||||
self.ism.resource_sync(ctxt, job_id, payload)
|
||||
|
||||
@request_context
|
||||
def flavor_sync(self, ctxt, job_id, payload):
|
||||
# Flavor Sync triggered by KB_API.
|
||||
self.fsm.resource_sync(ctxt, job_id, payload)
|
||||
|
||||
def _stop_rpc_server(self):
|
||||
# Stop RPC connection to prevent new requests
|
||||
LOG.debug(_("Attempting to stop engine service..."))
|
||||
|
|
|
@ -27,7 +27,8 @@ class Server(object):
|
|||
|
||||
|
||||
class Fake_Flavor(object):
|
||||
def __init__(self, id, ram, cores, disks, name, swap, is_public=True):
|
||||
def __init__(self, id, ram, cores, disks, name, swap, rxtx_factor,
|
||||
is_public=True, keys=None):
|
||||
self.id = id
|
||||
self.ram = ram
|
||||
self.vcpus = cores
|
||||
|
@ -35,6 +36,28 @@ class Fake_Flavor(object):
|
|||
self.name = name
|
||||
self.is_public = is_public
|
||||
self.swap = swap
|
||||
self.rxtx_factor = 1.0
|
||||
self._info = {u'name': self.name,
|
||||
u'links': [
|
||||
{u'href': u'http://www.flavor.com/v2.1/flavors/2',
|
||||
u'rel': u'self'},
|
||||
{u'href': u'http://www.fake_flavor.com/flavors/2',
|
||||
u'rel': u'bookmark'}],
|
||||
u'ram': self.ram, u'OS-FLV-DISABLED:disabled': False,
|
||||
u'vcpus': self.vcpus, u'swap': self.swap,
|
||||
u'rxtx_factor': 1.0, u'disk': self.disk,
|
||||
u'os-flavor-access:is_public': self.is_public,
|
||||
u'OS-FLV-EXT-DATA:ephemeral': 0, u'id': self.id}
|
||||
self.keys = keys
|
||||
|
||||
def get_keys(self):
|
||||
return self.keys
|
||||
|
||||
|
||||
class Access(object):
|
||||
def __init__(self, tenant_id):
|
||||
self.tenant_id = tenant_id
|
||||
|
||||
|
||||
s1 = Server(1, {'mkey': 'mvalue'})
|
||||
s2 = Server(1, {'mkey': 'mvalue', 'm2key': 'm2value'})
|
||||
|
@ -120,8 +143,8 @@ class TestNovaClient(base.KingbirdTestCase):
|
|||
def test_get_keypairs(self, mock_novaclient):
|
||||
nv_client = nova_v2.NovaClient('fake_region', self.session,
|
||||
DISABLED_QUOTAS)
|
||||
nv_client.get_keypairs(FAKE_RESOURCE_ID)
|
||||
mock_novaclient.Client().keypairs.get.return_value = 'key1'
|
||||
nv_client.get_keypairs(FAKE_RESOURCE_ID)
|
||||
mock_novaclient.Client().keypairs.get.\
|
||||
assert_called_once_with(FAKE_RESOURCE_ID)
|
||||
|
||||
|
@ -151,9 +174,134 @@ class TestNovaClient(base.KingbirdTestCase):
|
|||
|
||||
@mock.patch.object(nova_v2, 'client')
|
||||
def test_get_flavor(self, mock_novaclient):
|
||||
"""Test get_flavor method of nova."""
|
||||
nv_client = nova_v2.NovaClient('fake_region', self.session,
|
||||
DISABLED_QUOTAS)
|
||||
fake_flavor = Fake_Flavor('fake_id', 512, 2, 30, 'fake_flavor', 1)
|
||||
nv_client.get_flavor(fake_flavor.id)
|
||||
nv_client.get_flavor('fake_id')
|
||||
mock_novaclient.Client().flavors.get.\
|
||||
assert_called_once_with('fake_id')
|
||||
|
||||
@mock.patch.object(nova_v2, 'client')
|
||||
def test_get_flavor_access_tenants(self, mock_novaclient):
|
||||
nv_client = nova_v2.NovaClient('fake_region', self.session,
|
||||
DISABLED_QUOTAS)
|
||||
nv_client.get_flavor_access_tenant('fake_flavor')
|
||||
mock_novaclient.Client().flavor_access.list.\
|
||||
assert_called_once_with(flavor='fake_flavor')
|
||||
|
||||
@mock.patch.object(nova_v2, 'client')
|
||||
def test_check_and_delete_flavor(self, mock_novaclient):
|
||||
nv_client = nova_v2.NovaClient('fake_region', self.session,
|
||||
DISABLED_QUOTAS)
|
||||
fake_flavor = Fake_Flavor('fake_id', 512, 2, 30, 'fake_flavor', 1,
|
||||
1.0)
|
||||
mock_novaclient.Client().flavors.list.return_value = [fake_flavor]
|
||||
nv_client.check_and_delete_flavor_in_target_region(fake_flavor,
|
||||
fake_flavor._info)
|
||||
mock_novaclient.Client().flavors.get.\
|
||||
assert_called_once_with(fake_flavor.id)
|
||||
mock_novaclient.Client().flavors.list.\
|
||||
assert_called_once_with(is_public=None)
|
||||
mock_novaclient.Client().flavors.delete.\
|
||||
assert_called_once_with(fake_flavor.id)
|
||||
|
||||
@mock.patch.object(nova_v2, 'client')
|
||||
def test_check_and_delete_target_flavor(self, mock_novaclient):
|
||||
nv_client = nova_v2.NovaClient('fake_region', self.session,
|
||||
DISABLED_QUOTAS)
|
||||
fake_flavor = Fake_Flavor('fake_id', 512, 2, 30, 'fake_flavor', 1,
|
||||
1.0)
|
||||
mock_novaclient.Client().flavors.get.return_value = None
|
||||
mock_novaclient.Client().flavors.list.return_value = []
|
||||
nv_client.check_and_delete_flavor_in_target_region(fake_flavor,
|
||||
fake_flavor._info)
|
||||
|
||||
@mock.patch.object(nova_v2, 'client')
|
||||
def test_create_flavor_force_true_no_access_tenants(self,
|
||||
mock_novaclient):
|
||||
nv_client = nova_v2.NovaClient('fake_region', self.session,
|
||||
DISABLED_QUOTAS)
|
||||
fake_flavor = Fake_Flavor('fake_id', 512, 2, 30, 'fake_flavor', 1,
|
||||
1.0)
|
||||
nv_client.create_flavor(True, fake_flavor)
|
||||
mock_novaclient.Client().flavors.create.\
|
||||
assert_called_once_with(
|
||||
disk=fake_flavor.disk, name=fake_flavor.name,
|
||||
ram=fake_flavor.ram, rxtx_factor=fake_flavor.rxtx_factor,
|
||||
swap=fake_flavor.swap, vcpus=fake_flavor.vcpus)
|
||||
fake_resource_dict = fake_flavor._info.copy()
|
||||
fake_resource_dict.update({'flavorid': fake_flavor.id})
|
||||
fake_resource_dict.pop("links", None)
|
||||
fake_resource_dict.pop("OS-FLV-DISABLED:disabled", None)
|
||||
fake_resource_dict.pop("OS-FLV-EXT-DATA:ephemeral", None)
|
||||
fake_resource_dict.pop("os-flavor-access:is_public", None)
|
||||
fake_resource_dict.pop("id", None)
|
||||
mock_novaclient.Client().flavors.get.\
|
||||
assert_called_once_with(fake_flavor.id)
|
||||
mock_novaclient.Client().flavors.list.\
|
||||
assert_called_once_with(is_public=None)
|
||||
|
||||
@mock.patch.object(nova_v2, 'client')
|
||||
def test_create_flavor_force_false_no_access_tenants(self,
|
||||
mock_novaclient):
|
||||
nv_client = nova_v2.NovaClient('fake_region', self.session,
|
||||
DISABLED_QUOTAS)
|
||||
fake_flavor = Fake_Flavor('fake_id', 512, 2, 30, 'fake_flavor', 1,
|
||||
1.0)
|
||||
nv_client.create_flavor(False, fake_flavor)
|
||||
mock_novaclient.Client().flavors.create.\
|
||||
assert_called_once_with(
|
||||
flavorid=fake_flavor.id, disk=fake_flavor.disk,
|
||||
name=fake_flavor.name, ram=fake_flavor.ram,
|
||||
rxtx_factor=fake_flavor.rxtx_factor,
|
||||
swap=fake_flavor.swap, vcpus=fake_flavor.vcpus)
|
||||
mock_novaclient.Client().flavors.assert_not_called
|
||||
mock_novaclient.Client().flavors.assert_not_called
|
||||
|
||||
@mock.patch.object(nova_v2, 'client')
|
||||
def test_create_flavor_force_true_with_access_tenants(self,
|
||||
mock_novaclient):
|
||||
nv_client = nova_v2.NovaClient('fake_region', self.session,
|
||||
DISABLED_QUOTAS)
|
||||
fake_flavor = Fake_Flavor('fake_id', 512, 2, 30, 'fake_flavor', 1,
|
||||
1.0)
|
||||
access_tenants = ['fake_tenant_1', 'fake_tenant_2']
|
||||
nv_client.create_flavor(True, fake_flavor, access_tenants)
|
||||
mock_novaclient.Client().flavors.create.\
|
||||
assert_called_once_with(
|
||||
disk=fake_flavor.disk, name=fake_flavor.name,
|
||||
ram=fake_flavor.ram, rxtx_factor=fake_flavor.rxtx_factor,
|
||||
swap=fake_flavor.swap, vcpus=fake_flavor.vcpus)
|
||||
fake_resource_dict = fake_flavor._info.copy()
|
||||
fake_resource_dict.update({'flavorid': fake_flavor.id})
|
||||
fake_resource_dict.pop("links", None)
|
||||
fake_resource_dict.pop("OS-FLV-DISABLED:disabled", None)
|
||||
fake_resource_dict.pop("OS-FLV-EXT-DATA:ephemeral", None)
|
||||
fake_resource_dict.pop("os-flavor-access:is_public", None)
|
||||
fake_resource_dict.pop("id", None)
|
||||
mock_novaclient.Client().flavors.get.\
|
||||
assert_called_once_with(fake_flavor.id)
|
||||
mock_novaclient.Client().flavors.list.\
|
||||
assert_called_once_with(is_public=None)
|
||||
self.assertEqual(mock_novaclient.Client().flavor_access.
|
||||
add_tenant_access.call_count, 2)
|
||||
|
||||
@mock.patch.object(nova_v2, 'client')
|
||||
def test_create_flavor_force_false_with_access_tenants(self,
|
||||
mock_novaclient):
|
||||
nv_client = nova_v2.NovaClient('fake_region', self.session,
|
||||
DISABLED_QUOTAS)
|
||||
fake_flavor = Fake_Flavor('fake_id', 512, 2, 30, 'fake_flavor', 1,
|
||||
1.0)
|
||||
access_tenants = ['fake_tenant_1', 'fake_tenant_2']
|
||||
nv_client.create_flavor(False, fake_flavor, access_tenants)
|
||||
mock_novaclient.Client().flavors.create.\
|
||||
assert_called_once_with(
|
||||
flavorid=fake_flavor.id, disk=fake_flavor.disk,
|
||||
name=fake_flavor.name, ram=fake_flavor.ram,
|
||||
rxtx_factor=fake_flavor.rxtx_factor,
|
||||
swap=fake_flavor.swap, vcpus=fake_flavor.vcpus)
|
||||
mock_novaclient.Client().flavors.assert_not_called
|
||||
mock_novaclient.Client().flavors.assert_not_called
|
||||
self.assertEqual(mock_novaclient.Client().flavor_access.
|
||||
add_tenant_access.call_count, 2)
|
||||
|
|
|
@ -0,0 +1,216 @@
|
|||
# Copyright 2017 Ericsson AB.
|
||||
#
|
||||
# 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 mock
|
||||
|
||||
from kingbird.engine import flavor_sync_manager
|
||||
from kingbird.tests import base
|
||||
from kingbird.tests import utils
|
||||
|
||||
DEFAULT_FORCE = False
|
||||
SOURCE_FLAVOR = 'fake_key1'
|
||||
FAKE_USER_ID = 'user123'
|
||||
FAKE_TARGET_REGION = 'fake_target_region'
|
||||
FAKE_SOURCE_REGION = 'fake_source_region'
|
||||
FAKE_RESOURCE_ID = 'fake_id'
|
||||
FAKE_JOB_ID = utils.UUID1
|
||||
JOB_RESULT = "SUCCESS"
|
||||
FAKE_TENANTS = ['fake_tenant_1', 'fake_tenant_2']
|
||||
|
||||
|
||||
class FakeFlavor(object):
|
||||
def __init__(self, id, ram, cores, disks, name, swap, rxtx_factor,
|
||||
is_public=True):
|
||||
self.id = id
|
||||
self.ram = ram
|
||||
self.vcpus = cores
|
||||
self.disk = disks
|
||||
self.name = name
|
||||
self.is_public = is_public
|
||||
self.swap = swap
|
||||
self.rxtx_factor = 1.0
|
||||
|
||||
|
||||
class TestFlavorSyncManager(base.KingbirdTestCase):
|
||||
def setUp(self):
|
||||
super(TestFlavorSyncManager, self).setUp()
|
||||
self.ctxt = utils.dummy_context()
|
||||
|
||||
@mock.patch.object(flavor_sync_manager, 'NovaClient')
|
||||
@mock.patch.object(flavor_sync_manager, 'EndpointCache')
|
||||
@mock.patch.object(flavor_sync_manager.FlavorSyncManager,
|
||||
'create_resources')
|
||||
@mock.patch.object(flavor_sync_manager, 'db_api')
|
||||
def test_flavor_sync_force_false_no_access_tenants(
|
||||
self, mock_db_api, mock_create_resource, mock_endpoint_cache,
|
||||
mock_nova):
|
||||
access_tenants = None
|
||||
fake_flavor = FakeFlavor('fake_id', 512, 2, 30, 'fake_flavor', 1,
|
||||
1.0)
|
||||
payload = dict()
|
||||
payload['target'] = [FAKE_TARGET_REGION]
|
||||
payload['force'] = DEFAULT_FORCE
|
||||
payload['source'] = FAKE_SOURCE_REGION
|
||||
payload['resources'] = [fake_flavor]
|
||||
mock_endpoint_cache().get_session_from_token.\
|
||||
return_value = 'fake_session'
|
||||
mock_nova().get_flavor.return_value = fake_flavor
|
||||
mock_db_api().resource_sync_status.return_value = [JOB_RESULT]
|
||||
fsm = flavor_sync_manager.FlavorSyncManager()
|
||||
fsm.resource_sync(self.ctxt, FAKE_JOB_ID, payload)
|
||||
mock_create_resource.assert_called_once_with(
|
||||
FAKE_JOB_ID, payload['force'], payload['target'][0], fake_flavor,
|
||||
'fake_session', self.ctxt, access_tenants)
|
||||
mock_nova().get_flavor_access_tenant.assert_not_called
|
||||
mock_db_api.resource_sync_status.\
|
||||
assert_called_once_with(self.ctxt, FAKE_JOB_ID)
|
||||
mock_db_api.sync_job_update.\
|
||||
assert_called_once_with(self.ctxt, FAKE_JOB_ID, JOB_RESULT)
|
||||
|
||||
@mock.patch.object(flavor_sync_manager, 'NovaClient')
|
||||
@mock.patch.object(flavor_sync_manager, 'EndpointCache')
|
||||
@mock.patch.object(flavor_sync_manager.FlavorSyncManager,
|
||||
'create_resources')
|
||||
@mock.patch.object(flavor_sync_manager, 'db_api')
|
||||
def test_flavor_sync_force_true_no_access_tenants(
|
||||
self, mock_db_api, mock_create_resource, mock_endpoint_cache,
|
||||
mock_nova):
|
||||
access_tenants = None
|
||||
fake_flavor = FakeFlavor('fake_id', 512, 2, 30, 'fake_flavor', 1,
|
||||
1.0)
|
||||
payload = dict()
|
||||
payload['target'] = [FAKE_TARGET_REGION]
|
||||
payload['force'] = True
|
||||
payload['source'] = FAKE_SOURCE_REGION
|
||||
payload['resources'] = [fake_flavor]
|
||||
mock_endpoint_cache().get_session_from_token.\
|
||||
return_value = 'fake_session'
|
||||
mock_nova().get_flavor.return_value = fake_flavor
|
||||
mock_db_api().resource_sync_status.return_value = [JOB_RESULT]
|
||||
fsm = flavor_sync_manager.FlavorSyncManager()
|
||||
fsm.resource_sync(self.ctxt, FAKE_JOB_ID, payload)
|
||||
mock_create_resource.assert_called_once_with(
|
||||
FAKE_JOB_ID, payload['force'], payload['target'][0], fake_flavor,
|
||||
'fake_session', self.ctxt, access_tenants)
|
||||
mock_nova().get_flavor_access_tenant.assert_not_called
|
||||
mock_db_api.resource_sync_status.\
|
||||
assert_called_once_with(self.ctxt, FAKE_JOB_ID)
|
||||
mock_db_api.sync_job_update.\
|
||||
assert_called_once_with(self.ctxt, FAKE_JOB_ID, JOB_RESULT)
|
||||
|
||||
@mock.patch.object(flavor_sync_manager, 'NovaClient')
|
||||
@mock.patch.object(flavor_sync_manager, 'EndpointCache')
|
||||
@mock.patch.object(flavor_sync_manager.FlavorSyncManager,
|
||||
'create_resources')
|
||||
@mock.patch.object(flavor_sync_manager, 'db_api')
|
||||
def test_flavor_sync_force_false_with_access_tenants(
|
||||
self, mock_db_api, mock_create_resource, mock_endpoint_cache,
|
||||
mock_nova):
|
||||
access_tenants = FAKE_TENANTS
|
||||
fake_flavor = FakeFlavor('fake_id', 512, 2, 30, 'fake_flavor', 1,
|
||||
1.0, False)
|
||||
payload = dict()
|
||||
payload['target'] = [FAKE_TARGET_REGION]
|
||||
payload['force'] = DEFAULT_FORCE
|
||||
payload['source'] = FAKE_SOURCE_REGION
|
||||
payload['resources'] = [fake_flavor]
|
||||
mock_nova().get_flavor_access_tenant.return_value = access_tenants
|
||||
mock_endpoint_cache().get_session_from_token.\
|
||||
return_value = 'fake_session'
|
||||
mock_nova().get_flavor.return_value = fake_flavor
|
||||
mock_db_api().resource_sync_status.return_value = [JOB_RESULT]
|
||||
fsm = flavor_sync_manager.FlavorSyncManager()
|
||||
fsm.resource_sync(self.ctxt, FAKE_JOB_ID, payload)
|
||||
mock_create_resource.assert_called_once_with(
|
||||
FAKE_JOB_ID, payload['force'], payload['target'][0], fake_flavor,
|
||||
'fake_session', self.ctxt, access_tenants)
|
||||
mock_nova().get_flavor_access_tenant.\
|
||||
assert_called_once_with(fake_flavor)
|
||||
mock_db_api.resource_sync_status.\
|
||||
assert_called_once_with(self.ctxt, FAKE_JOB_ID)
|
||||
mock_db_api.sync_job_update.\
|
||||
assert_called_once_with(self.ctxt, FAKE_JOB_ID, JOB_RESULT)
|
||||
|
||||
@mock.patch.object(flavor_sync_manager, 'NovaClient')
|
||||
@mock.patch.object(flavor_sync_manager, 'EndpointCache')
|
||||
@mock.patch.object(flavor_sync_manager.FlavorSyncManager,
|
||||
'create_resources')
|
||||
@mock.patch.object(flavor_sync_manager, 'db_api')
|
||||
def test_flavor_sync_force_true_with_access_tenants(
|
||||
self, mock_db_api, mock_create_resource, mock_endpoint_cache,
|
||||
mock_nova):
|
||||
access_tenants = FAKE_TENANTS
|
||||
fake_flavor = FakeFlavor('fake_id', 512, 2, 30, 'fake_flavor', 1,
|
||||
1.0, False)
|
||||
payload = dict()
|
||||
payload['target'] = [FAKE_TARGET_REGION]
|
||||
payload['force'] = True
|
||||
payload['source'] = FAKE_SOURCE_REGION
|
||||
payload['resources'] = [fake_flavor]
|
||||
mock_nova().get_flavor_access_tenant.return_value = access_tenants
|
||||
mock_endpoint_cache().get_session_from_token.\
|
||||
return_value = 'fake_session'
|
||||
mock_nova().get_flavor.return_value = fake_flavor
|
||||
mock_db_api().resource_sync_status.return_value = [JOB_RESULT]
|
||||
fsm = flavor_sync_manager.FlavorSyncManager()
|
||||
fsm.resource_sync(self.ctxt, FAKE_JOB_ID, payload)
|
||||
mock_create_resource.assert_called_once_with(
|
||||
FAKE_JOB_ID, payload['force'], payload['target'][0], fake_flavor,
|
||||
'fake_session', self.ctxt, access_tenants)
|
||||
mock_nova().get_flavor_access_tenant.\
|
||||
assert_called_once_with(fake_flavor)
|
||||
mock_db_api.resource_sync_status.\
|
||||
assert_called_once_with(self.ctxt, FAKE_JOB_ID)
|
||||
mock_db_api.sync_job_update.\
|
||||
assert_called_once_with(self.ctxt, FAKE_JOB_ID, JOB_RESULT)
|
||||
|
||||
@mock.patch.object(flavor_sync_manager.FlavorSyncManager,
|
||||
'create_resources')
|
||||
def test_create_resources_in_region(self, mock_create_resource):
|
||||
access_tenants = None
|
||||
fake_flavor = FakeFlavor('fake_id', 512, 2, 30, 'fake_flavor', 1,
|
||||
1.0, False)
|
||||
payload = dict()
|
||||
payload['target'] = [FAKE_TARGET_REGION]
|
||||
payload['force'] = True
|
||||
payload['source'] = FAKE_SOURCE_REGION
|
||||
payload['resources'] = [fake_flavor]
|
||||
fsm = flavor_sync_manager.FlavorSyncManager()
|
||||
fsm.create_resources_in_region(FAKE_JOB_ID, payload['force'],
|
||||
payload['target'], fake_flavor,
|
||||
'fake_session', self.ctxt,
|
||||
access_tenants)
|
||||
mock_create_resource.assert_called_once_with(
|
||||
FAKE_JOB_ID, payload['force'], payload['target'][0], fake_flavor,
|
||||
'fake_session', self.ctxt, access_tenants)
|
||||
|
||||
@mock.patch.object(flavor_sync_manager, 'NovaClient')
|
||||
@mock.patch.object(flavor_sync_manager, 'db_api')
|
||||
def test_create_resources(self, mock_db_api, mock_nova):
|
||||
access_tenants = None
|
||||
fake_flavor = FakeFlavor('fake_id', 512, 2, 30, 'fake_flavor', 1,
|
||||
1.0, False)
|
||||
payload = dict()
|
||||
payload['target'] = [FAKE_TARGET_REGION]
|
||||
payload['force'] = True
|
||||
payload['source'] = FAKE_SOURCE_REGION
|
||||
payload['resources'] = [fake_flavor]
|
||||
fsm = flavor_sync_manager.FlavorSyncManager()
|
||||
fsm.create_resources(FAKE_JOB_ID, payload['force'],
|
||||
payload['target'][0], fake_flavor,
|
||||
'fake_session', self.ctxt, access_tenants)
|
||||
mock_nova().create_flavor.assert_called_once_with(
|
||||
payload['force'], fake_flavor, access_tenants)
|
||||
mock_db_api.resource_sync_update.assert_called_once_with(
|
||||
self.ctxt, FAKE_JOB_ID, payload['target'][0], fake_flavor.id,
|
||||
JOB_RESULT)
|
|
@ -58,6 +58,11 @@ class TestEngineService(base.KingbirdTestCase):
|
|||
self.service_obj.init_ksm()
|
||||
self.assertIsNotNone(self.service_obj.ksm)
|
||||
|
||||
@mock.patch.object(service, 'FlavorSyncManager')
|
||||
def test_init_fsm(self, mock_flavor_sync_manager):
|
||||
self.service_obj.init_fsm()
|
||||
self.assertIsNotNone(self.service_obj.fsm)
|
||||
|
||||
@mock.patch.object(service, 'ImageSyncManager')
|
||||
def test_init_ism(self, mock_image_sync_manager):
|
||||
self.service_obj.init_ism()
|
||||
|
@ -131,3 +136,11 @@ class TestEngineService(base.KingbirdTestCase):
|
|||
self.service_obj.image_sync(self.context, self.job_id, self.payload)
|
||||
mock_image_sync_manager().resource_sync.\
|
||||
assert_called_once_with(self.context, self.job_id, self.payload)
|
||||
|
||||
@mock.patch.object(service, 'FlavorSyncManager')
|
||||
def test_flavor_sync(self, mock_flavor_sync_manager):
|
||||
self.service_obj.init_tgm()
|
||||
self.service_obj.init_fsm()
|
||||
self.service_obj.flavor_sync(self.context, self.job_id, self.payload)
|
||||
mock_flavor_sync_manager().resource_sync.\
|
||||
assert_called_once_with(self.context, self.job_id, self.payload)
|
||||
|
|
Loading…
Reference in New Issue