summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJenkins <jenkins@review.openstack.org>2013-02-21 00:30:45 +0000
committerGerrit Code Review <review@openstack.org>2013-02-21 00:30:45 +0000
commit65d315929d64fcf199271a21c62c4cd2649556fc (patch)
treeefe233306ec863e0ec6c477a5b21b2a9f45efd38
parent61290aa603f08a927f7c7a82f0b5d0319b7c67f8 (diff)
parentab9f8667c63d901f37d1662c5204fb2938be44fe (diff)
downloadnova-65d315929d64fcf199271a21c62c4cd2649556fc.tar.gz
nova-65d315929d64fcf199271a21c62c4cd2649556fc.tar.xz
nova-65d315929d64fcf199271a21c62c4cd2649556fc.zip
Merge "Identify baremetal nodes by UUID."
-rw-r--r--nova/exception.py8
-rw-r--r--nova/tests/baremetal/db/test_bm_node.py6
-rw-r--r--nova/tests/baremetal/db/utils.py1
-rw-r--r--nova/tests/baremetal/test_driver.py28
-rw-r--r--nova/virt/baremetal/db/api.py8
-rw-r--r--nova/virt/baremetal/db/sqlalchemy/api.py38
-rw-r--r--nova/virt/baremetal/db/sqlalchemy/migrate_repo/versions/003_add_uuid_to_bm_nodes.py40
-rw-r--r--nova/virt/baremetal/db/sqlalchemy/models.py1
-rwxr-xr-xnova/virt/baremetal/driver.py32
-rw-r--r--nova/virt/baremetal/pxe.py4
10 files changed, 123 insertions, 43 deletions
diff --git a/nova/exception.py b/nova/exception.py
index 6d876f5b4..cad1c5c02 100644
--- a/nova/exception.py
+++ b/nova/exception.py
@@ -1060,6 +1060,14 @@ class InstanceNotFound(NotFound):
message = _("Instance %(instance_id)s could not be found.")
+class NodeNotFound(NotFound):
+ message = _("Node %(node_id)s could not be found.")
+
+
+class NodeNotFoundByUUID(NotFound):
+ message = _("Node with UUID %(node_uuid)s could not be found.")
+
+
class MarkerNotFound(NotFound):
message = _("Marker %(marker)s could not be found.")
diff --git a/nova/tests/baremetal/db/test_bm_node.py b/nova/tests/baremetal/db/test_bm_node.py
index 3caa49cf1..204a6bf7b 100644
--- a/nova/tests/baremetal/db/test_bm_node.py
+++ b/nova/tests/baremetal/db/test_bm_node.py
@@ -65,7 +65,7 @@ class BareMetalNodesTestCase(base.BMDBTestCase):
self.assertEquals(r['pm_address'], '1')
self.assertRaises(
- exception.InstanceNotFound,
+ exception.NodeNotFound,
db.bm_node_get,
self.context, -1)
@@ -113,7 +113,7 @@ class BareMetalNodesTestCase(base.BMDBTestCase):
db.bm_node_destroy(self.context, self.ids[0])
self.assertRaises(
- exception.InstanceNotFound,
+ exception.NodeNotFound,
db.bm_node_get,
self.context, self.ids[0])
@@ -147,7 +147,7 @@ class BareMetalNodesTestCase(base.BMDBTestCase):
self.assertEqual(self.ids[1], if_x['bm_node_id'])
self.assertRaises(
- exception.InstanceNotFound,
+ exception.NodeNotFound,
db.bm_node_get,
self.context, self.ids[0])
diff --git a/nova/tests/baremetal/db/utils.py b/nova/tests/baremetal/db/utils.py
index 800305402..e3a7b8489 100644
--- a/nova/tests/baremetal/db/utils.py
+++ b/nova/tests/baremetal/db/utils.py
@@ -22,6 +22,7 @@ from nova.virt.baremetal.db.sqlalchemy import models as bm_models
def new_bm_node(**kwargs):
h = bm_models.BareMetalNode()
h.id = kwargs.pop('id', None)
+ h.uuid = kwargs.pop('uuid', None)
h.service_host = kwargs.pop('service_host', None)
h.instance_uuid = kwargs.pop('instance_uuid', None)
h.cpus = kwargs.pop('cpus', 1)
diff --git a/nova/tests/baremetal/test_driver.py b/nova/tests/baremetal/test_driver.py
index 21956b7b1..160ca35df 100644
--- a/nova/tests/baremetal/test_driver.py
+++ b/nova/tests/baremetal/test_driver.py
@@ -111,7 +111,7 @@ class BareMetalDriverWithDBTestCase(bm_db_base.BMDBTestCase):
nic['port_no'],
)
result['instance'] = utils.get_test_instance()
- result['instance']['node'] = result['node']['id']
+ result['instance']['node'] = result['node']['uuid']
result['spawn_params'] = dict(
admin_password='test_pass',
block_device_info=None,
@@ -139,7 +139,7 @@ class BareMetalDriverWithDBTestCase(bm_db_base.BMDBTestCase):
self.assertEqual(stats['cpu_arch'], 'test')
self.assertEqual(stats['test_spec'], 'test_value')
self.assertEqual(stats['hypervisor_type'], 'baremetal')
- self.assertEqual(stats['hypervisor_hostname'], '123')
+ self.assertEqual(stats['hypervisor_hostname'], node['node']['uuid'])
self.assertEqual(stats['host'], 'test_host')
self.assertEqual(stats['vcpus'], 2)
self.assertEqual(stats['host_memory_total'], 2048)
@@ -153,7 +153,15 @@ class BareMetalDriverWithDBTestCase(bm_db_base.BMDBTestCase):
def test_macs_for_instance(self):
node = self._create_node()
- expected = set(['01:23:45:67:89:01', '01:23:45:67:89:02'])
+ expected = set([nic['address'] for nic in node['nic_info']])
+ self.assertEqual(
+ expected, self.driver.macs_for_instance(node['instance']))
+
+ def test_macs_for_instance_after_spawn(self):
+ node = self._create_node()
+ self.driver.spawn(**node['spawn_params'])
+
+ expected = set([nic['address'] for nic in node['nic_info']])
self.assertEqual(
expected, self.driver.macs_for_instance(node['instance']))
@@ -184,12 +192,12 @@ class BareMetalDriverWithDBTestCase(bm_db_base.BMDBTestCase):
def test_spawn_node_not_found(self):
node = self._create_node()
db.bm_node_update(self.context, node['node']['id'],
- {'id': 9876})
+ {'uuid': 'hide-this-node'})
self.assertRaises(exception.NovaException,
self.driver.spawn, **node['spawn_params'])
- row = db.bm_node_get(self.context, 9876)
+ row = db.bm_node_get(self.context, node['node']['id'])
self.assertEqual(row['task_state'], None)
def test_spawn_fails(self):
@@ -247,18 +255,18 @@ class BareMetalDriverWithDBTestCase(bm_db_base.BMDBTestCase):
def test_get_available_resources(self):
node = self._create_node()
- resources = self.driver.get_available_resource(node['node']['id'])
+ resources = self.driver.get_available_resource(node['node']['uuid'])
self.assertEqual(resources['memory_mb'],
node['node_info']['memory_mb'])
self.assertEqual(resources['memory_mb_used'], 0)
self.driver.spawn(**node['spawn_params'])
- resources = self.driver.get_available_resource(node['node']['id'])
+ resources = self.driver.get_available_resource(node['node']['uuid'])
self.assertEqual(resources['memory_mb_used'],
node['node_info']['memory_mb'])
self.driver.destroy(**node['destroy_params'])
- resources = self.driver.get_available_resource(node['node']['id'])
+ resources = self.driver.get_available_resource(node['node']['uuid'])
self.assertEqual(resources['memory_mb_used'], 0)
def test_get_available_nodes(self):
@@ -281,7 +289,7 @@ class BareMetalDriverWithDBTestCase(bm_db_base.BMDBTestCase):
]
node2 = self._create_node(node_info=node_info, nic_info=nic_info)
self.assertEqual(2, len(self.driver.get_available_nodes()))
- self.assertEqual(['123', '456'],
+ self.assertEqual([node1['node']['uuid'], node2['node']['uuid']],
self.driver.get_available_nodes())
node1['instance']['hostname'] = 'test-host-1'
@@ -298,5 +306,5 @@ class BareMetalDriverWithDBTestCase(bm_db_base.BMDBTestCase):
self.driver.destroy(**node2['destroy_params'])
self.assertEqual(2, len(self.driver.get_available_nodes()))
- self.assertEqual(['123', '456'],
+ self.assertEqual([node1['node']['uuid'], node2['node']['uuid']],
self.driver.get_available_nodes())
diff --git a/nova/virt/baremetal/db/api.py b/nova/virt/baremetal/db/api.py
index 44a5c1bcd..91edc05d9 100644
--- a/nova/virt/baremetal/db/api.py
+++ b/nova/virt/baremetal/db/api.py
@@ -101,6 +101,10 @@ def bm_node_get_by_instance_uuid(context, instance_uuid):
instance_uuid)
+def bm_node_get_by_node_uuid(context, node_uuid):
+ return IMPL.bm_node_get_by_node_uuid(context, node_uuid)
+
+
def bm_node_create(context, values):
return IMPL.bm_node_create(context, values)
@@ -113,8 +117,8 @@ def bm_node_update(context, bm_node_id, values):
return IMPL.bm_node_update(context, bm_node_id, values)
-def bm_node_set_uuid_safe(context, bm_node_id, uuid):
- return IMPL.bm_node_set_uuid_safe(context, bm_node_id, uuid)
+def bm_node_associate_and_update(context, node_uuid, values):
+ return IMPL.bm_node_associate_and_update(context, node_uuid, values)
def bm_pxe_ip_create(context, address, server_address):
diff --git a/nova/virt/baremetal/db/sqlalchemy/api.py b/nova/virt/baremetal/db/sqlalchemy/api.py
index 4a27e48be..e06bcd7d2 100644
--- a/nova/virt/baremetal/db/sqlalchemy/api.py
+++ b/nova/virt/baremetal/db/sqlalchemy/api.py
@@ -20,6 +20,8 @@
"""Implementation of SQLAlchemy backend."""
+import uuid
+
from sqlalchemy.sql.expression import asc
from sqlalchemy.sql.expression import literal_column
@@ -132,7 +134,7 @@ def bm_node_get(context, bm_node_id):
first()
if not result:
- raise exception.InstanceNotFound(instance_id=bm_node_id)
+ raise exception.NodeNotFound(node_id=bm_node_id)
return result
@@ -153,7 +155,21 @@ def bm_node_get_by_instance_uuid(context, instance_uuid):
@sqlalchemy_api.require_admin_context
+def bm_node_get_by_node_uuid(context, bm_node_uuid):
+ result = model_query(context, models.BareMetalNode, read_deleted="no").\
+ filter_by(uuid=bm_node_uuid).\
+ first()
+
+ if not result:
+ raise exception.NodeNotFoundByUUID(node_uuid=bm_node_uuid)
+
+ return result
+
+
+@sqlalchemy_api.require_admin_context
def bm_node_create(context, values):
+ if not values.get('uuid'):
+ values['uuid'] = str(uuid.uuid4())
bm_node_ref = models.BareMetalNode()
bm_node_ref.update(values)
_save(bm_node_ref)
@@ -167,11 +183,11 @@ def bm_node_update(context, bm_node_id, values):
update(values)
if not rows:
- raise exception.InstanceNotFound(instance_id=bm_node_id)
+ raise exception.NodeNotFound(node_id=bm_node_id)
@sqlalchemy_api.require_admin_context
-def bm_node_set_uuid_safe(context, bm_node_id, values):
+def bm_node_associate_and_update(context, node_uuid, values):
"""Associate an instance to a node safely
Associate an instance to a node only if that node is not yet assocated.
@@ -182,21 +198,21 @@ def bm_node_set_uuid_safe(context, bm_node_id, values):
"""
if 'instance_uuid' not in values:
raise exception.NovaException(_(
- "instance_uuid must be supplied to bm_node_set_uuid_safe"))
+ "instance_uuid must be supplied to bm_node_associate_and_update"))
session = db_session.get_session()
with session.begin():
query = model_query(context, models.BareMetalNode,
session=session, read_deleted="no").\
- filter_by(id=bm_node_id)
+ filter_by(uuid=node_uuid)
count = query.filter_by(instance_uuid=None).\
update(values, synchronize_session=False)
if count != 1:
raise exception.NovaException(_(
- "Failed to associate instance %(uuid)s to baremetal node "
- "%(id)s.") % {'id': bm_node_id,
- 'uuid': values['instance_uuid']})
+ "Failed to associate instance %(i_uuid)s to baremetal node "
+ "%(n_uuid)s.") % {'i_uuid': values['instance_uuid'],
+ 'n_uuid': node_uuid})
ref = query.first()
return ref
@@ -270,7 +286,7 @@ def bm_pxe_ip_get_by_bm_node_id(context, bm_node_id):
first()
if not result:
- raise exception.InstanceNotFound(instance_id=bm_node_id)
+ raise exception.NodeNotFound(node_id=bm_node_id)
return result
@@ -285,7 +301,7 @@ def bm_pxe_ip_associate(context, bm_node_id):
filter_by(id=bm_node_id).\
first()
if not node_ref:
- raise exception.InstanceNotFound(instance_id=bm_node_id)
+ raise exception.NodeNotFound(node_id=bm_node_id)
# Check if the node already has a pxe_ip
ip_ref = model_query(context, models.BareMetalPxeIp,
@@ -408,6 +424,6 @@ def bm_interface_get_all_by_bm_node_id(context, bm_node_id):
all()
if not result:
- raise exception.InstanceNotFound(instance_id=bm_node_id)
+ raise exception.NodeNotFound(node_id=bm_node_id)
return result
diff --git a/nova/virt/baremetal/db/sqlalchemy/migrate_repo/versions/003_add_uuid_to_bm_nodes.py b/nova/virt/baremetal/db/sqlalchemy/migrate_repo/versions/003_add_uuid_to_bm_nodes.py
new file mode 100644
index 000000000..cc9a9316d
--- /dev/null
+++ b/nova/virt/baremetal/db/sqlalchemy/migrate_repo/versions/003_add_uuid_to_bm_nodes.py
@@ -0,0 +1,40 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2013 Hewlett-Packard Development Company, L.P.
+# All Rights Reserved.
+#
+# 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 sqlalchemy import Column, MetaData, String, Table, Index
+
+
+def upgrade(migrate_engine):
+ meta = MetaData()
+ meta.bind = migrate_engine
+
+ t = Table('bm_nodes', meta, autoload=True)
+ uuid_col = Column('uuid', String(36))
+ t.create_column(uuid_col)
+
+ uuid_ux = Index('uuid_ux', t.c.uuid, unique=True)
+ uuid_ux.create(migrate_engine)
+
+
+def downgrade(migrate_engine):
+ meta = MetaData()
+ meta.bind = migrate_engine
+
+ t = Table('bm_nodes', meta, autoload=True)
+ uuid_col = Column('uuid', String(length=36))
+
+ t.drop_column(uuid_col)
diff --git a/nova/virt/baremetal/db/sqlalchemy/models.py b/nova/virt/baremetal/db/sqlalchemy/models.py
index fe86d7244..e1a8ebb3a 100644
--- a/nova/virt/baremetal/db/sqlalchemy/models.py
+++ b/nova/virt/baremetal/db/sqlalchemy/models.py
@@ -34,6 +34,7 @@ class BareMetalNode(BASE, models.NovaBase):
__tablename__ = 'bm_nodes'
id = Column(Integer, primary_key=True)
+ uuid = Column(String(36))
service_host = Column(String(255))
instance_uuid = Column(String(36), nullable=True)
cpus = Column(Integer)
diff --git a/nova/virt/baremetal/driver.py b/nova/virt/baremetal/driver.py
index d3d45682b..b95a3ad61 100755
--- a/nova/virt/baremetal/driver.py
+++ b/nova/virt/baremetal/driver.py
@@ -186,17 +186,17 @@ class BareMetalDriver(driver.ComputeDriver):
return l
def _require_node(self, instance):
- """Get a node_id out of a manager instance dict.
+ """Get a node's uuid out of a manager instance dict.
- The compute manager is meant to know the node id, so a missing node is
+ The compute manager is meant to know the node uuid, so missing uuid
a significant issue - it may mean we've been passed someone elses data.
"""
- node_id = instance.get('node')
- if not node_id:
+ node_uuid = instance.get('node')
+ if not node_uuid:
raise exception.NovaException(_(
"Baremetal node id not supplied to driver for %r")
% instance['uuid'])
- return node_id
+ return node_uuid
def _attach_block_devices(self, instance, block_device_info):
block_device_mapping = driver.\
@@ -230,18 +230,19 @@ class BareMetalDriver(driver.ComputeDriver):
def macs_for_instance(self, instance):
context = nova_context.get_admin_context()
- node_id = self._require_node(instance)
- return set(iface['address'] for iface in
- db.bm_interface_get_all_by_bm_node_id(context, node_id))
+ node_uuid = self._require_node(instance)
+ node = db.bm_node_get_by_node_uuid(context, node_uuid)
+ ifaces = db.bm_interface_get_all_by_bm_node_id(context, node['id'])
+ return set(iface['address'] for iface in ifaces)
def spawn(self, context, instance, image_meta, injected_files,
admin_password, network_info=None, block_device_info=None):
- node_id = self._require_node(instance)
+ node_uuid = self._require_node(instance)
# NOTE(deva): this db method will raise an exception if the node is
# already in use. We call it here to ensure no one else
# allocates this node before we begin provisioning it.
- node = db.bm_node_set_uuid_safe(context, node_id,
+ node = db.bm_node_associate_and_update(context, node_uuid,
{'instance_uuid': instance['uuid'],
'task_state': baremetal_states.BUILDING})
@@ -265,7 +266,8 @@ class BareMetalDriver(driver.ComputeDriver):
with excutils.save_and_reraise_exception():
LOG.error(_("Error deploying instance %(instance)s "
"on baremetal node %(node)s.") %
- {'instance': instance['uuid'], 'node': node['id']})
+ {'instance': instance['uuid'],
+ 'node': node['uuid']})
# Do not set instance=None yet. This prevents another
# spawn() while we are cleaning up.
@@ -408,7 +410,7 @@ class BareMetalDriver(driver.ComputeDriver):
'local_gb_used': local_gb_used,
'hypervisor_type': self.get_hypervisor_type(),
'hypervisor_version': self.get_hypervisor_version(),
- 'hypervisor_hostname': str(node['id']),
+ 'hypervisor_hostname': str(node['uuid']),
'cpu_info': 'baremetal cpu',
}
return dic
@@ -418,7 +420,7 @@ class BareMetalDriver(driver.ComputeDriver):
def get_available_resource(self, nodename):
context = nova_context.get_admin_context()
- node = db.bm_node_get(context, nodename)
+ node = db.bm_node_get_by_node_uuid(context, nodename)
dic = self._node_resource(node)
return dic
@@ -438,7 +440,7 @@ class BareMetalDriver(driver.ComputeDriver):
service_host=CONF.host)
for node in nodes:
res = self._node_resource(node)
- nodename = str(node['id'])
+ nodename = str(node['uuid'])
data = {}
data['vcpus'] = res['vcpus']
data['vcpus_used'] = res['vcpus_used']
@@ -489,5 +491,5 @@ class BareMetalDriver(driver.ComputeDriver):
def get_available_nodes(self):
context = nova_context.get_admin_context()
- return [str(n['id']) for n in
+ return [str(n['uuid']) for n in
db.bm_node_get_unassociated(context, service_host=CONF.host)]
diff --git a/nova/virt/baremetal/pxe.py b/nova/virt/baremetal/pxe.py
index 0abede93c..813f95c05 100644
--- a/nova/virt/baremetal/pxe.py
+++ b/nova/virt/baremetal/pxe.py
@@ -413,7 +413,7 @@ class PXE(base.NodeDriver):
'pxe_config_path': None,
'root_mb': 0,
'swap_mb': 0})
- except exception.InstanceNotFound:
+ except exception.NodeNotFound:
pass
try:
@@ -464,7 +464,7 @@ class PXE(base.NodeDriver):
raise utils.LoopingCallDone()
elif status == baremetal_states.DEPLOYFAIL:
locals['error'] = _("PXE deploy failed for instance %s")
- except exception.InstanceNotFound:
+ except exception.NodeNotFound:
locals['error'] = _("Baremetal node deleted while waiting "
"for deployment of instance %s")