Add major release logic

Major releases have additional requirements around SWACT and which
controller is used for what.  This adds that logic.

A major release is decided by the the major and minor sw_versions.
If either the major or minor version have changed we will consider it a
major release.

TEST PLAN
PASS: AIO-DX major release upgrade
* SWACTs and sorting occur
PASS: AIO-DX patch release upgrade with value manually changed to false
* SWACTs and sorting do not occur

Story: 2011045
Task: 50170
Change-Id: Ie357ab36622bd5fcca75f66899515534886fada1
Signed-off-by: Joshua Kraitberg <joshua.kraitberg@windriver.com>
This commit is contained in:
Joshua Kraitberg 2024-05-23 10:51:13 -04:00
parent 77a2dd027f
commit 2e46016364
9 changed files with 393 additions and 111 deletions

View File

@ -30,8 +30,10 @@
description: Run py39 for nfv
nodeset: debian-bullseye
required-projects:
- starlingx/config
- starlingx/fault
- starlingx/root
- starlingx/update
vars:
tox_extra_args: -c nfv/tox.ini
tox_constraints_file: '{{ ansible_user_dir }}/src/opendev.org/starlingx/root/build-tools/requirements/debian/upper-constraints.txt'
@ -61,8 +63,10 @@
description: Run pylint for nfv
nodeset: debian-bullseye
required-projects:
- starlingx/config
- starlingx/fault
- starlingx/root
- starlingx/update
vars:
tox_envlist: pylint
tox_extra_args: -c nfv/tox.ini

View File

