oslo.policy 3.6.1 breaks nova
Bug #1914592 reported by
Stephen Finucane
This bug affects 1 person
Affects | Status | Importance | Assigned to | Milestone | |
---|---|---|---|---|---|
OpenStack Compute (nova) |
Fix Released
|
High
|
Stephen Finucane | ||
oslo.policy |
Fix Released
|
Critical
|
Stephen Finucane |
Bug Description
As seen on the requirements change [1], a recently introduced version of oslo.policy appears to be breaking nova [2]. Initial investigations suggest both oslo.policy and nova are partially to blame.
[1] https:/
[2] https:/
Changed in nova: | |
importance: | Undecided → High |
status: | New → Confirmed |
assignee: | nobody → Stephen Finucane (stephenfinucane) |
Changed in oslo.policy: | |
status: | New → Confirmed |
importance: | Undecided → Critical |
assignee: | nobody → Stephen Finucane (stephenfinucane) |
Changed in oslo.policy: | |
status: | Confirmed → Fix Released |
Changed in nova: | |
status: | Confirmed → Fix Released |
To post a comment you must log in.
Consider an arbitrary failing test from the job linked above, which can be run like so:
$ tox -e functional-py38 -- \ functional. regressions. test_bug_ 1522536. TestServerGet. test_id_ overlap
-n nova.tests.
Having added a large number of print debugs (patch attached - can be applied to oslo.config tag 3.6.1), we see the following from nova functional tests (at nova commit 726e2fd03b5dec5 d6aa22a12a68a2f 8d7c8952b3) :
File "/home/ stephenfin/ Development/ openstack/ nova/nova/ tests/functiona l/regressions/ test_bug_ 1522536. py", line 26, in setUp TestServerGet, self).setUp() stephenfin/ Development/ openstack/ nova/nova/ test.py" , line 264, in setUp (policy_ fixture. PolicyFixture( )) stephenfin/ Development/ openstack/ nova/.tox/ functional- py38/lib/ python3. 8/site- packages/ testtools/ testcase. py", line 735, in useFixture stephenfin/ Development/ openstack/ nova/nova/ tests/unit/ policy_ fixture. py", line 56, in setUp policy. init(suppress_ deprecation_ warnings= True) stephenfin/ Development/ openstack/ nova/nova/ policy. py", line 93, in init load_rules( )
super(
File "/home/
self.policy = self.useFixture
File "/home/
fixture.setUp()
File "/home/
nova.
File "/home/
_ENFORCER.
This is followed shortly thereafter by:
File "/home/ stephenfin/ Development/ openstack/ nova/nova/ tests/functiona l/regressions/ test_bug_ 1522536. py", line 27, in setUp useFixture( policy_ fixture. RealPolicyFixtu re()) stephenfin/ Development/ openstack/ nova/.tox/ functional- py38/lib/ python3. 8/site- packages/ testtools/ testcase. py", line 735, in useFixture stephenfin/ Development/ openstack/ nova/nova/ tests/unit/ policy_ fixture. py", line 52, in setUp policy. reset() stephenfin/ Development/ openstack/ nova/nova/ policy. py", line 54, in reset
self.
File "/home/
fixture.setUp()
File "/home/
nova.
File "/home/
_ENFORCER.clear()
From this we can see there are two fixtures being applied: the legacy 'PolicyFixture', which should really be deprecated and removed by now, and the modern 'RealPolicyFixt ure'. The sequence of these calls is important.
The call to 'PolicyFixture' attempts to 'reset()' nova's global policy engine instance [1] but isn't able to do so since it hasn't been initialized yet. It then 'init()'s this global policy engine [2]. Since the engine is now initialized, the 'RealPolicyFixt ure's call to 'reset()' will be permitted. The enforcer is deleted and then later initialized again in the subsequent 'init()' call. However, there is a difference in how we initialized the enforcer the second time around. In the first call from the legacy 'PolicyFixture', we initialized it with a sample file [3] that we created from some fake policy. However, in the second call from the 'RealPolicyFixture' we don't generate a fake policy file but rather point to 'etc/nova/ policy. yaml' in tree, which doesn't actually exist [4][5] and therefore has nothing to load from.
This change in how we initialize the enforcer has a knock on effect. For reasons I haven't yet entirely groked - though I suspect it's to ensure the user gets exactly what they asked for without modifications - we only apply the deprecated check string via an OR *if* the rule wasn't loaded...