Merge "Move the NovaInventory class to utils/openstack/nova.py"
This commit is contained in:
@@ -26,7 +26,6 @@ from blazar.db import utils as db_utils
|
||||
from blazar.manager import exceptions as manager_ex
|
||||
from blazar.plugins import base
|
||||
from blazar.plugins import oshosts as plugin
|
||||
from blazar.plugins.oshosts import nova_inventory
|
||||
from blazar.utils.openstack import nova
|
||||
from blazar.utils import trusts
|
||||
|
||||
@@ -243,7 +242,7 @@ class PhysicalHostPlugin(base.BasePlugin, nova.NovaClientWrapper):
|
||||
raise manager_ex.InvalidHost(host=host_values)
|
||||
|
||||
with trusts.create_ctx_from_trust(trust_id):
|
||||
inventory = nova_inventory.NovaInventory()
|
||||
inventory = nova.NovaInventory()
|
||||
servers = inventory.get_servers_per_host(host_ref)
|
||||
if servers:
|
||||
raise manager_ex.HostHavingServers(host=host_ref,
|
||||
@@ -326,7 +325,7 @@ class PhysicalHostPlugin(base.BasePlugin, nova.NovaClientWrapper):
|
||||
with trusts.create_ctx_from_trust(host['trust_id']):
|
||||
# TODO(sbauza):
|
||||
# - Check if no leases having this host scheduled
|
||||
inventory = nova_inventory.NovaInventory()
|
||||
inventory = nova.NovaInventory()
|
||||
servers = inventory.get_servers_per_host(
|
||||
host['hypervisor_hostname'])
|
||||
if servers:
|
||||
|
||||
@@ -1,84 +0,0 @@
|
||||
# Copyright (c) 2013 Bull.
|
||||
#
|
||||
# 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.
|
||||
|
||||
from novaclient import exceptions as nova_exceptions
|
||||
from oslo_config import cfg
|
||||
|
||||
from blazar.manager import exceptions as manager_exceptions
|
||||
from blazar.utils.openstack import nova
|
||||
|
||||
|
||||
class NovaInventory(nova.NovaClientWrapper):
|
||||
def __init__(self):
|
||||
super(NovaInventory, self).__init__(
|
||||
username=cfg.CONF.os_admin_username,
|
||||
password=cfg.CONF.os_admin_password,
|
||||
user_domain_name=cfg.CONF.os_admin_user_domain_name,
|
||||
project_name=cfg.CONF.os_admin_project_name,
|
||||
project_domain_name=cfg.CONF.os_admin_user_domain_name)
|
||||
|
||||
def get_host_details(self, host):
|
||||
"""Get Nova capabilities of a single host
|
||||
|
||||
:param host: UUID or name of nova-compute host
|
||||
:return: Dict of capabilities or raise HostNotFound
|
||||
"""
|
||||
try:
|
||||
hypervisor = self.nova.hypervisors.get(host)
|
||||
except nova_exceptions.NotFound:
|
||||
try:
|
||||
hypervisors_list = self.nova.hypervisors.search(host)
|
||||
except nova_exceptions.NotFound:
|
||||
raise manager_exceptions.HostNotFound(host=host)
|
||||
if len(hypervisors_list) > 1:
|
||||
raise manager_exceptions.MultipleHostsFound(host)
|
||||
else:
|
||||
hypervisor_id = hypervisors_list[0].id
|
||||
# NOTE(sbauza): No need to catch the exception as we're sure
|
||||
# that the hypervisor exists
|
||||
hypervisor = self.nova.hypervisors.get(hypervisor_id)
|
||||
try:
|
||||
return {'id': hypervisor.id,
|
||||
'hypervisor_hostname': hypervisor.hypervisor_hostname,
|
||||
'service_name': hypervisor.service['host'],
|
||||
'vcpus': hypervisor.vcpus,
|
||||
'cpu_info': hypervisor.cpu_info,
|
||||
'hypervisor_type': hypervisor.hypervisor_type,
|
||||
'hypervisor_version': hypervisor.hypervisor_version,
|
||||
'memory_mb': hypervisor.memory_mb,
|
||||
'local_gb': hypervisor.local_gb}
|
||||
except AttributeError:
|
||||
raise manager_exceptions.InvalidHost(host=host)
|
||||
|
||||
def get_servers_per_host(self, host):
|
||||
"""List all servers of a nova-compute host
|
||||
|
||||
:param host: Name (not UUID) of nova-compute host
|
||||
:return: Dict of servers or None
|
||||
"""
|
||||
try:
|
||||
hypervisors_list = self.nova.hypervisors.search(host, servers=True)
|
||||
except nova_exceptions.NotFound:
|
||||
raise manager_exceptions.HostNotFound(host=host)
|
||||
if len(hypervisors_list) > 1:
|
||||
raise manager_exceptions.MultipleHostsFound(host)
|
||||
else:
|
||||
try:
|
||||
return hypervisors_list[0].servers
|
||||
except AttributeError:
|
||||
# NOTE(sbauza): nova.hypervisors.search(servers=True) returns
|
||||
# a list of hosts without 'servers' attribute if no servers
|
||||
# are running on that host
|
||||
return None
|
||||
@@ -1,139 +0,0 @@
|
||||
# Copyright (c) 2013 Bull.
|
||||
#
|
||||
# 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.
|
||||
|
||||
from novaclient import exceptions as nova_exceptions
|
||||
from novaclient.v2 import hypervisors
|
||||
|
||||
from blazar import context
|
||||
from blazar.manager import exceptions as manager_exceptions
|
||||
from blazar.plugins.oshosts import nova_inventory
|
||||
from blazar import tests
|
||||
from blazar.utils.openstack import base
|
||||
|
||||
|
||||
class FakeNovaHypervisors(object):
|
||||
|
||||
class FakeHost(object):
|
||||
id = 1
|
||||
hypervisor_hostname = 'fake_name'
|
||||
vcpus = 1
|
||||
cpu_info = 'fake_cpu'
|
||||
hypervisor_type = 'fake_type'
|
||||
hypervisor_version = 1000000
|
||||
memory_mb = 8192
|
||||
local_gb = 10
|
||||
|
||||
servers = ['server1', 'server2']
|
||||
service = {'host': 'fake_name'}
|
||||
|
||||
@classmethod
|
||||
def get(cls, host):
|
||||
try:
|
||||
host = int(host)
|
||||
except ValueError:
|
||||
raise nova_exceptions.NotFound(404)
|
||||
if host == cls.FakeHost.id:
|
||||
return cls.FakeHost
|
||||
else:
|
||||
raise nova_exceptions.NotFound(404)
|
||||
|
||||
@classmethod
|
||||
def search(cls, host, servers=False):
|
||||
if host == 'multiple':
|
||||
return [cls.FakeHost, cls.FakeHost]
|
||||
if host == cls.FakeHost.service['host']:
|
||||
return [cls.FakeHost]
|
||||
else:
|
||||
raise nova_exceptions.NotFound(404)
|
||||
|
||||
@classmethod
|
||||
def expected(cls):
|
||||
return {'id': cls.FakeHost.id,
|
||||
'hypervisor_hostname': cls.FakeHost.hypervisor_hostname,
|
||||
'service_name': cls.FakeHost.service['host'],
|
||||
'vcpus': cls.FakeHost.vcpus,
|
||||
'cpu_info': cls.FakeHost.cpu_info,
|
||||
'hypervisor_type': cls.FakeHost.hypervisor_type,
|
||||
'hypervisor_version': cls.FakeHost.hypervisor_version,
|
||||
'memory_mb': cls.FakeHost.memory_mb,
|
||||
'local_gb': cls.FakeHost.local_gb}
|
||||
|
||||
|
||||
class NovaInventoryTestCase(tests.TestCase):
|
||||
def setUp(self):
|
||||
super(NovaInventoryTestCase, self).setUp()
|
||||
self.context = context
|
||||
self.patch(self.context, 'BlazarContext')
|
||||
self.nova_inventory = nova_inventory
|
||||
self.patch(base, 'url_for').return_value = 'http://foo.bar'
|
||||
self.inventory = self.nova_inventory.NovaInventory()
|
||||
|
||||
self.hypervisors_get = self.patch(hypervisors.HypervisorManager, 'get')
|
||||
self.hypervisors_get.side_effect = FakeNovaHypervisors.get
|
||||
self.hypervisors_search = self.patch(hypervisors.HypervisorManager,
|
||||
'search')
|
||||
self.hypervisors_search.side_effect = FakeNovaHypervisors.search
|
||||
|
||||
def test_get_host_details_with_host_id(self):
|
||||
host = self.inventory.get_host_details('1')
|
||||
expected = FakeNovaHypervisors.expected()
|
||||
self.assertEqual(expected, host)
|
||||
|
||||
def test_get_host_details_with_host_name(self):
|
||||
host = self.inventory.get_host_details('fake_name')
|
||||
expected = FakeNovaHypervisors.expected()
|
||||
self.assertEqual(expected, host)
|
||||
|
||||
def test_get_host_details_with_host_name_having_multiple_results(self):
|
||||
self.assertRaises(manager_exceptions.MultipleHostsFound,
|
||||
self.inventory.get_host_details, 'multiple')
|
||||
|
||||
def test_get_host_details_with_host_id_not_found(self):
|
||||
self.assertRaises(manager_exceptions.HostNotFound,
|
||||
self.inventory.get_host_details, '2')
|
||||
|
||||
def test_get_host_details_with_host_name_not_found(self):
|
||||
self.assertRaises(manager_exceptions.HostNotFound,
|
||||
self.inventory.get_host_details, 'wrong_name')
|
||||
|
||||
def test_get_host_details_with_invalid_host(self):
|
||||
invalid_host = FakeNovaHypervisors.FakeHost
|
||||
del invalid_host.vcpus
|
||||
self.hypervisors_get.return_value = invalid_host
|
||||
self.assertRaises(manager_exceptions.InvalidHost,
|
||||
self.inventory.get_host_details, '1')
|
||||
|
||||
def test_get_servers_per_host(self):
|
||||
servers = self.inventory.get_servers_per_host('fake_name')
|
||||
self.assertEqual(FakeNovaHypervisors.FakeHost.servers, servers)
|
||||
|
||||
def test_get_servers_per_host_with_host_id(self):
|
||||
self.assertRaises(manager_exceptions.HostNotFound,
|
||||
self.inventory.get_servers_per_host, '1')
|
||||
|
||||
def test_get_servers_per_host_with_host_not_found(self):
|
||||
self.assertRaises(manager_exceptions.HostNotFound,
|
||||
self.inventory.get_servers_per_host, 'wrong_name')
|
||||
|
||||
def test_get_servers_per_host_having_multiple_results(self):
|
||||
self.assertRaises(manager_exceptions.MultipleHostsFound,
|
||||
self.inventory.get_servers_per_host, 'multiple')
|
||||
|
||||
def test_get_servers_per_host_with_host_having_no_servers(self):
|
||||
host_with_zero_servers = FakeNovaHypervisors.FakeHost
|
||||
# NOTE(sbauza): We need to simulate a host having zero servers
|
||||
del host_with_zero_servers.servers
|
||||
servers = self.inventory.get_servers_per_host('fake_name')
|
||||
self.assertIsNone(servers)
|
||||
@@ -27,7 +27,6 @@ from blazar.manager import exceptions as manager_exceptions
|
||||
from blazar.manager import service
|
||||
from blazar.plugins import oshosts as plugin
|
||||
from blazar.plugins.oshosts import host_plugin
|
||||
from blazar.plugins.oshosts import nova_inventory
|
||||
from blazar import tests
|
||||
from blazar.utils.openstack import base
|
||||
from blazar.utils.openstack import nova
|
||||
@@ -52,7 +51,6 @@ class PhysicalHostPlugingSetupOnlyTestCase(tests.TestCase):
|
||||
self.host_plugin = host_plugin
|
||||
self.fake_phys_plugin = self.host_plugin.PhysicalHostPlugin()
|
||||
self.nova = nova
|
||||
self.nova_inventory = nova_inventory
|
||||
self.rp_create = self.patch(self.nova.ReservationPool, 'create')
|
||||
self.db_api = db_api
|
||||
self.db_host_extra_capability_get_all_per_host = (
|
||||
@@ -134,18 +132,17 @@ class PhysicalHostPluginTestCase(tests.TestCase):
|
||||
self.db_api, 'host_extra_capability_update')
|
||||
|
||||
self.nova = nova
|
||||
self.nova_inventory = nova_inventory
|
||||
self.rp_create = self.patch(self.nova.ReservationPool, 'create')
|
||||
self.patch(self.nova.ReservationPool, 'get_aggregate_from_name_or_id')
|
||||
self.add_compute_host = self.patch(self.nova.ReservationPool,
|
||||
'add_computehost')
|
||||
self.remove_compute_host = self.patch(self.nova.ReservationPool,
|
||||
'remove_computehost')
|
||||
self.get_host_details = self.patch(self.nova_inventory.NovaInventory,
|
||||
self.get_host_details = self.patch(self.nova.NovaInventory,
|
||||
'get_host_details')
|
||||
self.get_host_details.return_value = self.fake_host
|
||||
self.get_servers_per_host = self.patch(
|
||||
self.nova_inventory.NovaInventory, 'get_servers_per_host')
|
||||
self.nova.NovaInventory, 'get_servers_per_host')
|
||||
self.get_servers_per_host.return_value = None
|
||||
self.get_extra_capabilities = self.patch(
|
||||
self.fake_phys_plugin, '_get_extra_capabilities')
|
||||
|
||||
@@ -18,6 +18,7 @@ from keystoneauth1 import session
|
||||
from keystoneauth1 import token_endpoint
|
||||
from novaclient import client as nova_client
|
||||
from novaclient import exceptions as nova_exceptions
|
||||
from novaclient.v2 import hypervisors
|
||||
from oslo_config import cfg
|
||||
|
||||
from blazar import context
|
||||
@@ -405,3 +406,119 @@ class ReservationPoolTestCase(tests.TestCase):
|
||||
check = self.nova.aggregates.set_metadata
|
||||
check.assert_called_once_with(self.fake_aggregate.id,
|
||||
{'projectY': None})
|
||||
|
||||
|
||||
class FakeNovaHypervisors(object):
|
||||
|
||||
class FakeHost(object):
|
||||
id = 1
|
||||
hypervisor_hostname = 'fake_name'
|
||||
vcpus = 1
|
||||
cpu_info = 'fake_cpu'
|
||||
hypervisor_type = 'fake_type'
|
||||
hypervisor_version = 1000000
|
||||
memory_mb = 8192
|
||||
local_gb = 10
|
||||
|
||||
servers = ['server1', 'server2']
|
||||
service = {'host': 'fake_name'}
|
||||
|
||||
@classmethod
|
||||
def get(cls, host):
|
||||
try:
|
||||
host = int(host)
|
||||
except ValueError:
|
||||
raise nova_exceptions.NotFound(404)
|
||||
if host == cls.FakeHost.id:
|
||||
return cls.FakeHost
|
||||
else:
|
||||
raise nova_exceptions.NotFound(404)
|
||||
|
||||
@classmethod
|
||||
def search(cls, host, servers=False):
|
||||
if host == 'multiple':
|
||||
return [cls.FakeHost, cls.FakeHost]
|
||||
if host == cls.FakeHost.service['host']:
|
||||
return [cls.FakeHost]
|
||||
else:
|
||||
raise nova_exceptions.NotFound(404)
|
||||
|
||||
@classmethod
|
||||
def expected(cls):
|
||||
return {'id': cls.FakeHost.id,
|
||||
'hypervisor_hostname': cls.FakeHost.hypervisor_hostname,
|
||||
'service_name': cls.FakeHost.service['host'],
|
||||
'vcpus': cls.FakeHost.vcpus,
|
||||
'cpu_info': cls.FakeHost.cpu_info,
|
||||
'hypervisor_type': cls.FakeHost.hypervisor_type,
|
||||
'hypervisor_version': cls.FakeHost.hypervisor_version,
|
||||
'memory_mb': cls.FakeHost.memory_mb,
|
||||
'local_gb': cls.FakeHost.local_gb}
|
||||
|
||||
|
||||
class NovaInventoryTestCase(tests.TestCase):
|
||||
def setUp(self):
|
||||
super(NovaInventoryTestCase, self).setUp()
|
||||
self.context = context
|
||||
self.patch(self.context, 'BlazarContext')
|
||||
self.nova = nova
|
||||
self.patch(base, 'url_for').return_value = 'http://foo.bar'
|
||||
self.inventory = self.nova.NovaInventory()
|
||||
|
||||
self.hypervisors_get = self.patch(hypervisors.HypervisorManager, 'get')
|
||||
self.hypervisors_get.side_effect = FakeNovaHypervisors.get
|
||||
self.hypervisors_search = self.patch(hypervisors.HypervisorManager,
|
||||
'search')
|
||||
self.hypervisors_search.side_effect = FakeNovaHypervisors.search
|
||||
|
||||
def test_get_host_details_with_host_id(self):
|
||||
host = self.inventory.get_host_details('1')
|
||||
expected = FakeNovaHypervisors.expected()
|
||||
self.assertEqual(expected, host)
|
||||
|
||||
def test_get_host_details_with_host_name(self):
|
||||
host = self.inventory.get_host_details('fake_name')
|
||||
expected = FakeNovaHypervisors.expected()
|
||||
self.assertEqual(expected, host)
|
||||
|
||||
def test_get_host_details_with_host_name_having_multiple_results(self):
|
||||
self.assertRaises(manager_exceptions.MultipleHostsFound,
|
||||
self.inventory.get_host_details, 'multiple')
|
||||
|
||||
def test_get_host_details_with_host_id_not_found(self):
|
||||
self.assertRaises(manager_exceptions.HostNotFound,
|
||||
self.inventory.get_host_details, '2')
|
||||
|
||||
def test_get_host_details_with_host_name_not_found(self):
|
||||
self.assertRaises(manager_exceptions.HostNotFound,
|
||||
self.inventory.get_host_details, 'wrong_name')
|
||||
|
||||
def test_get_host_details_with_invalid_host(self):
|
||||
invalid_host = FakeNovaHypervisors.FakeHost
|
||||
del invalid_host.vcpus
|
||||
self.hypervisors_get.return_value = invalid_host
|
||||
self.assertRaises(manager_exceptions.InvalidHost,
|
||||
self.inventory.get_host_details, '1')
|
||||
|
||||
def test_get_servers_per_host(self):
|
||||
servers = self.inventory.get_servers_per_host('fake_name')
|
||||
self.assertEqual(FakeNovaHypervisors.FakeHost.servers, servers)
|
||||
|
||||
def test_get_servers_per_host_with_host_id(self):
|
||||
self.assertRaises(manager_exceptions.HostNotFound,
|
||||
self.inventory.get_servers_per_host, '1')
|
||||
|
||||
def test_get_servers_per_host_with_host_not_found(self):
|
||||
self.assertRaises(manager_exceptions.HostNotFound,
|
||||
self.inventory.get_servers_per_host, 'wrong_name')
|
||||
|
||||
def test_get_servers_per_host_having_multiple_results(self):
|
||||
self.assertRaises(manager_exceptions.MultipleHostsFound,
|
||||
self.inventory.get_servers_per_host, 'multiple')
|
||||
|
||||
def test_get_servers_per_host_with_host_having_no_servers(self):
|
||||
host_with_zero_servers = FakeNovaHypervisors.FakeHost
|
||||
# NOTE(sbauza): We need to simulate a host having zero servers
|
||||
del host_with_zero_servers.servers
|
||||
servers = self.inventory.get_servers_per_host('fake_name')
|
||||
self.assertEqual(None, servers)
|
||||
|
||||
@@ -421,3 +421,60 @@ class ReservationPool(NovaClientWrapper):
|
||||
|
||||
metadata = {project_id: None}
|
||||
return self.nova.aggregates.set_metadata(agg.id, metadata)
|
||||
|
||||
|
||||
class NovaInventory(NovaClientWrapper):
|
||||
|
||||
def get_host_details(self, host):
|
||||
"""Get Nova capabilities of a single host
|
||||
|
||||
:param host: UUID or name of nova-compute host
|
||||
:return: Dict of capabilities or raise HostNotFound
|
||||
"""
|
||||
try:
|
||||
hypervisor = self.nova.hypervisors.get(host)
|
||||
except nova_exception.NotFound:
|
||||
try:
|
||||
hypervisors_list = self.nova.hypervisors.search(host)
|
||||
except nova_exception.NotFound:
|
||||
raise manager_exceptions.HostNotFound(host=host)
|
||||
if len(hypervisors_list) > 1:
|
||||
raise manager_exceptions.MultipleHostsFound(host)
|
||||
else:
|
||||
hypervisor_id = hypervisors_list[0].id
|
||||
# NOTE(sbauza): No need to catch the exception as we're sure
|
||||
# that the hypervisor exists
|
||||
hypervisor = self.nova.hypervisors.get(hypervisor_id)
|
||||
try:
|
||||
return {'id': hypervisor.id,
|
||||
'hypervisor_hostname': hypervisor.hypervisor_hostname,
|
||||
'service_name': hypervisor.service['host'],
|
||||
'vcpus': hypervisor.vcpus,
|
||||
'cpu_info': hypervisor.cpu_info,
|
||||
'hypervisor_type': hypervisor.hypervisor_type,
|
||||
'hypervisor_version': hypervisor.hypervisor_version,
|
||||
'memory_mb': hypervisor.memory_mb,
|
||||
'local_gb': hypervisor.local_gb}
|
||||
except AttributeError:
|
||||
raise manager_exceptions.InvalidHost(host=host)
|
||||
|
||||
def get_servers_per_host(self, host):
|
||||
"""List all servers of a nova-compute host
|
||||
|
||||
:param host: Name (not UUID) of nova-compute host
|
||||
:return: Dict of servers or None
|
||||
"""
|
||||
try:
|
||||
hypervisors_list = self.nova.hypervisors.search(host, servers=True)
|
||||
except nova_exception.NotFound:
|
||||
raise manager_exceptions.HostNotFound(host=host)
|
||||
if len(hypervisors_list) > 1:
|
||||
raise manager_exceptions.MultipleHostsFound(host)
|
||||
else:
|
||||
try:
|
||||
return hypervisors_list[0].servers
|
||||
except AttributeError:
|
||||
# NOTE(sbauza): nova.hypervisors.search(servers=True) returns
|
||||
# a list of hosts without 'servers' attribute if no servers
|
||||
# are running on that host
|
||||
return None
|
||||
|
||||
Reference in New Issue
Block a user