@ -20,6 +20,13 @@ from nfv_vim.strategy._strategy import SwUpgradeStrategy
from nfv_unit_tests.tests import sw_update_testcase
INITIAL_RELEASE = "3.2.1"
PATCH_RELEASE_UPGRADE = "3.2.2"
# Minor and Major are both major release upgrades
MINOR_RELEASE_UPGRADE = "4.0.1"
MAJOR_RELEASE_UPGRADE = "4.0.1"
# utility method for the formatting of unlock-hosts stage as dict
# workers default to 5 retries with 120 second delay between attempts
# std controllers and storage have 0 retries
@ -41,6 +48,7 @@ def _unlock_hosts_stage_as_dict(host_names, retry_count=5, retry_delay=120):
sw_update_testcase.fake_timer)
@mock.patch('nfv_vim.nfvi.nfvi_compute_plugin_disabled',
sw_update_testcase.fake_nfvi_compute_plugin_disabled)
@mock.patch.object(nfvi.objects.v1.upgrade, 'SW_VERSION', INITIAL_RELEASE)
class TestSwUpgradeStrategy(sw_update_testcase.SwUpdateStrategyTestCase):
def create_sw_deploy_strategy(self,
@ -50,7 +58,7 @@ class TestSwUpgradeStrategy(sw_update_testcase.SwUpdateStrategyTestCase):
max_parallel_worker_hosts=10,
alarm_restrictions=SW_UPDATE_ALARM_RESTRICTION.STRICT,
default_instance_action=SW_UPDATE_INSTANCE_ACTION.STOP_START,
release="123.1",
release=MAJOR_RELEASE_UPGRADE,
rollback=False,
nfvi_upgrade=None,
single_controller=False
@ -179,6 +187,22 @@ class TestSwUpgradeStrategy(sw_update_testcase.SwUpdateStrategyTestCase):
return controller_hosts, storage_hosts, worker_hosts, strategy
def test_is_major_release(self):
is_major_release = nfvi.objects.v1.is_major_release
assert is_major_release(INITIAL_RELEASE, MAJOR_RELEASE_UPGRADE)
assert is_major_release(INITIAL_RELEASE, MINOR_RELEASE_UPGRADE)
assert not is_major_release(INITIAL_RELEASE, PATCH_RELEASE_UPGRADE)
assert is_major_release("22.12", "24.09.1")
assert is_major_release("22.12", "24.09.1")
assert is_major_release("22.12", "24.09.1")
assert is_major_release("22.12", "24.09")
assert is_major_release("22.12.1", "24.09")
assert is_major_release("24.03", "24.09.1")
assert is_major_release("24.03", "24.09.1")
assert not is_major_release("22.12", "22.12")
assert not is_major_release("22.12", "22.12.1")
assert not is_major_release("22.12.2", "22.12.1")
@mock.patch('nfv_common.strategy._strategy.Strategy._build')
def test_sw_deploy_strategy_build_steps(self, fake_build):
"""
@ -233,6 +257,7 @@ class TestSwUpgradeStrategy(sw_update_testcase.SwUpdateStrategyTestCase):
{
'state': 'available',
'reboot_required': False,
'sw_version': PATCH_RELEASE_UPGRADE,
},
None,
None,
@ -280,6 +305,7 @@ class TestSwUpgradeStrategy(sw_update_testcase.SwUpdateStrategyTestCase):
{
'state': 'available',
'reboot_required': False,
'sw_version': PATCH_RELEASE_UPGRADE,
},
None,
None,
@ -310,8 +336,6 @@ class TestSwUpgradeStrategy(sw_update_testcase.SwUpdateStrategyTestCase):
sw_update_testcase.validate_phase(apply_phase, expected_results)
# pylint: disable=no-member
@mock.patch('nfv_vim.strategy._strategy.get_local_host_name',
sw_update_testcase.fake_host_name_flipper('controller-1', 'controller-0', n=2))
def test_sw_deploy_strategy_start_on_controller_1_aiodx(self):
"""
Test the sw_upgrade strategy start stages on controller-1:
@ -328,6 +352,7 @@ class TestSwUpgradeStrategy(sw_update_testcase.SwUpdateStrategyTestCase):
{
'state': 'available',
'reboot_required': False,
'sw_version': PATCH_RELEASE_UPGRADE,
},
None,
None,
@ -342,7 +367,55 @@ class TestSwUpgradeStrategy(sw_update_testcase.SwUpdateStrategyTestCase):
'total_stages': 1,
'stages': [
{'name': 'sw-upgrade-start',
'total_steps': 5,
'total_steps': 3,
'steps': [
{'name': 'query-alarms'},
{'name': 'start-upgrade',
'release': release},
{'name': 'system-stabilize',
'timeout': 60},
]
}
]
}
sw_update_testcase.validate_strategy_persists(strategy)
sw_update_testcase.validate_phase(apply_phase, expected_results)
# pylint: disable=no-member
def test_sw_deploy_strategy_start_on_controller_1_aiodx_major(self):
"""
Test the sw_upgrade strategy start stages on controller-1:
- dx
- major release
Verify:
- pass
"""
release = "888.8"
_, strategy = self._gen_aiodx_hosts_and_strategy(
release=release,
nfvi_upgrade=nfvi.objects.v1.Upgrade(
release,
{
'state': 'available',
'reboot_required': True,
'sw_version': MAJOR_RELEASE_UPGRADE,
},
None,
None,
)
)
strategy._add_upgrade_start_stage()
apply_phase = strategy.apply_phase.as_dict()
expected_results = {
'total_stages': 1,
'stages': [
{'name': 'sw-upgrade-start',
'total_steps': 4,
'steps': [
{'name': 'query-alarms'},
{'name': 'swact-hosts',
@ -351,8 +424,6 @@ class TestSwUpgradeStrategy(sw_update_testcase.SwUpdateStrategyTestCase):
'release': release},
{'name': 'system-stabilize',
'timeout': 60},
{'name': 'swact-hosts',
'entity_names': ['controller-0']},
]
}
]
@ -381,6 +452,7 @@ class TestSwUpgradeStrategy(sw_update_testcase.SwUpdateStrategyTestCase):
{
'state': 'available',
'reboot_required': False,
'sw_version': PATCH_RELEASE_UPGRADE,
},
None,
None,
@ -430,6 +502,7 @@ class TestSwUpgradeStrategy(sw_update_testcase.SwUpdateStrategyTestCase):
{
'state': 'available',
'reboot_required': False,
'sw_version': PATCH_RELEASE_UPGRADE,
},
None,
None,
@ -462,8 +535,6 @@ class TestSwUpgradeStrategy(sw_update_testcase.SwUpdateStrategyTestCase):
sw_update_testcase.validate_phase(apply_phase, expected_results)
# pylint: disable=no-member
@mock.patch('nfv_vim.strategy._strategy.get_local_host_name',
sw_update_testcase.fake_host_name_flipper('controller-1', 'controller-0', n=2))
def test_sw_deploy_strategy_complete_on_controller_1_aiodx(self):
"""
Test the sw_upgrade strategy complete stages on controller-1:
@ -480,6 +551,57 @@ class TestSwUpgradeStrategy(sw_update_testcase.SwUpdateStrategyTestCase):
{
'state': 'available',
'reboot_required': False,
'sw_version': PATCH_RELEASE_UPGRADE,
},
None,
None,
)
)
strategy._add_upgrade_complete_stage()
apply_phase = strategy.apply_phase.as_dict()
expected_results = {
'total_stages': 1,
'stages': [
{'name': 'sw-upgrade-complete',
'total_steps': 4,
'steps': [
{'name': 'query-alarms'},
{'name': 'activate-upgrade',
'release': release},
{'name': 'complete-upgrade',
'release': release},
{'name': 'system-stabilize',
'timeout': 60},
]
}
]
}
sw_update_testcase.validate_strategy_persists(strategy)
sw_update_testcase.validate_phase(apply_phase, expected_results)
# pylint: disable=no-member
def test_sw_deploy_strategy_complete_on_controller_1_aiodx_major(self):
"""
Test the sw_upgrade strategy complete stages on controller-1:
- dx
- major releasee
Verify:
- pass
"""
release = "888.8"
_, strategy = self._gen_aiodx_hosts_and_strategy(
release=release,
nfvi_upgrade=nfvi.objects.v1.Upgrade(
release,
{
'state': 'available',
'reboot_required': True,
'sw_version': MAJOR_RELEASE_UPGRADE,
},
None,
None,
@ -943,9 +1065,9 @@ class TestSwUpgradeStrategy(sw_update_testcase.SwUpdateStrategyTestCase):
expected_reason = "Software release is already deployed or committed."
bpr = strategy.build_phase
assert strategy._state == common_strategy.STRATEGY_STATE.BUILD_FAILED
assert bpr.result == common_strategy.STRATEGY_PHASE_RESULT.FAILED
assert bpr.result_reason == expected_reason, strategy.build_phase.result_reason
assert strategy._state == common_strategy.STRATEGY_STATE.BUILD_FAILED, strategy._state
assert bpr.result == common_strategy.STRATEGY_PHASE_RESULT.FAILED, bpr.result
assert bpr.result_reason == expected_reason, bpr.result_reason
def test_sw_deploy_strategy_aiosx_already_committed(self):
"""
@ -1158,6 +1280,7 @@ class TestSwUpgradeStrategy(sw_update_testcase.SwUpdateStrategyTestCase):
{
'state': 'available',
'reboot_required': False,
'sw_version': PATCH_RELEASE_UPGRADE,
},
None,
None,
@ -1187,7 +1310,7 @@ class TestSwUpgradeStrategy(sw_update_testcase.SwUpdateStrategyTestCase):
'total_steps': 3,
'steps': [
{'name': 'query-alarms'},
{'name': 'upgrade-hosts', 'entity_names': ['controller-1']},
{'name': 'upgrade-hosts', 'entity_names': ['controller-0']},
{'name': 'system-stabilize', 'timeout': 30},
]
},
@ -1196,7 +1319,7 @@ class TestSwUpgradeStrategy(sw_update_testcase.SwUpdateStrategyTestCase):
'total_steps': 3,
'steps': [
{'name': 'query-alarms'},
{'name': 'upgrade-hosts', 'entity_names': ['controller-0']},
{'name': 'upgrade-hosts', 'entity_names': ['controller-1']},
{'name': 'system-stabilize', 'timeout': 30},
]
},
@ -1233,6 +1356,7 @@ class TestSwUpgradeStrategy(sw_update_testcase.SwUpdateStrategyTestCase):
{
'state': 'available',
'reboot_required': True,
'sw_version': PATCH_RELEASE_UPGRADE,
},
None,
None,
@ -1262,12 +1386,12 @@ class TestSwUpgradeStrategy(sw_update_testcase.SwUpdateStrategyTestCase):
'total_steps': 7,
'steps': [
{'name': 'query-alarms'},
{'name': 'swact-hosts', 'entity_names': ['controller-1']},
{'name': 'lock-hosts', 'entity_names': ['controller-1']},
{'name': 'upgrade-hosts', 'entity_names': ['controller-1']},
{'name': 'swact-hosts', 'entity_names': ['controller-0']},
{'name': 'lock-hosts', 'entity_names': ['controller-0']},
{'name': 'upgrade-hosts', 'entity_names': ['controller-0']},
{'name': 'system-stabilize', 'timeout': 15},
{'name': 'unlock-hosts',
'entity_names': ['controller-1'], 'retry_count': 0, 'retry_delay': 120},
'entity_names': ['controller-0'], 'retry_count': 0, 'retry_delay': 120},
{'name': 'wait-alarms-clear', 'timeout': 2400},
]
},
@ -1276,12 +1400,12 @@ class TestSwUpgradeStrategy(sw_update_testcase.SwUpdateStrategyTestCase):
'total_steps': 7,
'steps': [
{'name': 'query-alarms'},
{'name': 'swact-hosts', 'entity_names': ['controller-0']},
{'name': 'lock-hosts', 'entity_names': ['controller-0']},
{'name': 'upgrade-hosts', 'entity_names': ['controller-0']},
{'name': 'swact-hosts', 'entity_names': ['controller-1']},
{'name': 'lock-hosts', 'entity_names': ['controller-1']},
{'name': 'upgrade-hosts', 'entity_names': ['controller-1']},
{'name': 'system-stabilize', 'timeout': 15},
{'name': 'unlock-hosts',
'entity_names': ['controller-0'], 'retry_count': 0, 'retry_delay': 120},
'entity_names': ['controller-1'], 'retry_count': 0, 'retry_delay': 120},
{'name': 'wait-alarms-clear', 'timeout': 2400},
]
},
@ -1320,6 +1444,7 @@ class TestSwUpgradeStrategy(sw_update_testcase.SwUpdateStrategyTestCase):
{
'state': 'available',
'reboot_required': False,
'sw_version': PATCH_RELEASE_UPGRADE,
},
None,
None,
@ -1349,7 +1474,7 @@ class TestSwUpgradeStrategy(sw_update_testcase.SwUpdateStrategyTestCase):
'total_steps': 3,
'steps': [
{'name': 'query-alarms'},
{'name': 'upgrade-hosts', 'entity_names': ['controller-1']},
{'name': 'upgrade-hosts', 'entity_names': ['controller-0']},
{'name': 'system-stabilize', 'timeout': 30},
]
},
@ -1358,7 +1483,7 @@ class TestSwUpgradeStrategy(sw_update_testcase.SwUpdateStrategyTestCase):
'total_steps': 3,
'steps': [
{'name': 'query-alarms'},
{'name': 'upgrade-hosts', 'entity_names': ['controller-0']},
{'name': 'upgrade-hosts', 'entity_names': ['controller-1']},
{'name': 'system-stabilize', 'timeout': 30},
]
},
@ -1417,6 +1542,7 @@ class TestSwUpgradeStrategy(sw_update_testcase.SwUpdateStrategyTestCase):
{
'state': 'available',
'reboot_required': True,
'sw_version': PATCH_RELEASE_UPGRADE,
},
None,
None,
@ -1441,6 +1567,128 @@ class TestSwUpgradeStrategy(sw_update_testcase.SwUpdateStrategyTestCase):
{'name': 'system-stabilize', 'timeout': 60},
],
},
{
'name': 'sw-upgrade-controllers',
'total_steps': 7,
'steps': [
{'name': 'query-alarms'},
{'name': 'swact-hosts', 'entity_names': ['controller-0']},
{'name': 'lock-hosts', 'entity_names': ['controller-0']},
{'name': 'upgrade-hosts', 'entity_names': ['controller-0']},
{'name': 'system-stabilize', 'timeout': 15},
{'name': 'unlock-hosts',
'entity_names': ['controller-0'], 'retry_count': 0, 'retry_delay': 120},
{'name': 'wait-alarms-clear', 'timeout': 2400},
]
},
{
'name': 'sw-upgrade-controllers',
'total_steps': 7,
'steps': [
{'name': 'query-alarms'},
{'name': 'swact-hosts', 'entity_names': ['controller-1']},
{'name': 'lock-hosts', 'entity_names': ['controller-1']},
{'name': 'upgrade-hosts', 'entity_names': ['controller-1']},
{'name': 'system-stabilize', 'timeout': 15},
{'name': 'unlock-hosts',
'entity_names': ['controller-1'], 'retry_count': 0, 'retry_delay': 120},
{'name': 'wait-alarms-clear', 'timeout': 2400},
]
},
{
'name': 'sw-upgrade-storage-hosts',
'total_steps': 6,
'steps': [
{'name': 'query-alarms'},
{'name': 'lock-hosts',
'entity_names': ['storage-0', 'storage-1', 'storage-2']},
{'name': 'upgrade-hosts',
'entity_names': ['storage-0', 'storage-1', 'storage-2']},
{'name': 'system-stabilize', 'timeout': 15},
{'name': 'unlock-hosts',
'entity_names': ['storage-0', 'storage-1', 'storage-2']},
{'name': 'wait-data-sync', 'timeout': 1800},
]
},
{
'name': 'sw-upgrade-worker-hosts',
'total_steps': 6,
'steps': [
{'name': 'query-alarms'},
{'name': 'lock-hosts',
'entity_names': ['compute-0', 'compute-1', 'compute-2']},
{'name': 'upgrade-hosts',
'entity_names': ['compute-0', 'compute-1', 'compute-2']},
{'name': 'system-stabilize', 'timeout': 15},
{'name': 'unlock-hosts',
'entity_names': ['compute-0', 'compute-1', 'compute-2']},
{'name': 'wait-alarms-clear', 'timeout': 600},
]
},
{
'name': 'sw-upgrade-complete',
'total_steps': 4,
'steps': [
{'name': 'query-alarms'},
{'name': 'activate-upgrade', 'release': release},
{'name': 'complete-upgrade', 'release': release},
{'name': 'system-stabilize', 'timeout': 60},
],
},
],
}
sw_update_testcase.validate_strategy_persists(strategy)
sw_update_testcase.validate_phase(apply_phase, expected_results)
def test_sw_deploy_strategy_standard_apply_phase_rr_major(self):
"""
Test the sw_deploy strategy apply phase:
- standard
- rr
- parallel storage
- parallel workers
- major release
Verify:
- Pass
"""
release = '888.8'
_, _, _, strategy = self._gen_standard_hosts_and_strategy(
release=release,
nfvi_upgrade=nfvi.objects.v1.Upgrade(
release,
{
'state': 'available',
'reboot_required': True,
'sw_version': MAJOR_RELEASE_UPGRADE,
},
None,
None,
)
)
fake_upgrade_obj = SwUpgrade()
strategy.sw_update_obj = fake_upgrade_obj
strategy.build_complete(common_strategy.STRATEGY_RESULT.SUCCESS, "")
apply_phase = strategy.apply_phase.as_dict()
expected_results = {
'total_stages': 6,
'stages': [
{
'name': 'sw-upgrade-start',
'total_steps': 4,
'steps': [
{'name': 'query-alarms'},
{'name': 'swact-hosts',
'entity_names': ['controller-1']},
{'name': 'start-upgrade', 'release': release},
{'name': 'system-stabilize', 'timeout': 60},
],
},
{
'name': 'sw-upgrade-controllers',
'total_steps': 7,
@ -1501,9 +1749,11 @@ class TestSwUpgradeStrategy(sw_update_testcase.SwUpdateStrategyTestCase):
},
{
'name': 'sw-upgrade-complete',
'total_steps': 4,
'total_steps': 5,
'steps': [
{'name': 'query-alarms'},
{'name': 'swact-hosts',
'entity_names': ['controller-1']},
{'name': 'activate-upgrade', 'release': release},
{'name': 'complete-upgrade', 'release': release},
{'name': 'system-stabilize', 'timeout': 60},

View File

@ -21,6 +21,21 @@ from nfv_vim.strategy._strategy import SwUpgradeStrategy
from nfv_unit_tests.tests import sw_update_testcase
INITIAL_RELEASE = "3.2.1"
PATCH_RELEASE_UPGRADE = "3.2.2"
# Minor and Major are both major release upgrades
MINOR_RELEASE_UPGRADE = "4.0.1"
MAJOR_RELEASE_UPGRADE = "4.0.1"
IGNORE_ALARMS_LIST = [
"900.005",
"900.201",
"750.006",
"100.119",
"900.701",
"900.231",
]
# TODO(jkraitbe): Update this when retry count is decicded.
# utility method for the formatting of unlock-hosts stage as dict
@ -44,6 +59,7 @@ def _unlock_hosts_stage_as_dict(host_names, retry_count=5, retry_delay=120):
sw_update_testcase.fake_timer)
@mock.patch('nfv_vim.nfvi.nfvi_compute_plugin_disabled',
sw_update_testcase.fake_nfvi_compute_plugin_disabled)
@mock.patch.object(nfvi.objects.v1.upgrade, 'SW_VERSION', INITIAL_RELEASE)
class TestSwUpgradeStrategy(sw_update_testcase.SwUpdateStrategyTestCase):
def create_sw_upgrade_strategy(self,
@ -81,6 +97,7 @@ class TestSwUpgradeStrategy(sw_update_testcase.SwUpdateStrategyTestCase):
{
'state': 'available',
'reboot_required': True,
'sw_version': MAJOR_RELEASE_UPGRADE,
},
None,
None,
@ -1162,7 +1179,7 @@ class TestSwUpgradeStrategy(sw_update_testcase.SwUpdateStrategyTestCase):
{'name': 'system-stabilize', 'timeout': 15},
_unlock_hosts_stage_as_dict(['controller-0']),
{'name': 'wait-alarms-clear',
'ignore_alarms': ['900.005', '900.201', '750.006', '100.119', '900.701'],
'ignore_alarms': IGNORE_ALARMS_LIST,
'timeout': 2400}
]
}
@ -1212,7 +1229,7 @@ class TestSwUpgradeStrategy(sw_update_testcase.SwUpdateStrategyTestCase):
{'name': 'system-stabilize', 'timeout': 15},
_unlock_hosts_stage_as_dict(['controller-0']),
{'name': 'wait-alarms-clear',
'ignore_alarms': ['900.005', '900.201', '750.006', '100.119', '900.701'],
'ignore_alarms': IGNORE_ALARMS_LIST,
'timeout': 2400},
]
},
@ -1229,7 +1246,7 @@ class TestSwUpgradeStrategy(sw_update_testcase.SwUpdateStrategyTestCase):
{'name': 'system-stabilize', 'timeout': 15},
_unlock_hosts_stage_as_dict(['controller-1']),
{'name': 'wait-alarms-clear',
'ignore_alarms': ['900.005', '900.201', '750.006', '100.119', '900.701'],
'ignore_alarms': IGNORE_ALARMS_LIST,
'timeout': 2400},
]
}
@ -1301,7 +1318,7 @@ class TestSwUpgradeStrategy(sw_update_testcase.SwUpdateStrategyTestCase):
{'name': 'system-stabilize', 'timeout': 15},
_unlock_hosts_stage_as_dict(['controller-0']),
{'name': 'wait-alarms-clear',
'ignore_alarms': ['900.005', '900.201', '750.006', '100.119', '900.701'],
'ignore_alarms': IGNORE_ALARMS_LIST,
'timeout': 2400}
]
},
@ -1318,7 +1335,7 @@ class TestSwUpgradeStrategy(sw_update_testcase.SwUpdateStrategyTestCase):
{'name': 'system-stabilize', 'timeout': 15},
_unlock_hosts_stage_as_dict(['controller-1']),
{'name': 'wait-alarms-clear',
'ignore_alarms': ['900.005', '900.201', '750.006', '100.119', '900.701'],
'ignore_alarms': IGNORE_ALARMS_LIST,
'timeout': 2400}
]
},
@ -1407,9 +1424,11 @@ class TestSwUpgradeStrategy(sw_update_testcase.SwUpdateStrategyTestCase):
'total_stages': 8,
'stages': [
{'name': 'sw-upgrade-start',
'total_steps': 3,
'total_steps': 4,
'steps': [
{'name': 'query-alarms'},
{'name': 'swact-hosts',
'entity_names': ['controller-1']},
{'name': 'start-upgrade',
'release': strategy.nfvi_upgrade.release},
{'name': 'system-stabilize',
@ -1430,7 +1449,7 @@ class TestSwUpgradeStrategy(sw_update_testcase.SwUpdateStrategyTestCase):
'timeout': 15},
_unlock_hosts_stage_as_dict(['controller-1']),
{'name': 'wait-alarms-clear',
'ignore_alarms': ['900.005', '900.201', '750.006', '100.119', '900.701'],
'ignore_alarms': IGNORE_ALARMS_LIST,
'timeout': 2400}
]
},
@ -1448,7 +1467,7 @@ class TestSwUpgradeStrategy(sw_update_testcase.SwUpdateStrategyTestCase):
'timeout': 15},
_unlock_hosts_stage_as_dict(['controller-0']),
{'name': 'wait-alarms-clear',
'ignore_alarms': ['900.005', '900.201', '750.006', '100.119', '900.701'],
'ignore_alarms': IGNORE_ALARMS_LIST,
'timeout': 2400}
]
},
@ -1465,7 +1484,7 @@ class TestSwUpgradeStrategy(sw_update_testcase.SwUpdateStrategyTestCase):
{'name': 'unlock-hosts',
'entity_names': ['storage-0']},
{'name': 'wait-data-sync',
'ignore_alarms': ['900.005', '900.201', '750.006', '100.119', '900.701'],
'ignore_alarms': IGNORE_ALARMS_LIST,
'timeout': 1800}
]
},
@ -1482,7 +1501,7 @@ class TestSwUpgradeStrategy(sw_update_testcase.SwUpdateStrategyTestCase):
{'name': 'unlock-hosts',
'entity_names': ['storage-1']},
{'name': 'wait-data-sync',
'ignore_alarms': ['900.005', '900.201', '750.006', '100.119', '900.701'],
'ignore_alarms': IGNORE_ALARMS_LIST,
'timeout': 1800}
]
},
@ -1522,9 +1541,11 @@ class TestSwUpgradeStrategy(sw_update_testcase.SwUpdateStrategyTestCase):
]
},
{'name': 'sw-upgrade-complete',
'total_steps': 4,
'total_steps': 5,
'steps': [
{'name': 'query-alarms'},
{'name': 'swact-hosts',
'entity_names': ['controller-1']},
{'name': 'activate-upgrade',
'release': strategy.nfvi_upgrade.release},
{'name': 'complete-upgrade',
@ -1540,8 +1561,6 @@ class TestSwUpgradeStrategy(sw_update_testcase.SwUpdateStrategyTestCase):
sw_update_testcase.validate_phase(apply_phase, expected_results)
# pylint: disable=no-member
@mock.patch('nfv_vim.strategy._strategy.get_local_host_name',
sw_update_testcase.fake_host_name_flipper('controller-1', 'controller-0', n=2))
def test_sw_upgrade_strategy_build_complete_serial_migrate(self):
"""
Test the sw_upgrade strategy build_complete:
@ -1575,7 +1594,7 @@ class TestSwUpgradeStrategy(sw_update_testcase.SwUpdateStrategyTestCase):
'total_stages': 6,
'stages': [
{'name': 'sw-upgrade-start',
'total_steps': 5,
'total_steps': 4,
'steps': [
{'name': 'query-alarms'},
{'name': 'swact-hosts',
@ -1584,8 +1603,6 @@ class TestSwUpgradeStrategy(sw_update_testcase.SwUpdateStrategyTestCase):
'release': strategy.nfvi_upgrade.release},
{'name': 'system-stabilize',
'timeout': 60},
{'name': 'swact-hosts',
'entity_names': ['controller-0']},
]
},
{'name': 'sw-upgrade-controllers',
@ -1602,7 +1619,7 @@ class TestSwUpgradeStrategy(sw_update_testcase.SwUpdateStrategyTestCase):
'timeout': 15},
_unlock_hosts_stage_as_dict(['controller-1']),
{'name': 'wait-alarms-clear',
'ignore_alarms': ['900.005', '900.201', '750.006', '100.119', '900.701'],
'ignore_alarms': IGNORE_ALARMS_LIST,
'timeout': 2400}
]
},
@ -1620,7 +1637,7 @@ class TestSwUpgradeStrategy(sw_update_testcase.SwUpdateStrategyTestCase):
'timeout': 15},
_unlock_hosts_stage_as_dict(['controller-0']),
{'name': 'wait-alarms-clear',
'ignore_alarms': ['900.005', '900.201', '750.006', '100.119', '900.701'],
'ignore_alarms': IGNORE_ALARMS_LIST,
'timeout': 2400}
]
},

View File

@ -7,6 +7,7 @@ import six
from nfv_common import debug
from nfv_common.helpers import coroutine
from nfv_common.helpers import get_local_host_name
from nfv_common.helpers import Singleton
from nfv_vim import nfvi
@ -716,6 +717,11 @@ class HostDirector(object):
host_operation.operation_type))
self._host_operation = None
# We don't need to SWACT if we are already on the correct controller.
# This assumes that there will only ever two be controllers.
if len(host_names) == 1 and host_names[0] != get_local_host_name():
return None
host_table = tables.tables_get_host_table()
for host_name in host_names:
host = host_table.get(host_name, None)

View File

@ -1,8 +1,9 @@
#
# Copyright (c) 2015-2023 Wind River Systems, Inc.
# Copyright (c) 2015-2024 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
from nfv_vim.nfvi.objects.v1._alarm import Alarm # noqa: F401
from nfv_vim.nfvi.objects.v1._alarm import ALARM_SEVERITY # noqa: F401
from nfv_vim.nfvi.objects.v1._guest_service import GUEST_SERVICE_ADMIN_STATE # noqa: F401
@ -68,6 +69,8 @@ from nfv_vim.nfvi.objects.v1._subnet import Subnet # noqa: F401
from nfv_vim.nfvi.objects.v1._sw_patch import SwPatch # noqa: F401
from nfv_vim.nfvi.objects.v1._system import System # noqa: F401
from nfv_vim.nfvi.objects.v1._tenant import Tenant # noqa: F401
from nfv_vim.nfvi.objects.v1._upgrade import is_major_release # noqa: F401
import nfv_vim.nfvi.objects.v1._upgrade as upgrade # noqa: F401,H306
from nfv_vim.nfvi.objects.v1._upgrade import Upgrade # noqa: F401
from nfv_vim.nfvi.objects.v1._volume import Volume # noqa: F401
from nfv_vim.nfvi.objects.v1._volume import VOLUME_ACTION # noqa: F401

View File

@ -4,43 +4,19 @@
# SPDX-License-Identifier: Apache-2.0
#
from enum import Enum
from nfv_vim.nfvi.objects.v1._object import ObjectData
import software.states as usm_states
from tsconfig.tsconfig import SW_VERSION
# Enums from https://opendev.org/starlingx/update/src/branch/master/software/software/states.py
class RELEASE_STATES(Enum):
AVAILABLE = 'available'
UNAVAILABLE = 'unavailable'
DEPLOYING = 'deploying'
DEPLOYED = 'deployed'
REMOVING = 'removing'
COMMITTED = 'committed'
def is_major_release(to_release, from_release):
"""Determine if this is a major release software deployment
Major release if major or minor version changed:
eg. 10.11.12 -> (11.1.1 or 10.12.1)
"""
class DEPLOY_STATES(Enum):
START = 'start'
START_DONE = 'start-done'
START_FAILED = 'start-failed'
HOST = 'host'
HOST_DONE = 'host-done'
HOST_FAILED = 'host-failed'
ACTIVATE = 'activate'
ACTIVATE_DONE = 'activate-done'
ACTIVATE_FAILED = 'activate-failed'
ABORT = 'abort'
ABORT_DONE = 'abort-done'
class DEPLOY_HOST_STATES(Enum):
DEPLOYED = 'deployed'
DEPLOYING = 'deploying'
FAILED = 'failed'
PENDING = 'pending'
return to_release.split(".")[:2] != from_release.split(".")[:2]
class Upgrade(ObjectData):
@ -75,50 +51,74 @@ class Upgrade(ObjectData):
return self.release_info["reboot_required"]
@property
def sw_version(self):
if not self.release_info:
return None
return self.release_info["sw_version"]
@property
def major_release(self):
if not self.release_info:
return None
return is_major_release(SW_VERSION, self.sw_version)
@property
def is_available(self):
return self.release_state == RELEASE_STATES.AVAILABLE.value
return self.release_state == usm_states.AVAILABLE
@property
def is_deployed(self):
return self.release_state == RELEASE_STATES.DEPLOYED.value
return self.release_state == usm_states.DEPLOYED
@property
def is_committed(self):
return self.release_state == RELEASE_STATES.COMMITTED.value
return self.release_state == usm_states.COMMITTED
@property
def is_starting(self):
return self.deploy_state == DEPLOY_STATES.START.value
return self.deploy_state == usm_states.DEPLOY_STATES.START.value
@property
def is_start_done(self):
return self.deploy_state == DEPLOY_STATES.START_DONE.value
return self.deploy_state == usm_states.DEPLOY_STATES.START_DONE.value
@property
def is_start_failed(self):
return self.deploy_state == DEPLOY_STATES.START_FAILED.value
return self.deploy_state == usm_states.DEPLOY_STATES.START_FAILED.value
@property
def is_deploying_hosts(self):
return self.deploy_state == DEPLOY_STATES.HOST.value
return self.deploy_state == usm_states.DEPLOY_STATES.HOST.value
@property
def is_deploy_hosts_done(self):
return self.deploy_state == DEPLOY_STATES.HOST_DONE.value
return self.deploy_state == usm_states.DEPLOY_STATES.HOST_DONE.value
@property
def is_deploy_hosts_failed(self):
return self.deploy_state == DEPLOY_STATES.HOST_FAILED.value
return self.deploy_state == usm_states.DEPLOY_STATES.HOST_FAILED.value
@property
def is_activating(self):
return self.deploy_state == DEPLOY_STATES.ACTIVATE.value
return self.deploy_state == usm_states.DEPLOY_STATES.ACTIVATE.value
@property
def is_activate_done(self):
return self.deploy_state == DEPLOY_STATES.ACTIVATE_DONE.value
return self.deploy_state == usm_states.DEPLOY_STATES.ACTIVATE_DONE.value
@property
def is_activate_failed(self):
return self.deploy_state == DEPLOY_STATES.ACTIVATE_FAILED.value
return self.deploy_state == usm_states.DEPLOY_STATES.ACTIVATE_FAILED.value
@property
def all_hosts_deployed(self):
if not self.hosts_info:
return None
for v in self.hosts_info:
if v["host_state"] != usm_states.DEPLOY_HOST_STATES.DEPLOYED.value:
return False
return True

View File

@ -1785,6 +1785,7 @@ class SwUpgradeStrategy(
'750.006', # Configuration change requires reapply of cert-manager
'100.119', # PTP alarm for SyncE
'900.701', # Node tainted
'900.231', # Software deployment data is out of sync
]
self._ignore_alarms += IGNORE_ALARMS
self._single_controller = single_controller
@ -1864,12 +1865,9 @@ class SwUpgradeStrategy(
Currently, certain steps during sw-deploy must be done on a specific controller.
Here we insert arbitrary SWACTs to meet those requirements.
If controller_name does not match the current active host we return because
we are already on ideal host.
"""
if self._single_controller or controller_name != get_local_host_name():
if self._single_controller or not self.nfvi_upgrade.major_release:
return
from nfv_vim import strategy
@ -1885,19 +1883,21 @@ class SwUpgradeStrategy(
"""
Add upgrade start strategy stage
"""
from nfv_vim import strategy
stage = strategy.StrategyStage(strategy.STRATEGY_STAGE_NAME.SW_UPGRADE_START)
stage.add_step(strategy.QueryAlarmsStep(True, ignore_alarms=self._ignore_alarms))
# If the release is not available the deployment is already started
# sw-deploy start must be done on controller-0
if self.nfvi_upgrade.is_available:
stage.add_step(strategy.QueryAlarmsStep(True, ignore_alarms=self._ignore_alarms))
# sw-deploy start for major releases must be done on controller-0
self._swact_fix(stage, HOST_NAME.CONTROLLER_1)
stage.add_step(strategy.UpgradeStartStep(release=self._release, force=self._ignore_alarms))
stage.add_step(strategy.SystemStabilizeStep())
# TODO(jkraitbe): This SWACT should be part of deploy hosts logic
# sw-deploy host must first be on controller-1
self._swact_fix(stage, HOST_NAME.CONTROLLER_0)
else:
DLOG.info("Software deployment already inprogress, skipping start")
self.apply_phase.add_stage(stage)
def _add_upgrade_complete_stage(self):
@ -1908,8 +1908,6 @@ class SwUpgradeStrategy(
stage = strategy.StrategyStage(strategy.STRATEGY_STAGE_NAME.SW_UPGRADE_COMPLETE)
stage.add_step(strategy.QueryAlarmsStep(ignore_alarms=self._ignore_alarms))
# TODO(jkraitbe): This SWACT should be part of deploy hosts logic
# sw-deploy complete should be on controller-0
self._swact_fix(stage, HOST_NAME.CONTROLLER_1)
stage.add_step(strategy.UpgradeActivateStep(release=self._release))
stage.add_step(strategy.UpgradeCompleteStep(release=self._release))
@ -1988,13 +1986,6 @@ class SwUpgradeStrategy(
self._add_upgrade_start_stage()
# TODO(jkraitbe): Exclude hosts that are already deployed.
# The hosts states are found in self.nfvi_upgrade.hosts_info.
# None means deployment hasn't started.
# TODO(jkraitbe): SWACT to controller-1 should be
# here instead of in _add_upgrade_start_stage.
for host in host_table.values():
if HOST_PERSONALITY.CONTROLLER in host.personality:
controllers_hosts.append(host)
@ -2020,8 +2011,12 @@ class SwUpgradeStrategy(
self.save()
return
if not self._single_controller and self.nfvi_upgrade.major_release:
# Reverse controller hosts so controller-1 is first
controllers_hosts = controllers_hosts[::-1]
controllers_hosts = sorted(
controllers_hosts,
key=lambda x: x.name == HOST_NAME.CONTROLLER_0,
)
strategy_pairs = [
(controller_strategy, controllers_hosts),

View File

@ -623,9 +623,12 @@ class SwactHostsStep(strategy.StrategyStep):
DLOG.info("Step (%s) apply for hosts %s." % (self._name,
self._host_names))
host_director = directors.get_host_director()
operation = host_director.swact_hosts(self._host_names)
if operation.is_inprogress():
if operation is None:
return strategy.STRATEGY_STEP_RESULT.SUCCESS, "Already on correct host"
elif operation.is_inprogress():
return strategy.STRATEGY_STEP_RESULT.WAIT, ""
elif operation.is_failed():
return strategy.STRATEGY_STEP_RESULT.FAILED, operation.reason

View File

@ -31,6 +31,8 @@ nfv_plugins_dir = ./nfv-plugins
nfv_vim_dir = ./nfv-vim
nfv_test_dir = ./nfv-tests
stx_fault_dir = ../../fault
stx_tsconfig_dir = ../../config/tsconfig/tsconfig
stx_software_dir = ../../update/software
nfv_client_src_dir = {[nfv]nfv_client_dir}/nfv_client
nfv_common_src_dir = {[nfv]nfv_common_dir}/nfv_common
@ -43,6 +45,8 @@ deps = -e{[nfv]nfv_client_dir}
-e{[nfv]nfv_plugins_dir}
-e{[nfv]nfv_vim_dir}
-e{[nfv]stx_fault_dir}/fm-api/source
-e{[nfv]stx_tsconfig_dir}
-e{[nfv]stx_software_dir}
iso8601
keyring
kombu