Skip to content
Snippets Groups Projects
Commit 77a0fc9d authored by geant-release-service's avatar geant-release-service
Browse files

Finished release 2.24.

parents 31ca85e7 9f3007b1
Branches
Tags 2.24
No related merge requests found
Pipeline #90228 passed
...@@ -15,7 +15,7 @@ run-tox-pipeline: ...@@ -15,7 +15,7 @@ run-tox-pipeline:
image: python:3.12 image: python:3.12
services: services:
- postgres:15.4 - postgres:14
# Change pip's cache directory to be inside the project directory since we can # Change pip's cache directory to be inside the project directory since we can
# only cache local items. # only cache local items.
......
# Changelog # Changelog
## [2.24] - 2024-11-07
- Add support for Moodi dashboard in Edge Port creation workflow
- Fix a bug where ISIS metric restoration did not work correctly
## [2.23] - 2024-11-05 ## [2.23] - 2024-11-05
- Added new workflows and updated the products of Swich and LAN Swith Interconnect - Added new workflows and updated the products of Swich and LAN Swith Interconnect
- Upgraded orchestrator-core to 2.8.0 - Upgraded orchestrator-core to 2.8.0
......
...@@ -116,3 +116,6 @@ Glossary of terms ...@@ -116,3 +116,6 @@ Glossary of terms
WFO WFO
`Workflow Orchestrator <https://workfloworchestrator.org/>`_ `Workflow Orchestrator <https://workfloworchestrator.org/>`_
Moodi
A service that does monitoring on demand during a workflow execution.
\ No newline at end of file
...@@ -125,6 +125,7 @@ ...@@ -125,6 +125,7 @@
"DSN": "https://sentry-dsn-url" "DSN": "https://sentry-dsn-url"
}, },
"MOODI": { "MOODI": {
"host": "moodi.test.gap.geant.org" "host": "moodi.test.gap.geant.org",
"moodi_enabled": false
} }
} }
...@@ -209,6 +209,7 @@ class MoodiParams(BaseSettings): ...@@ -209,6 +209,7 @@ class MoodiParams(BaseSettings):
"""Settings for Moodi.""" """Settings for Moodi."""
host: str host: str
moodi_enabled: bool = False
class OSSParams(BaseSettings): class OSSParams(BaseSettings):
......
...@@ -7,6 +7,7 @@ from orchestrator import inputstep, step ...@@ -7,6 +7,7 @@ from orchestrator import inputstep, step
from orchestrator.config.assignee import Assignee from orchestrator.config.assignee import Assignee
from orchestrator.types import State, UUIDstr from orchestrator.types import State, UUIDstr
from orchestrator.utils.json import json_dumps from orchestrator.utils.json import json_dumps
from orchestrator.workflow import StepList, conditional
from pydantic import ConfigDict from pydantic import ConfigDict
from pydantic_forms.core import FormPage from pydantic_forms.core import FormPage
from pydantic_forms.types import FormGenerator from pydantic_forms.types import FormGenerator
...@@ -14,7 +15,7 @@ from pydantic_forms.validators import Label ...@@ -14,7 +15,7 @@ from pydantic_forms.validators import Label
from gso.products.product_blocks.router import RouterRole from gso.products.product_blocks.router import RouterRole
from gso.products.product_types.iptrunk import Iptrunk from gso.products.product_types.iptrunk import Iptrunk
from gso.services.lso_client import LSOState from gso.services.lso_client import LSOState, anonymous_lso_interaction
from gso.settings import load_oss_params from gso.settings import load_oss_params
from gso.utils.helpers import generate_inventory_for_active_routers from gso.utils.helpers import generate_inventory_for_active_routers
from gso.utils.shared_enums import Vendor from gso.utils.shared_enums import Vendor
...@@ -391,25 +392,34 @@ def prompt_sharepoint_checklist_url(checklist_url: str) -> FormGenerator: ...@@ -391,25 +392,34 @@ def prompt_sharepoint_checklist_url(checklist_url: str) -> FormGenerator:
return {} return {}
@step("Start Moodi") _is_moodi_enabled = conditional(lambda _: load_oss_params().MOODI.moodi_enabled)
def start_moodi(subscription: dict[str, Any]) -> LSOState:
"""Start monitoring on demand using Moodi Telemetry stack."""
params = load_oss_params()
return {
"playbook_name": "moodi_telemetry/playbooks/start_moodi.yaml",
"inventory": {"all": {"hosts": {params.MOODI.host: None}}},
"extra_vars": {"subscription": subscription},
}
def start_moodi() -> StepList:
"""Start monitoring on demand using :term:`Moodi` Telemetry stack."""
host = load_oss_params().MOODI.host
@step("Stop Moodi") @step("Start Moodi")
def stop_moodi() -> LSOState: def _start_moodi(subscription: dict[str, Any]) -> LSOState:
"""Stop monitoring on demand.""" return {
params = load_oss_params() "playbook_name": "moodi_telemetry/playbooks/start_moodi.yaml",
"inventory": {"all": {"hosts": {host: None}}},
"extra_vars": {"subscription": subscription},
}
return { return _is_moodi_enabled(anonymous_lso_interaction(_start_moodi))
"playbook_name": "moodi_telemetry/playbooks/stop_moodi.yaml",
"inventory": {"all": {"hosts": {params.MOODI.host: None}}},
"extra_vars": None, def stop_moodi() -> StepList:
} """Stop :term:`Moodi` Telemetry monitoring on demand."""
host = load_oss_params().MOODI.host
@step("Stop Moodi")
def _stop_moodi() -> LSOState:
return {
"playbook_name": "moodi_telemetry/playbooks/stop_moodi.yaml",
"inventory": {"all": {"hosts": {host: None}}},
"extra_vars": None,
}
return _is_moodi_enabled(anonymous_lso_interaction(_stop_moodi))
...@@ -31,6 +31,7 @@ from gso.utils.helpers import ( ...@@ -31,6 +31,7 @@ from gso.utils.helpers import (
) )
from gso.utils.types.interfaces import LAGMember, PhysicalPortCapacity from gso.utils.types.interfaces import LAGMember, PhysicalPortCapacity
from gso.utils.types.tt_number import TTNumber from gso.utils.types.tt_number import TTNumber
from gso.utils.workflow_steps import start_moodi, stop_moodi
from gso.workflows.shared import create_summary_form from gso.workflows.shared import create_summary_form
...@@ -267,11 +268,13 @@ def create_edge_port() -> StepList: ...@@ -267,11 +268,13 @@ def create_edge_port() -> StepList:
>> create_subscription >> create_subscription
>> store_process_subscription(Target.CREATE) >> store_process_subscription(Target.CREATE)
>> initialize_subscription >> initialize_subscription
>> start_moodi()
>> reserve_interfaces_in_netbox >> reserve_interfaces_in_netbox
>> lso_interaction(create_edge_port_dry) >> lso_interaction(create_edge_port_dry)
>> lso_interaction(create_edge_port_real) >> lso_interaction(create_edge_port_real)
>> allocate_interfaces_in_netbox >> allocate_interfaces_in_netbox
>> set_status(SubscriptionLifecycle.ACTIVE) >> set_status(SubscriptionLifecycle.ACTIVE)
>> resync >> resync
>> stop_moodi()
>> done >> done
) )
...@@ -631,6 +631,7 @@ def restore_isis_metric( ...@@ -631,6 +631,7 @@ def restore_isis_metric(
} }
return { return {
"subscription": subscription,
"playbook_name": "gap_ansible/playbooks/iptrunks.yaml", "playbook_name": "gap_ansible/playbooks/iptrunks.yaml",
"inventory": { "inventory": {
"all": { "all": {
......
...@@ -4,7 +4,7 @@ from setuptools import find_packages, setup ...@@ -4,7 +4,7 @@ from setuptools import find_packages, setup
setup( setup(
name="geant-service-orchestrator", name="geant-service-orchestrator",
version="2.23", version="2.24",
author="GÉANT Orchestration and Automation Team", author="GÉANT Orchestration and Automation Team",
author_email="goat@geant.org", author_email="goat@geant.org",
description="GÉANT Service Orchestrator", description="GÉANT Service Orchestrator",
......
...@@ -109,6 +109,7 @@ def interface_lists_are_equal(list1, list2): ...@@ -109,6 +109,7 @@ def interface_lists_are_equal(list1, list2):
[UseJuniperSide.NONE, UseJuniperSide.SIDE_A, UseJuniperSide.SIDE_B, UseJuniperSide.SIDE_BOTH], [UseJuniperSide.NONE, UseJuniperSide.SIDE_A, UseJuniperSide.SIDE_B, UseJuniperSide.SIDE_BOTH],
indirect=True, indirect=True,
) )
@pytest.mark.parametrize("restore_isis_metric", [True, False])
@pytest.mark.workflow() @pytest.mark.workflow()
@patch("gso.services.infoblox.create_host_by_ip") @patch("gso.services.infoblox.create_host_by_ip")
@patch("gso.services.infoblox.delete_host_by_ip") @patch("gso.services.infoblox.delete_host_by_ip")
...@@ -122,7 +123,7 @@ def interface_lists_are_equal(list1, list2): ...@@ -122,7 +123,7 @@ def interface_lists_are_equal(list1, list2):
@patch("gso.services.netbox_client.NetboxClient.free_interface") @patch("gso.services.netbox_client.NetboxClient.free_interface")
@patch("gso.services.netbox_client.NetboxClient.delete_interface") @patch("gso.services.netbox_client.NetboxClient.delete_interface")
@patch("gso.workflows.iptrunk.migrate_iptrunk.SharePointClient") @patch("gso.workflows.iptrunk.migrate_iptrunk.SharePointClient")
def test_migrate_iptrunk_success( def test_migrate_iptrunk_success( # noqa: PLR0915
mock_sharepoint_client, mock_sharepoint_client,
mocked_delete_interface, mocked_delete_interface,
mocked_free_interface, mocked_free_interface,
...@@ -136,6 +137,7 @@ def test_migrate_iptrunk_success( ...@@ -136,6 +137,7 @@ def test_migrate_iptrunk_success(
mock_delete_host_by_ip, mock_delete_host_by_ip,
mock_create_host_by_ip, mock_create_host_by_ip,
migrate_form_input, migrate_form_input,
restore_isis_metric,
data_config_filename: PathLike, data_config_filename: PathLike,
): ):
# Set up mock return values # Set up mock return values
...@@ -150,6 +152,7 @@ def test_migrate_iptrunk_success( ...@@ -150,6 +152,7 @@ def test_migrate_iptrunk_success(
mocked_delete_interface.return_value = mocked_netbox.delete_interface() mocked_delete_interface.return_value = mocked_netbox.delete_interface()
mock_sharepoint_client.return_value = MockedSharePointClient mock_sharepoint_client.return_value = MockedSharePointClient
migrate_form_input[1]["restore_isis_metric"] = restore_isis_metric
result, process_stat, step_log = run_workflow("migrate_iptrunk", migrate_form_input) result, process_stat, step_log = run_workflow("migrate_iptrunk", migrate_form_input)
for _ in range(8): for _ in range(8):
...@@ -161,10 +164,10 @@ def test_migrate_iptrunk_success( ...@@ -161,10 +164,10 @@ def test_migrate_iptrunk_success(
for _ in range(8): for _ in range(8):
result, step_log = assert_lso_interaction_success(result, process_stat, step_log) result, step_log = assert_lso_interaction_success(result, process_stat, step_log)
assert_suspended(result) if restore_isis_metric:
result, step_log = resume_workflow(process_stat, step_log, input_data=USER_CONFIRM_EMPTY_FORM) assert_suspended(result)
result, step_log = resume_workflow(process_stat, step_log, input_data=USER_CONFIRM_EMPTY_FORM)
for _ in range(1):
result, step_log = assert_lso_interaction_success(result, process_stat, step_log) result, step_log = assert_lso_interaction_success(result, process_stat, step_log)
# Continue workflow after it has displayed a checklist URL. # Continue workflow after it has displayed a checklist URL.
...@@ -178,7 +181,7 @@ def test_migrate_iptrunk_success( ...@@ -178,7 +181,7 @@ def test_migrate_iptrunk_success(
subscription = Iptrunk.from_subscription(subscription_id) subscription = Iptrunk.from_subscription(subscription_id)
assert subscription.status == "active" assert subscription.status == "active"
assert mock_execute_playbook.call_count == 17 assert mock_execute_playbook.call_count == 17 if restore_isis_metric else 16
assert mock_create_host_by_ip.call_count == 1 assert mock_create_host_by_ip.call_count == 1
assert mock_delete_host_by_ip.call_count == 1 assert mock_delete_host_by_ip.call_count == 1
...@@ -216,3 +219,4 @@ def test_migrate_iptrunk_success( ...@@ -216,3 +219,4 @@ def test_migrate_iptrunk_success(
assert subscription.iptrunk.iptrunk_sides[0].iptrunk_side_ae_iface == new_lag_interface assert subscription.iptrunk.iptrunk_sides[0].iptrunk_side_ae_iface == new_lag_interface
existing_members = subscription.iptrunk.iptrunk_sides[0].iptrunk_side_ae_members existing_members = subscription.iptrunk.iptrunk_sides[0].iptrunk_side_ae_members
assert interface_lists_are_equal(new_lag_member_interfaces, existing_members) assert interface_lists_are_equal(new_lag_member_interfaces, existing_members)
assert (subscription.iptrunk.iptrunk_isis_metric == 999999) != restore_isis_metric
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment