Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add log to inform skipped(non-empty) hypervisors #351

Merged
merged 21 commits into from
Apr 11, 2024
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
fd770a9
# This is a combination of 3 commits.
rgildein Mar 26, 2024
87b03b6
Rebase onto main
zxhdaze Apr 4, 2024
7d2281a
Merge branch 'main' into BSENG-2235/add-nonempty-hypervisor-log
agileshaw Apr 5, 2024
6584cee
Merge branch 'main' into BSENG-2235/add-nonempty-hypervisor-log
zxhdaze Apr 8, 2024
3a726c5
Update get_empty_hypervisor, add unit test for upgradable log
zxhdaze Apr 8, 2024
1075cd0
Merge branch 'main' into BSENG-2235/add-nonempty-hypervisor-log
zxhdaze Apr 9, 2024
946ae69
reformat code
zxhdaze Apr 9, 2024
4348c2b
merge onto main
zxhdaze Apr 9, 2024
1f48fe6
move log logic into get_empty_hyperviosr
zxhdaze Apr 9, 2024
55d42d9
reformat code
zxhdaze Apr 9, 2024
df3efa4
reformat code
zxhdaze Apr 9, 2024
126baff
Update cou/utils/nova_compute.py description
zxhdaze Apr 10, 2024
b0ef7a3
Update cou/utils/nova_compute.py description
zxhdaze Apr 10, 2024
30314f7
Merge branch 'main' into BSENG-2235/add-nonempty-hypervisor-log
zxhdaze Apr 10, 2024
df63779
Merge branch 'main' into BSENG-2235/add-nonempty-hypervisor-log
zxhdaze Apr 10, 2024
09c86f8
Merge branch 'main' into BSENG-2235/add-nonempty-hypervisor-log
zxhdaze Apr 10, 2024
53aa21e
change unit test to use mock logger, adjust log level to warning
zxhdaze Apr 10, 2024
8f4e3f1
switch to assert_called_once_with in unit test
zxhdaze Apr 10, 2024
6e392ba
remove unused import
zxhdaze Apr 10, 2024
f5eeb9a
Merge branch 'main' into BSENG-2235/add-nonempty-hypervisor-log
agileshaw Apr 10, 2024
3e6cd3e
Merge branch 'main' into BSENG-2235/add-nonempty-hypervisor-log
agileshaw Apr 11, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions cou/steps/plan.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
from cou.steps.hypervisor import HypervisorUpgradePlanner
from cou.utils.app_utils import set_require_osd_release_option
from cou.utils.juju_utils import DEFAULT_TIMEOUT, Machine, Unit
from cou.utils.nova_compute import get_empty_hypervisors
from cou.utils.nova_compute import get_empty_hypervisors, stringify_units
from cou.utils.openstack import LTS_TO_OS_RELEASE, OpenStackRelease

logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -594,9 +594,18 @@ async def _get_upgradable_hypervisors_machines(
)

if cli_force:
logger.info("Selected all hypervisors: %s", stringify_units(nova_compute_units))
return nova_compute_machines
zxhdaze marked this conversation as resolved.
Show resolved Hide resolved

return await get_empty_hypervisors(nova_compute_units, analysis_result.model)
empty_units, empty_machines = await get_empty_hypervisors(
nova_compute_units, analysis_result.model
)
skipped_units = set(nova_compute_units) - set(empty_units)

logger.info("Found non-empty hypervisors: %s", stringify_units(skipped_units))
logger.info("Selected hypervisors: %s", stringify_units(empty_units))
zxhdaze marked this conversation as resolved.
Show resolved Hide resolved

return empty_machines


def _get_nova_compute_units_and_machines(
Expand Down
29 changes: 25 additions & 4 deletions cou/utils/nova_compute.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,27 +16,36 @@

import asyncio
import logging
from typing import Iterable

from cou.exceptions import HaltUpgradeExecution
from cou.utils.juju_utils import Machine, Model, Unit

logger = logging.getLogger(__name__)


async def get_empty_hypervisors(units: list[Unit], model: Model) -> list[Machine]:
async def get_empty_hypervisors(
units: list[Unit], model: Model
) -> tuple[list[Unit], list[Machine]]:
"""Get the empty hypervisors in the model.

:param units: All nova-compute units.
:type units: list[Unit]
:param model: Model object
:type model: Model
:return: List with just the empty hypervisors machines.
:rtype: list[Machine]
:return: A tuple containing a list of just the empty hypervisors Units
and a list of mahines.
:rtype: tuple[list[Unit], list[Machine]]:
"""
tasks = [get_instance_count(unit.name, model) for unit in units]
instances = await asyncio.gather(*tasks)
units_instances = zip(units, instances)
return [unit.machine for unit, instances in units_instances if instances == 0]
empty_units, empty_machines = [], []
for unit, instance_count in units_instances:
if instance_count == 0:
empty_units.append(unit)
empty_machines.append(unit.machine)
return empty_units, empty_machines


async def get_instance_count(unit: str, model: Model) -> int:
Expand Down Expand Up @@ -85,3 +94,15 @@ async def verify_empty_hypervisor(unit: Unit, model: Model) -> None:
unit_instance_count,
)
raise HaltUpgradeExecution(f"Unit: {unit.name} has {unit_instance_count} VMs running")


