summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.zuul.yaml43
-rw-r--r--nova/api/openstack/placement/handlers/root.py12
-rw-r--r--nova/compute/resource_tracker.py21
-rw-r--r--nova/exception.py2
-rw-r--r--nova/tests/functional/api/openstack/placement/gabbits/microversion.yaml2
-rwxr-xr-xnova/tests/live_migration/hooks/ceph.sh1
-rwxr-xr-xnova/tests/live_migration/hooks/run_tests.sh5
-rw-r--r--nova/tests/unit/compute/test_resource_tracker.py52
-rw-r--r--nova/virt/libvirt/host.py2
-rw-r--r--nova/virt/libvirt/volume/mount.py2
-rw-r--r--placement-api-ref/source/get-root.json9
-rw-r--r--placement-api-ref/source/parameters.yaml13
-rw-r--r--placement-api-ref/source/root.inc2
-rw-r--r--test-requirements.txt2
-rwxr-xr-xtools/check-cherry-picks.sh2
15 files changed, 107 insertions, 63 deletions
diff --git a/.zuul.yaml b/.zuul.yaml
index dd7e90ff44..4d34143075 100644
--- a/.zuul.yaml
+++ b/.zuul.yaml
@@ -162,7 +162,6 @@
- ^tests-py3.txt$
- ^tools/.*$
- ^tox.ini$
- - nova-grenade-live-migration
- nova-live-migration
- tempest-slow:
irrelevant-files:
@@ -181,21 +180,6 @@
- ^tox.ini$
- nova-tox-functional
- nova-tox-functional-py35
- - neutron-grenade-multinode:
- irrelevant-files:
- - ^(placement-)?api-.*$
- - ^(test-|)requirements.txt$
- - ^.*\.rst$
- - ^.git.*$
- - ^doc/.*$
- - ^nova/hacking/.*$
- - ^nova/locale/.*$
- - ^nova/tests/.*$
- - ^releasenotes/.*$
- - ^setup.cfg$
- - ^tests-py3.txt$
- - ^tools/.*$
- - ^tox.ini$
- neutron-tempest-linuxbridge:
irrelevant-files:
- ^(?!nova/network/.*)(?!nova/virt/libvirt/vif.py).*$
@@ -243,7 +227,10 @@
- ^tests-py3.txt$
- ^tools/.*$
- ^tox.ini$
- - neutron-grenade:
+ gate:
+ jobs:
+ - nova-live-migration
+ - tempest-slow:
irrelevant-files:
- ^(placement-)?api-.*$
- ^(test-|)requirements.txt$
@@ -258,10 +245,9 @@
- ^tests-py3.txt$
- ^tools/.*$
- ^tox.ini$
- gate:
- jobs:
- - nova-live-migration
- - tempest-slow:
+ - nova-tox-functional
+ - nova-tox-functional-py35
+ - tempest-full:
irrelevant-files:
- ^(placement-)?api-.*$
- ^(test-|)requirements.txt$
@@ -276,9 +262,13 @@
- ^tests-py3.txt$
- ^tools/.*$
- ^tox.ini$
- - nova-tox-functional
- - nova-tox-functional-py35
- - tempest-full:
+ post:
+ jobs:
+ - openstack-tox-cover
+ experimental:
+ jobs:
+ - nova-grenade-live-migration
+ - neutron-grenade-multinode:
irrelevant-files:
- ^(placement-)?api-.*$
- ^(test-|)requirements.txt$
@@ -308,11 +298,6 @@
- ^tests-py3.txt$
- ^tools/.*$
- ^tox.ini$
- post:
- jobs:
- - openstack-tox-cover
- experimental:
- jobs:
- tempest-nova-v2-api:
irrelevant-files:
- ^(placement-)?api-.*$
diff --git a/nova/api/openstack/placement/handlers/root.py b/nova/api/openstack/placement/handlers/root.py
index 9b5b1bb948..5c35039ce9 100644
--- a/nova/api/openstack/placement/handlers/root.py
+++ b/nova/api/openstack/placement/handlers/root.py
@@ -30,6 +30,18 @@ def home(req):
'id': 'v%s' % min_version,
'max_version': max_version,
'min_version': min_version,
+ # for now there is only ever one version, so it must be CURRENT
+ 'status': 'CURRENT',
+ 'links': [{
+ # Point back to this same URL as the root of this version.
+ # NOTE(cdent): We explicitly want this to be a relative-URL
+ # representation of "this same URL", otherwise placement needs
+ # to keep track of proxy addresses and the like, which we have
+ # avoided thus far, in order to construct full URLs. Placement
+ # is much easier to scale if we never track that stuff.
+ 'rel': 'self',
+ 'href': '',
+ }],
}
version_json = jsonutils.dumps({'versions': [version_data]})
req.response.body = encodeutils.to_utf8(version_json)
diff --git a/nova/compute/resource_tracker.py b/nova/compute/resource_tracker.py
index 024d915875..adf26260c3 100644
--- a/nova/compute/resource_tracker.py
+++ b/nova/compute/resource_tracker.py
@@ -583,7 +583,6 @@ class ResourceTracker(object):
cn = self.compute_nodes[nodename]
self._copy_resources(cn, resources)
self._setup_pci_tracker(context, cn, resources)
- self._update(context, cn)
return
# now try to get the compute node record from the
@@ -593,7 +592,6 @@ class ResourceTracker(object):
self.compute_nodes[nodename] = cn
self._copy_resources(cn, resources)
self._setup_pci_tracker(context, cn, resources)
- self._update(context, cn)
return
if self._check_for_nodes_rebalance(context, resources, nodename):
@@ -616,7 +614,6 @@ class ResourceTracker(object):
{'host': self.host, 'node': nodename, 'uuid': cn.uuid})
self._setup_pci_tracker(context, cn, resources)
- self._update(context, cn)
def _setup_pci_tracker(self, context, compute_node, resources):
if not self.pci_tracker:
@@ -895,10 +892,22 @@ class ResourceTracker(object):
def _update(self, context, compute_node):
"""Update partial stats locally and populate them to Scheduler."""
- if not self._resource_change(compute_node):
- return
+ if self._resource_change(compute_node):
+ # If the compute_node's resource changed, update to DB.
+ # NOTE(jianghuaw): Once we completely move to use get_inventory()
+ # for all resource provider's inv data. We can remove this check.
+ # At the moment we still need this check and save compute_node.
+ compute_node.save()
+
+ # NOTE(jianghuaw): Some resources(e.g. ironic custom resources) are
+ # not saved in the object of compute_node; instead the inventory data
+ # for these resource is reported by driver's get_inventory(). So even
+ # there is no resource change for compute_node as above, we need
+ # proceed to get inventory and use scheduler_client interfaces to
+ # update inventory to placement. It's scheduler_client's responsibility
+ # to ensure the update request to placement only happens when inventory
+ # is changed.
nodename = compute_node.hypervisor_hostname
- compute_node.save()
# Persist the stats to the Scheduler
try:
inv_data = self.driver.get_inventory(nodename)
diff --git a/nova/exception.py b/nova/exception.py
index 85fe8f8b0f..4eb436b827 100644
--- a/nova/exception.py
+++ b/nova/exception.py
@@ -462,7 +462,7 @@ class ComputeResourcesUnavailable(ServiceUnavailable):
class HypervisorUnavailable(NovaException):
- msg_fmt = _("Connection to the hypervisor is broken on host: %(host)s")
+ msg_fmt = _("Connection to the hypervisor is broken on host")
class ComputeServiceUnavailable(ServiceUnavailable):
diff --git a/nova/tests/functional/api/openstack/placement/gabbits/microversion.yaml b/nova/tests/functional/api/openstack/placement/gabbits/microversion.yaml
index 778ab4fce0..abcec8f61a 100644
--- a/nova/tests/functional/api/openstack/placement/gabbits/microversion.yaml
+++ b/nova/tests/functional/api/openstack/placement/gabbits/microversion.yaml
@@ -22,6 +22,8 @@ tests:
$.versions[0].max_version: /^\d+\.\d+$/
$.versions[0].min_version: /^\d+\.\d+$/
$.versions[0].id: v1.0
+ $.versions[0].status: CURRENT
+ $.versions[0].links[?rel = 'self'].href: ''
- name: unavailable microversion raises 406
GET: /
diff --git a/nova/tests/live_migration/hooks/ceph.sh b/nova/tests/live_migration/hooks/ceph.sh
index 4fbe3f2ad3..fd16fc2a7e 100755
--- a/nova/tests/live_migration/hooks/ceph.sh
+++ b/nova/tests/live_migration/hooks/ceph.sh
@@ -8,6 +8,7 @@ function prepare_ceph {
configure_ceph
#install ceph-common package on compute nodes
$ANSIBLE subnodes --become -f 5 -i "$WORKSPACE/inventory" -m raw -a "executable=/bin/bash
+ export CEPH_RELEASE=nautilus
source $BASE/new/devstack/functions
source $BASE/new/devstack/functions-common
git clone https://git.openstack.org/openstack/devstack-plugin-ceph /tmp/devstack-plugin-ceph
diff --git a/nova/tests/live_migration/hooks/run_tests.sh b/nova/tests/live_migration/hooks/run_tests.sh
index 21768642ed..7f27c334ac 100755
--- a/nova/tests/live_migration/hooks/run_tests.sh
+++ b/nova/tests/live_migration/hooks/run_tests.sh
@@ -54,6 +54,11 @@ if [[ "$GRENADE_OLD_BRANCH" == "stable/ocata" ]]; then
echo '3. Grenade testing with Ceph is disabled until bug 1691769 is fixed or Queens.'
else
echo '3. test with Ceph for root + ephemeral disks'
+ # NOTE(lyarwood): Pin the CEPH_RELEASE to nautilus here as was the case
+ # prior to https://review.opendev.org/c/openstack/devstack-plugin-ceph/+/777232
+ # landing in the branchless plugin, we also have to pin in ceph.sh when
+ # configuring ceph on a remote node via ansible.
+ export CEPH_RELEASE=nautilus
GetOSVersion
prepare_ceph
GLANCE_API_CONF=${GLANCE_API_CONF:-/etc/glance/glance-api.conf}
diff --git a/nova/tests/unit/compute/test_resource_tracker.py b/nova/tests/unit/compute/test_resource_tracker.py
index 73a189dc21..9e9534b9cd 100644
--- a/nova/tests/unit/compute/test_resource_tracker.py
+++ b/nova/tests/unit/compute/test_resource_tracker.py
@@ -568,6 +568,7 @@ class TestUpdateAvailableResources(BaseTestCase):
actual_resources = update_mock.call_args[0][1]
self.assertTrue(obj_base.obj_equal_prims(expected_resources,
actual_resources))
+ update_mock.assert_called_once()
@mock.patch('nova.objects.InstancePCIRequests.get_by_instance',
return_value=objects.InstancePCIRequests(requests=[]))
@@ -608,6 +609,7 @@ class TestUpdateAvailableResources(BaseTestCase):
actual_resources = update_mock.call_args[0][1]
self.assertTrue(obj_base.obj_equal_prims(expected_resources,
actual_resources))
+ update_mock.assert_called_once()
@mock.patch('nova.objects.InstancePCIRequests.get_by_instance',
return_value=objects.InstancePCIRequests(requests=[]))
@@ -655,6 +657,7 @@ class TestUpdateAvailableResources(BaseTestCase):
actual_resources = update_mock.call_args[0][1]
self.assertTrue(obj_base.obj_equal_prims(expected_resources,
actual_resources))
+ update_mock.assert_called_once()
@mock.patch('nova.objects.InstancePCIRequests.get_by_instance',
return_value=objects.InstancePCIRequests(requests=[]))
@@ -718,6 +721,7 @@ class TestUpdateAvailableResources(BaseTestCase):
actual_resources = update_mock.call_args[0][1]
self.assertTrue(obj_base.obj_equal_prims(expected_resources,
actual_resources))
+ update_mock.assert_called_once()
@mock.patch('nova.objects.InstancePCIRequests.get_by_instance',
return_value=objects.InstancePCIRequests(requests=[]))
@@ -780,6 +784,7 @@ class TestUpdateAvailableResources(BaseTestCase):
actual_resources = update_mock.call_args[0][1]
self.assertTrue(obj_base.obj_equal_prims(expected_resources,
actual_resources))
+ update_mock.assert_called_once()
@mock.patch('nova.objects.InstancePCIRequests.get_by_instance',
return_value=objects.InstancePCIRequests(requests=[]))
@@ -839,6 +844,7 @@ class TestUpdateAvailableResources(BaseTestCase):
actual_resources = update_mock.call_args[0][1]
self.assertTrue(obj_base.obj_equal_prims(expected_resources,
actual_resources))
+ update_mock.assert_called_once()
@mock.patch('nova.objects.InstancePCIRequests.get_by_instance',
return_value=objects.InstancePCIRequests(requests=[]))
@@ -894,6 +900,7 @@ class TestUpdateAvailableResources(BaseTestCase):
actual_resources = update_mock.call_args[0][1]
self.assertTrue(obj_base.obj_equal_prims(expected_resources,
actual_resources))
+ update_mock.assert_called_once()
@mock.patch('nova.objects.InstancePCIRequests.get_by_instance',
return_value=objects.InstancePCIRequests(requests=[]))
@@ -962,6 +969,7 @@ class TestUpdateAvailableResources(BaseTestCase):
actual_resources = update_mock.call_args[0][1]
self.assertTrue(obj_base.obj_equal_prims(expected_resources,
actual_resources))
+ update_mock.assert_called_once()
class TestInitComputeNode(BaseTestCase):
@@ -987,7 +995,7 @@ class TestInitComputeNode(BaseTestCase):
self.assertFalse(get_mock.called)
self.assertFalse(create_mock.called)
self.assertTrue(pci_mock.called)
- self.assertTrue(update_mock.called)
+ self.assertFalse(update_mock.called)
@mock.patch('nova.objects.PciDeviceList.get_by_compute_node',
return_value=objects.PciDeviceList())
@@ -1011,7 +1019,7 @@ class TestInitComputeNode(BaseTestCase):
get_mock.assert_called_once_with(mock.sentinel.ctx, _HOSTNAME,
_NODENAME)
self.assertFalse(create_mock.called)
- self.assertTrue(update_mock.called)
+ self.assertFalse(update_mock.called)
@mock.patch('nova.objects.ComputeNodeList.get_by_hypervisor')
@mock.patch('nova.objects.PciDeviceList.get_by_compute_node',
@@ -1165,7 +1173,7 @@ class TestInitComputeNode(BaseTestCase):
create_mock.assert_called_once_with()
self.assertTrue(obj_base.obj_equal_prims(expected_compute, cn))
setup_pci.assert_called_once_with(mock.sentinel.ctx, cn, resources)
- self.assertTrue(update_mock.called)
+ self.assertFalse(update_mock.called)
@mock.patch('nova.compute.resource_tracker.ResourceTracker.'
'_setup_pci_tracker')
@@ -1195,11 +1203,8 @@ class TestInitComputeNode(BaseTestCase):
_cn.uuid = uuids.cn_uuid
return original_copy_resources(_cn, _resources)
- with test.nested(
- mock.patch.object(self.rt, '_copy_resources',
- fake_copy_resources),
- mock.patch.object(self.rt, '_update')
- ) as (mock_copy_resources, mock_update):
+ with mock.patch.object(self.rt, '_copy_resources',
+ fake_copy_resources):
self.rt._init_compute_node(ctxt, resources)
self.assertIn(_NODENAME, self.rt.compute_nodes)
mock_get.assert_has_calls([mock.call(
@@ -1207,8 +1212,6 @@ class TestInitComputeNode(BaseTestCase):
self.assertEqual(2, mock_create.call_count)
mock_setup_pci.assert_called_once_with(
ctxt, test.MatchType(objects.ComputeNode), resources)
- mock_update.assert_called_once_with(
- ctxt, self.rt.compute_nodes[_NODENAME])
@mock.patch('nova.objects.ComputeNodeList.get_by_hypervisor')
@mock.patch('nova.objects.ComputeNode.create')
@@ -1236,25 +1239,26 @@ class TestUpdateComputeNode(BaseTestCase):
self._setup_rt()
# This is the same set of resources as the fixture, deliberately. We
- # are checking below to see that update_compute_node() is not
- # needlessly called when the resources don't actually change.
+ # are checking below to see that compute_node.save is not needlessly
+ # called when the resources don't actually change.
orig_compute = _COMPUTE_NODE_FIXTURES[0].obj_clone()
self.rt.compute_nodes[_NODENAME] = orig_compute
self.rt.old_resources[_NODENAME] = orig_compute
new_compute = orig_compute.obj_clone()
- # Here, we check that if we call _update() with the same resources that
- # are already stored in the resource tracker, that the scheduler client
- # won't be called again to update those (unchanged) resources for the
- # compute node
- ucn_mock = self.sched_client_mock.update_compute_node
self.rt._update(mock.sentinel.ctx, new_compute)
- self.assertFalse(ucn_mock.called)
self.assertFalse(save_mock.called)
+ # Even the compute node is not updated, get_inventory still got called.
+ # And update_compute_node() is also called when get_inventory() is not
+ # implemented.
+ self.driver_mock.get_inventory.assert_called_once_with(_NODENAME)
+ ucn_mock = self.sched_client_mock.update_compute_node
+ ucn_mock.assert_called_once_with(new_compute)
@mock.patch('nova.objects.ComputeNode.save')
def test_existing_compute_node_updated_diff_updated_at(self, save_mock):
+ # if only updated_at is changed, it won't call compute_node.save()
self._setup_rt()
ts1 = timeutils.utcnow()
ts2 = ts1 + datetime.timedelta(seconds=10)
@@ -1269,13 +1273,14 @@ class TestUpdateComputeNode(BaseTestCase):
new_compute = orig_compute.obj_clone()
new_compute.updated_at = ts2
- ucn_mock = self.sched_client_mock.update_compute_node
self.rt._update(mock.sentinel.ctx, new_compute)
self.assertFalse(save_mock.called)
- self.assertFalse(ucn_mock.called)
+ @mock.patch('nova.compute.resource_tracker.'
+ '_normalize_inventory_from_cn_obj')
@mock.patch('nova.objects.ComputeNode.save')
- def test_existing_compute_node_updated_new_resources(self, save_mock):
+ def test_existing_compute_node_updated_new_resources(self, save_mock,
+ norm_mock):
self._setup_rt()
orig_compute = _COMPUTE_NODE_FIXTURES[0].obj_clone()
@@ -1291,9 +1296,12 @@ class TestUpdateComputeNode(BaseTestCase):
new_compute.vcpus_used = 2
new_compute.local_gb_used = 4
- ucn_mock = self.sched_client_mock.update_compute_node
self.rt._update(mock.sentinel.ctx, new_compute)
save_mock.assert_called_once_with()
+ # The get_inventory() is not implemented, it shouldn't call
+ # _normalize_inventory_from_cn_obj but call update_compute_node().
+ self.assertFalse(norm_mock.called)
+ ucn_mock = self.sched_client_mock.update_compute_node
ucn_mock.assert_called_once_with(new_compute)
@mock.patch('nova.compute.resource_tracker.'
diff --git a/nova/virt/libvirt/host.py b/nova/virt/libvirt/host.py
index 10a7dabfa4..3a885d33cd 100644
--- a/nova/virt/libvirt/host.py
+++ b/nova/virt/libvirt/host.py
@@ -457,7 +457,7 @@ class Host(object):
rpc.get_notifier('compute').error(nova_context.get_admin_context(),
'compute.libvirt.error',
payload)
- raise exception.HypervisorUnavailable(host=CONF.host)
+ raise exception.HypervisorUnavailable()
return conn
diff --git a/nova/virt/libvirt/volume/mount.py b/nova/virt/libvirt/volume/mount.py
index 476e914932..86ace4d5c6 100644
--- a/nova/virt/libvirt/volume/mount.py
+++ b/nova/virt/libvirt/volume/mount.py
@@ -84,7 +84,7 @@ class _HostMountStateManager(object):
with self.cond:
state = self.state
if state is None:
- raise exception.HypervisorUnavailable(host=CONF.host)
+ raise exception.HypervisorUnavailable()
self.use_count += 1
try:
diff --git a/placement-api-ref/source/get-root.json b/placement-api-ref/source/get-root.json
index bdb92c3dec..2e4c862445 100644
--- a/placement-api-ref/source/get-root.json
+++ b/placement-api-ref/source/get-root.json
@@ -3,7 +3,14 @@
{
"min_version" : "1.0",
"id" : "v1.0",
- "max_version" : "1.2"
+ "max_version" : "1.10",
+ "status": "CURRENT",
+ "links": [
+ {
+ "href": "",
+ "rel": "self"
+ }
+ ]
}
]
}
diff --git a/placement-api-ref/source/parameters.yaml b/placement-api-ref/source/parameters.yaml
index 08fdf96ca3..1b7581cf4c 100644
--- a/placement-api-ref/source/parameters.yaml
+++ b/placement-api-ref/source/parameters.yaml
@@ -261,6 +261,12 @@ version_id:
required: true
description: >
A common name for the version being described. Informative only.
+version_links:
+ type: array
+ in: body
+ required: true
+ description: >
+ A list of links related to and describing this version.
version_max:
type: string
in: body
@@ -273,6 +279,13 @@ version_min:
required: true
description: >
The minimum microversion that is supported.
+version_status:
+ type: string
+ in: body
+ required: true
+ description: >
+ The status of the version being described. With placement this is
+ "CURRENT".
versions:
type: array
in: body
diff --git a/placement-api-ref/source/root.inc b/placement-api-ref/source/root.inc
index edf9e63479..ab121a6aa5 100644
--- a/placement-api-ref/source/root.inc
+++ b/placement-api-ref/source/root.inc
@@ -24,6 +24,8 @@ Response
- id: version_id
- min_version: version_min
- max_version: version_max
+ - status: version_status
+ - links: version_links
Response Example
----------------
diff --git a/test-requirements.txt b/test-requirements.txt
index b2444f6da0..27822d3fef 100644
--- a/test-requirements.txt
+++ b/test-requirements.txt
@@ -22,7 +22,7 @@ osprofiler>=1.4.0 # Apache-2.0
testresources>=0.2.4 # Apache-2.0/BSD
testscenarios>=0.4 # Apache-2.0/BSD
testtools>=1.4.0 # MIT
-bandit>=1.1.0 # Apache-2.0
+bandit>=1.1.0,<=1.6.2 # Apache-2.0
openstackdocstheme>=1.16.0 # Apache-2.0
gabbi>=1.35.0 # Apache-2.0
diff --git a/tools/check-cherry-picks.sh b/tools/check-cherry-picks.sh
index 32627e59b6..5a449c520b 100755
--- a/tools/check-cherry-picks.sh
+++ b/tools/check-cherry-picks.sh
@@ -32,7 +32,7 @@ if [ $checked -eq 0 ]; then
echo "Checked $checked cherry-pick hashes: OK"
exit 0
else
- if ! git show --format='%B' --quiet | grep -qi 'stable.*only'; then
+ if ! git show --format='%B' --quiet $commit_hash | grep -qi 'stable.*only'; then
echo 'Stable branch requires either cherry-pick -x headers or [stable-only] tag!'
exit 1
fi