Merge "Add a cell and host mapping utility to nova-manage"

This commit is contained in:
Jenkins 2016-03-15 22:42:30 +00:00 committed by Gerrit Code Review
commit bc5035343d
2 changed files with 208 additions and 0 deletions

View File

@ -66,6 +66,7 @@ from oslo_db import exception as db_exc
from oslo_log import log as logging
import oslo_messaging as messaging
from oslo_utils import importutils
from oslo_utils import uuidutils
import six
from nova.api.ec2 import ec2utils
@ -95,6 +96,7 @@ CONF.import_opt('vlan_start', 'nova.network.manager')
CONF.import_opt('vpn_start', 'nova.network.manager')
CONF.import_opt('default_floating_pool', 'nova.network.floating_ips')
CONF.import_opt('public_interface', 'nova.network.linux_net')
CONF.import_opt('connection', 'oslo_db.options', group='database')
QUOTAS = quota.QUOTAS
@ -1360,6 +1362,74 @@ class CellV2Commands(object):
instance = instances[-1]
print('Next marker: - %s' % instance.uuid)
# TODO(melwitt): Remove this when the oslo.messaging function
# for assembling a transport url from ConfigOpts is available
@args('--transport-url', metavar='<transport url>', required=True,
dest='transport_url',
help='The transport url for the cell message queue')
@args('--name', metavar='<name>', help='The name of the cell')
@args('--verbose', action='store_true',
help='Return and output the uuid of the created cell')
def map_cell_and_hosts(self, transport_url, name=None, verbose=False):
"""EXPERIMENTAL. Create a cell mapping and host mappings for a cell.
Users not dividing their cloud into multiple cells will be a single
cell v2 deployment and should specify:
nova-manage cell_v2 map_cell_and_hosts --config-file <nova.conf>
Users running multiple cells can add a cell v2 by specifying:
nova-manage cell_v2 map_cell_and_hosts --config-file <cell nova.conf>
"""
ctxt = context.RequestContext()
cell_mapping_uuid = cell_mapping = None
# First, try to detect if a CellMapping has already been created
compute_nodes = objects.ComputeNodeList.get_all(ctxt)
if not compute_nodes:
print(_('No hosts found to map to cell, exiting.'))
return(0)
missing_nodes = []
for compute_node in compute_nodes:
try:
host_mapping = objects.HostMapping.get_by_host(
ctxt, compute_node.host)
except exception.HostMappingNotFound:
missing_nodes.append(compute_node)
else:
if verbose:
print(_(
'Host %(host)s is already mapped to cell %(uuid)s'
) % {'host': host_mapping.host,
'uuid': host_mapping.cell_mapping.uuid})
# Re-using the existing UUID in case there is already a mapping
# NOTE(sbauza): There could be possibly multiple CellMappings
# if the operator provides another configuration file and moves
# the hosts to another cell v2, but that's not really something
# we should support.
cell_mapping_uuid = host_mapping.cell_mapping.uuid
if not missing_nodes:
print(_('All hosts are already mapped to cell(s), exiting.'))
return(0)
# Create the cell mapping in the API database
if cell_mapping_uuid is not None:
cell_mapping = objects.CellMapping.get_by_uuid(
ctxt, cell_mapping_uuid)
if cell_mapping is None:
cell_mapping_uuid = uuidutils.generate_uuid()
cell_mapping = objects.CellMapping(
ctxt, uuid=cell_mapping_uuid, name=name,
transport_url=transport_url,
database_connection=CONF.database.connection)
cell_mapping.create()
# Pull the hosts from the cell database and create the host mappings
for compute_node in missing_nodes:
host_mapping = objects.HostMapping(
ctxt, host=compute_node.host, cell_mapping=cell_mapping)
host_mapping.create()
if verbose:
print(cell_mapping_uuid)
CATEGORIES = {
'account': AccountCommands,

View File

@ -18,6 +18,7 @@ import sys
import fixtures
import mock
from oslo_utils import uuidutils
from nova.cmd import manage
from nova import context
@ -680,3 +681,140 @@ class CellCommandsTestCase(test.NoDBTestCase):
'weight_offset': 0.0,
'weight_scale': 0.0}
mock_db_cell_create.assert_called_once_with(ctxt, exp_values)
class CellV2CommandsTestCase(test.TestCase):
def setUp(self):
super(CellV2CommandsTestCase, self).setUp()
self.useFixture(fixtures.MonkeyPatch('sys.stdout', StringIO()))
self.commands = manage.CellV2Commands()
def test_map_cell_and_hosts(self):
# Create some fake compute nodes and check if they get host mappings
ctxt = context.RequestContext()
values = {
'vcpus': 4,
'memory_mb': 4096,
'local_gb': 1024,
'vcpus_used': 2,
'memory_mb_used': 2048,
'local_gb_used': 512,
'hypervisor_type': 'Hyper-Dan-VM-ware',
'hypervisor_version': 1001,
'cpu_info': 'Schmintel i786',
}
for i in range(3):
host = 'host%s' % i
compute_node = objects.ComputeNode(ctxt, host=host, **values)
compute_node.create()
cell_transport_url = "fake://guest:devstack@127.0.0.1:9999/"
self.commands.map_cell_and_hosts(cell_transport_url, name='ssd',
verbose=True)
cell_mapping_uuid = sys.stdout.getvalue().strip()
# Verify the cell mapping
cell_mapping = objects.CellMapping.get_by_uuid(ctxt, cell_mapping_uuid)
self.assertEqual('ssd', cell_mapping.name)
self.assertEqual(cell_transport_url, cell_mapping.transport_url)
# Verify the host mappings
for i in range(3):
host = 'host%s' % i
host_mapping = objects.HostMapping.get_by_host(ctxt, host)
self.assertEqual(cell_mapping.uuid, host_mapping.cell_mapping.uuid)
def test_map_cell_and_hosts_duplicate(self):
# Create a cell mapping and hosts and check that nothing new is created
ctxt = context.RequestContext()
cell_mapping_uuid = uuidutils.generate_uuid()
cell_mapping = objects.CellMapping(
ctxt, uuid=cell_mapping_uuid, name='fake',
transport_url='fake://', database_connection='fake://')
cell_mapping.create()
# Create compute nodes that will map to the cell
values = {
'vcpus': 4,
'memory_mb': 4096,
'local_gb': 1024,
'vcpus_used': 2,
'memory_mb_used': 2048,
'local_gb_used': 512,
'hypervisor_type': 'Hyper-Dan-VM-ware',
'hypervisor_version': 1001,
'cpu_info': 'Schmintel i786',
}
for i in range(3):
host = 'host%s' % i
compute_node = objects.ComputeNode(ctxt, host=host, **values)
compute_node.create()
host_mapping = objects.HostMapping(
ctxt, host=host, cell_mapping=cell_mapping)
host_mapping.create()
cell_transport_url = "fake://guest:devstack@127.0.0.1:9999/"
retval = self.commands.map_cell_and_hosts(cell_transport_url,
name='ssd',
verbose=True)
self.assertEqual(0, retval)
output = sys.stdout.getvalue().strip()
expected = ''
for i in range(3):
expected += ('Host host%s is already mapped to cell %s\n' %
(i, cell_mapping_uuid))
expected += 'All hosts are already mapped to cell(s), exiting.'
self.assertEqual(expected, output)
def test_map_cell_and_hosts_partial_update(self):
# Create a cell mapping and partial hosts and check that
# missing HostMappings are created
ctxt = context.RequestContext()
cell_mapping_uuid = uuidutils.generate_uuid()
cell_mapping = objects.CellMapping(
ctxt, uuid=cell_mapping_uuid, name='fake',
transport_url='fake://', database_connection='fake://')
cell_mapping.create()
# Create compute nodes that will map to the cell
values = {
'vcpus': 4,
'memory_mb': 4096,
'local_gb': 1024,
'vcpus_used': 2,
'memory_mb_used': 2048,
'local_gb_used': 512,
'hypervisor_type': 'Hyper-Dan-VM-ware',
'hypervisor_version': 1001,
'cpu_info': 'Schmintel i786',
}
for i in range(3):
host = 'host%s' % i
compute_node = objects.ComputeNode(ctxt, host=host, **values)
compute_node.create()
# Only create 2 existing HostMappings out of 3
for i in range(2):
host = 'host%s' % i
host_mapping = objects.HostMapping(
ctxt, host=host, cell_mapping=cell_mapping)
host_mapping.create()
cell_transport_url = "fake://guest:devstack@127.0.0.1:9999/"
self.commands.map_cell_and_hosts(cell_transport_url,
name='ssd',
verbose=True)
# Verify the HostMapping for the last host was created
host_mapping = objects.HostMapping.get_by_host(ctxt, 'host2')
self.assertEqual(cell_mapping.uuid, host_mapping.cell_mapping.uuid)
# Verify the output
output = sys.stdout.getvalue().strip()
expected = ''
for i in range(2):
expected += ('Host host%s is already mapped to cell %s\n' %
(i, cell_mapping_uuid))
# The expected CellMapping UUID for the last host should be the same
expected += cell_mapping.uuid
self.assertEqual(expected, output)
def test_map_cell_and_hosts_no_hosts_found(self):
cell_transport_url = "fake://guest:devstack@127.0.0.1:9999/"
retval = self.commands.map_cell_and_hosts(cell_transport_url,
name='ssd',
verbose=True)
self.assertEqual(0, retval)
output = sys.stdout.getvalue().strip()
expected = 'No hosts found to map to cell, exiting.'
self.assertEqual(expected, output)