def stringify_units(units: Iterable[Unit]) -> str:
zxhdaze marked this conversation as resolved.
Show resolved Hide resolved
zxhdaze marked this conversation as resolved.
Show resolved Hide resolved
"""Convert Units into a comma-separatedstring of unit names, sorted alphabetically.
zxhdaze marked this conversation as resolved.
Show resolved Hide resolved

:param units: A iterable of Unit objects to be converted.
zxhdaze marked this conversation as resolved.
Show resolved Hide resolved
:type units: Iterable[Unit]
:return: A comma-separated string of sorted unit names.
:rtype: str
"""
sorted_unit_names = sorted([unit.name for unit in units], key=lambda name: name)
zxhdaze marked this conversation as resolved.
Show resolved Hide resolved
return ", ".join(sorted_unit_names)
66 changes: 65 additions & 1 deletion tests/unit/steps/test_plan.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
# 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.
import logging
from unittest.mock import MagicMock, PropertyMock, call, patch

import pytest
Expand Down Expand Up @@ -988,7 +989,7 @@ async def test_get_upgradable_hypervisors_machines(
analysis_result = MagicMock(spec_set=Analysis)()
analysis_result.data_plane_machines = analysis_result.machines = machines
analysis_result.apps_data_plane = [nova_compute]
mock_empty_hypervisors.return_value = {
mock_empty_hypervisors.return_value = [], {
machines[f"{machine_id}"] for machine_id in empty_hypervisors
}
hypervisors_possible_to_upgrade = await cou_plan._get_upgradable_hypervisors_machines(
Expand Down Expand Up @@ -1575,3 +1576,66 @@ def test_create_upgrade_plan_failed():

with pytest.raises(Exception, match="test"):
cou_plan._create_upgrade_group([app], "victoria", "test", False)


@pytest.mark.parametrize(
"cli_force, empty_hypervisors, expected_logs",
[
(
True,
{},
[
(
"cou.steps.plan",
logging.INFO,
"Selected all hypervisors: nova-compute/0, nova-compute/1, nova-compute/2",
)
],
),
(
False,
{1},
[
(
"cou.steps.plan",
logging.INFO,
"Found non-empty hypervisors: nova-compute/0, nova-compute/2",
),
("cou.steps.plan", logging.INFO, "Selected hypervisors: nova-compute/1"),
],
),
],
)
@pytest.mark.asyncio
@patch("cou.steps.plan._get_nova_compute_units_and_machines")
@patch("cou.steps.plan.get_empty_hypervisors")
async def test_log_upgradable_hypervisors(
zxhdaze marked this conversation as resolved.
Show resolved Hide resolved
mock_empty_hypervisors,
mock_all_hypervisors,
cli_force,
empty_hypervisors,
expected_logs,
caplog,
):
all_machines = [Machine(str(i), (), ()) for i in range(1, 4)]
empty_machines = [Machine(str(i + 1), (), ()) for i in empty_hypervisors]
all_units = [
Unit(
name=f"nova-compute/{i}",
machine=all_machines[i],
workload_version="21.0.0",
)
for i in range(len(all_machines))
]
empty_units = [unit for unit in all_units if unit.machine in empty_machines]

analysis_result = MagicMock(spec_set=Analysis)()

mock_all_hypervisors.return_value = all_units, all_machines
mock_empty_hypervisors.return_value = empty_units, empty_machines

with caplog.at_level(logging.INFO):
await cou_plan._get_upgradable_hypervisors_machines(cli_force, analysis_result)

for expected_log in expected_logs:
assert expected_log in caplog.record_tuples
2 changes: 1 addition & 1 deletion tests/unit/utils/test_nova_compute.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ async def test_get_empty_hypervisors(
mock_instance_count, hypervisors_count, expected_result, model
):
mock_instance_count.side_effect = [count for _, count in hypervisors_count]
result = await nova_compute.get_empty_hypervisors(
_, result = await nova_compute.get_empty_hypervisors(
[_mock_nova_unit(nova_unit) for nova_unit, _ in hypervisors_count], model
)
assert {machine.machine_id for machine in result} == expected_result
Expand Down
Loading