-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #289 from stfc/enable-disable-HV-action
Enable and Disable Hypervisor in Openstack StacksStorm Action
- Loading branch information
Showing
7 changed files
with
313 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
--- | ||
description: Disables the nova compute service on a hypervisor | ||
enabled: true | ||
entry_point: src/openstack_actions.py | ||
name: hv.compute.service.disable | ||
parameters: | ||
timeout: | ||
default: 5400 | ||
lib_entry_point: | ||
default: workflows.hv_service_actions.hv_service_disable | ||
immutable: true | ||
type: string | ||
requires_openstack: | ||
default: true | ||
immutable: true | ||
type: boolean | ||
cloud_account: | ||
description: "The clouds.yaml account to use whilst performing this action" | ||
required: true | ||
type: string | ||
default: "dev" | ||
enum: | ||
- "dev" | ||
- "prod" | ||
hypervisor_name: | ||
description: Hypervisor to run action on, this should also be the host name on icinga. | ||
required: true | ||
type: string | ||
disabled_reason: | ||
description: The reason this service needs to be disabled. | ||
required: true | ||
type: string | ||
service_binary: | ||
description: The name of the service, i.e. "nova-compute" | ||
type: string | ||
immutable: true | ||
default: "nova-compute" | ||
runner_type: python-script |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
--- | ||
description: Enables the nova compute service on a hypervisor | ||
enabled: true | ||
entry_point: src/openstack_actions.py | ||
name: hv.compute.service.enable | ||
parameters: | ||
timeout: | ||
default: 5400 | ||
lib_entry_point: | ||
default: workflows.hv_service_actions.hv_service_enable | ||
immutable: true | ||
type: string | ||
requires_openstack: | ||
default: true | ||
immutable: true | ||
type: boolean | ||
cloud_account: | ||
description: "The clouds.yaml account to use whilst performing this action" | ||
required: true | ||
type: string | ||
default: "dev" | ||
enum: | ||
- "dev" | ||
- "prod" | ||
hypervisor_name: | ||
description: Hypervisor to run action on, this should also be the host name on icinga. | ||
required: true | ||
type: string | ||
service_binary: | ||
description: The name of the service, i.e. "nova-compute" | ||
type: string | ||
immutable: true | ||
default: "nova-compute" | ||
runner_type: python-script |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
from typing import Optional | ||
from openstack.connection import Connection | ||
from openstack.compute.v2.service import Service | ||
|
||
|
||
def disable_service( | ||
conn: Connection, | ||
service: Service, | ||
hypervisor_name: str, | ||
service_binary: str, | ||
disabled_reason: str, | ||
) -> Optional[Service]: | ||
""" | ||
Disables an Openstack service | ||
:param conn: Openstack connection | ||
:param service: The instance of the service class. | ||
:param hypervisor_name: The name or ID of the hypervisor. | ||
:param service_binary: The name of the service. | ||
:param disabled_reason: The reason for disabling the service. | ||
:return: Returns the Service object. | ||
""" | ||
|
||
if service.status == "enabled": | ||
return conn.compute.disable_service( | ||
service, | ||
host=hypervisor_name, | ||
binary=service_binary, | ||
disabled_reason=disabled_reason, | ||
) | ||
raise RuntimeError( | ||
f"Failed to disable {service_binary} on {hypervisor_name}. Already disabled." | ||
) | ||
|
||
|
||
def enable_service( | ||
conn: Connection, | ||
service: Service, | ||
hypervisor_name: str, | ||
service_binary: str, | ||
) -> Optional[Service]: | ||
""" | ||
Enables an Openstack service | ||
:param conn: Openstack connection | ||
:param service: The instance of the service class. | ||
:param hypervisor_name: The name or ID of the hypervisor. | ||
:param service_binary: The name of the service. | ||
:return: Returns the Service object. | ||
""" | ||
|
||
if service.status == "disabled": | ||
return conn.compute.enable_service( | ||
service, host=hypervisor_name, binary=service_binary | ||
) | ||
raise RuntimeError( | ||
f"Failed to enable {service_binary} on {hypervisor_name}. Already enabled." | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
from openstack.connection import Connection | ||
from openstack_api.openstack_service import disable_service, enable_service | ||
|
||
|
||
def hv_service_disable( | ||
conn: Connection, | ||
hypervisor_name: str, | ||
service_binary: str, | ||
disabled_reason: str, | ||
) -> None: | ||
""" | ||
Disables an Openstack service | ||
:param conn: Openstack connection | ||
:param hypervisor_name: The name or ID of the hypervisor. | ||
:param service_binary: The name of the service. | ||
:param disabled_reason: The reason for disabling the service. | ||
""" | ||
|
||
service = conn.compute.find_service( | ||
service_binary, ignore_missing=False, host=hypervisor_name | ||
) | ||
|
||
disable_service(conn, service, hypervisor_name, service_binary, disabled_reason) | ||
|
||
|
||
def hv_service_enable( | ||
conn: Connection, | ||
hypervisor_name: str, | ||
service_binary: str, | ||
) -> None: | ||
""" | ||
Enables an Openstack service | ||
:param conn: Openstack connection | ||
:param hypervisor_name: The name or ID of the hypervisor. | ||
:param service_binary: The name of the service. | ||
""" | ||
|
||
service = conn.compute.find_service( | ||
service_binary, ignore_missing=False, host=hypervisor_name | ||
) | ||
|
||
enable_service(conn, service, hypervisor_name, service_binary) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,7 +6,7 @@ enabled: true | |
|
||
trigger: | ||
type: "core.st2.webhook" | ||
parameters: | ||
parameters: | ||
url: "migrate-server" | ||
|
||
action: | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
from unittest.mock import MagicMock, NonCallableMagicMock | ||
import pytest | ||
from openstack_api.openstack_service import disable_service, enable_service | ||
|
||
|
||
def test_disable_service_function_disables_service_when_enabled(): | ||
"""tests that openstack disables the service when it is currently enabled""" | ||
|
||
mock_conn = MagicMock() | ||
mock_service = MagicMock() | ||
mock_hypervisor_name = NonCallableMagicMock() | ||
mock_service_binary = NonCallableMagicMock() | ||
mock_disable_reason = NonCallableMagicMock() | ||
|
||
mock_service.status = "enabled" | ||
|
||
res = disable_service( | ||
mock_conn, | ||
mock_service, | ||
mock_hypervisor_name, | ||
mock_service_binary, | ||
mock_disable_reason, | ||
) | ||
|
||
mock_conn.compute.disable_service.assert_called_once_with( | ||
mock_service, | ||
host=mock_hypervisor_name, | ||
binary=mock_service_binary, | ||
disabled_reason=mock_disable_reason, | ||
) | ||
|
||
assert res == mock_conn.compute.disable_service.return_value | ||
|
||
|
||
def test_disable_service_function_returns_none_when_disabled(): | ||
"""tests that openstack returns None when the service is currently disabled""" | ||
|
||
mock_conn = MagicMock() | ||
mock_service = MagicMock() | ||
mock_hypervisor_name = NonCallableMagicMock() | ||
mock_service_binary = NonCallableMagicMock() | ||
mock_disable_reason = NonCallableMagicMock() | ||
|
||
mock_service.status = "disabled" | ||
|
||
with pytest.raises(RuntimeError): | ||
disable_service( | ||
mock_conn, | ||
mock_service, | ||
mock_hypervisor_name, | ||
mock_service_binary, | ||
mock_disable_reason, | ||
) | ||
|
||
|
||
def test_enable_service_function_enables_service_when_disabled(): | ||
"""tests that openstack enables the service when it is currently disabled""" | ||
|
||
mock_conn = MagicMock() | ||
mock_service = MagicMock() | ||
mock_hypervisor_name = NonCallableMagicMock() | ||
mock_service_binary = NonCallableMagicMock() | ||
|
||
mock_service.status = "disabled" | ||
|
||
res = enable_service( | ||
mock_conn, mock_service, mock_hypervisor_name, mock_service_binary | ||
) | ||
|
||
mock_conn.compute.enable_service.assert_called_once_with( | ||
mock_service, | ||
host=mock_hypervisor_name, | ||
binary=mock_service_binary, | ||
) | ||
|
||
assert res == mock_conn.compute.enable_service.return_value | ||
|
||
|
||
def test_enable_service_function_returns_none_when_enabled(): | ||
"""tests that openstack returns none when the service is currently enabled""" | ||
|
||
mock_conn = MagicMock() | ||
mock_service = MagicMock() | ||
mock_hypervisor_name = NonCallableMagicMock() | ||
mock_service_binary = NonCallableMagicMock() | ||
|
||
mock_service.status = "enabled" | ||
|
||
with pytest.raises(RuntimeError): | ||
enable_service( | ||
mock_conn, mock_service, mock_hypervisor_name, mock_service_binary | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
from unittest.mock import MagicMock, patch, NonCallableMagicMock | ||
from workflows.hv_service_actions import hv_service_disable, hv_service_enable | ||
|
||
|
||
@patch("workflows.hv_service_actions.disable_service") | ||
def test_service_disabled_successfully(mock_hv_service_disable): | ||
"""test that hv_service_disable disables an openstack service""" | ||
|
||
mock_conn = MagicMock() | ||
mock_hypervisor_name = NonCallableMagicMock() | ||
mock_service_binary = NonCallableMagicMock() | ||
mock_disabled_reason = NonCallableMagicMock() | ||
|
||
hv_service_disable( | ||
mock_conn, mock_hypervisor_name, mock_service_binary, mock_disabled_reason | ||
) | ||
|
||
mock_conn.compute.find_service.assert_called_once_with( | ||
mock_service_binary, ignore_missing=False, host=mock_hypervisor_name | ||
) | ||
|
||
mock_hv_service_disable.assert_called_once_with( | ||
mock_conn, | ||
mock_conn.compute.find_service.return_value, | ||
mock_hypervisor_name, | ||
mock_service_binary, | ||
mock_disabled_reason, | ||
) | ||
|
||
|
||
@patch("workflows.hv_service_actions.enable_service") | ||
def test_hv_service_enabled_successfully(mock_hv_service_enable): | ||
"""test that hv_service_enable enables an openstack service""" | ||
|
||
mock_conn = MagicMock() | ||
mock_hypervisor_name = NonCallableMagicMock() | ||
mock_service_binary = NonCallableMagicMock() | ||
|
||
hv_service_enable(mock_conn, mock_hypervisor_name, mock_service_binary) | ||
|
||
mock_conn.compute.find_service.assert_called_once_with( | ||
mock_service_binary, ignore_missing=False, host=mock_hypervisor_name | ||
) | ||
|
||
mock_hv_service_enable.assert_called_once_with( | ||
mock_conn, | ||
mock_conn.compute.find_service.return_value, | ||
mock_hypervisor_name, | ||
mock_service_binary, | ||
) |