diff --git a/openstack/instance_ha/v1/_proxy.py b/openstack/instance_ha/v1/_proxy.py index 13471d182..11081e5ea 100644 --- a/openstack/instance_ha/v1/_proxy.py +++ b/openstack/instance_ha/v1/_proxy.py @@ -16,6 +16,7 @@ from openstack import exceptions from openstack.instance_ha.v1 import host as _host from openstack.instance_ha.v1 import notification as _notification from openstack.instance_ha.v1 import segment as _segment +from openstack.instance_ha.v1 import vmove as _vmove from openstack import proxy from openstack import resource @@ -30,6 +31,7 @@ class Proxy(proxy.Proxy): "host": _host.Host, "notification": _notification.Notification, "segment": _segment.Segment, + "vmove": _vmove.VMove, } def notifications(self, **query): @@ -216,3 +218,43 @@ class Proxy(proxy.Proxy): segment_id=segment_id, ignore_missing=ignore_missing, ) + + def vmoves(self, notification, **query): + """Return a generator of vmoves. + + :param notification: The value can be the UUID of a notification or + a :class: `~masakariclient.sdk.ha.v1.notification.Notification` + instance. + :param kwargs query: Optional query parameters to be sent to + limit the vmoves being returned. + + :returns: A generator of vmoves + """ + notification_id = resource.Resource._get_id(notification) + return self._list( + _vmove.VMove, + notification_id=notification_id, + **query, + ) + + def get_vmove(self, vmove, notification): + """Get a single vmove. + + :param vmove: The value can be the UUID of one vmove or + a :class: `~masakariclient.sdk.ha.v1.vmove.VMove` instance. + :param notification: The value can be the UUID of a notification or + a :class: `~masakariclient.sdk.ha.v1.notification.Notification` + instance. + :returns: one 'VMove' resource class. + :raises: :class:`~openstack.exceptions.ResourceNotFound` + when no resource can be found. + :raises: :class:`~openstack.exceptions.InvalidRequest` + when notification_id is None. + """ + notification_id = resource.Resource._get_id(notification) + vmove_id = resource.Resource._get_id(vmove) + return self._get( + _vmove.VMove, + vmove_id, + notification_id=notification_id, + ) diff --git a/openstack/instance_ha/v1/vmove.py b/openstack/instance_ha/v1/vmove.py new file mode 100644 index 000000000..e9cf9e360 --- /dev/null +++ b/openstack/instance_ha/v1/vmove.py @@ -0,0 +1,63 @@ +# Copyright(c) 2022 Inspur +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# 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. + +from openstack import resource + + +class VMove(resource.Resource): + resource_key = "vmove" + resources_key = "vmoves" + base_path = "/notifications/%(notification_id)s/vmoves" + + # capabilities + # 1] GET /v1/notifications/{notification_uuid}/vmoves + # 2] GET /v1/notifications/{notification_uuid}/vmoves/{vmove_uuid} + allow_list = True + allow_fetch = True + + _query_mapping = resource.QueryParameters( + "sort_key", + "sort_dir", + "type", + "status", + ) + + #: A ID of representing this vmove + id = resource.Body("id") + #: A UUID of representing this vmove + uuid = resource.Body("uuid") + #: The notification UUID this vmove belongs to(in URI) + notification_id = resource.URI("notification_id") + #: A created time of this vmove + created_at = resource.Body("created_at") + #: A latest updated time of this vmove + updated_at = resource.Body("updated_at") + #: The instance uuid of this vmove + server_id = resource.Body("instance_uuid") + #: The instance name of this vmove + server_name = resource.Body("instance_name") + #: The source host of this vmove + source_host = resource.Body("source_host") + #: The dest host of this vmove + dest_host = resource.Body("dest_host") + #: A start time of this vmove + start_time = resource.Body("start_time") + #: A end time of this vmove + end_time = resource.Body("end_time") + #: The status of this vmove + status = resource.Body("status") + #: The type of this vmove + type = resource.Body("type") + #: The message of this vmove + message = resource.Body("message") diff --git a/openstack/tests/unit/instance_ha/v1/test_proxy.py b/openstack/tests/unit/instance_ha/v1/test_proxy.py index 2e54410c3..4fa93520d 100644 --- a/openstack/tests/unit/instance_ha/v1/test_proxy.py +++ b/openstack/tests/unit/instance_ha/v1/test_proxy.py @@ -16,10 +16,13 @@ from openstack.instance_ha.v1 import _proxy from openstack.instance_ha.v1 import host from openstack.instance_ha.v1 import notification from openstack.instance_ha.v1 import segment +from openstack.instance_ha.v1 import vmove from openstack.tests.unit import test_proxy_base SEGMENT_ID = "c50b96eb-2a66-40f8-bca8-c5fa90d595c0" HOST_ID = "52d05e43-d08e-42b8-ae33-e47c8ea2ad47" +NOTIFICATION_ID = "a0e70d3a-b3a2-4616-b65d-a7c03a2c85fc" +VMOVE_ID = "16a7c91f-8342-49a7-c731-3a632293f845" class TestInstanceHaProxy(test_proxy_base.TestProxyBase): @@ -102,3 +105,23 @@ class TestInstanceHaSegments(TestInstanceHaProxy): def test_segment_delete(self): self.verify_delete(self.proxy.delete_segment, segment.Segment, True) + + +class TestInstanceHaVMoves(TestInstanceHaProxy): + def test_vmoves(self): + self.verify_list( + self.proxy.vmoves, + vmove.VMove, + method_args=[NOTIFICATION_ID], + expected_args=[], + expected_kwargs={"notification_id": NOTIFICATION_ID}, + ) + + def test_vmove_get(self): + self.verify_get( + self.proxy.get_vmove, + vmove.VMove, + method_args=[VMOVE_ID, NOTIFICATION_ID], + expected_args=[VMOVE_ID], + expected_kwargs={"notification_id": NOTIFICATION_ID}, + ) diff --git a/openstack/tests/unit/instance_ha/v1/test_vmove.py b/openstack/tests/unit/instance_ha/v1/test_vmove.py new file mode 100644 index 000000000..c5c708d96 --- /dev/null +++ b/openstack/tests/unit/instance_ha/v1/test_vmove.py @@ -0,0 +1,79 @@ +# Copyright(c) 2022 Inspur +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# 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. + +from openstack.instance_ha.v1 import vmove +from openstack.tests.unit import base + +FAKE_ID = "1" +FAKE_UUID = "16a7c91f-8342-49a7-c731-3a632293f845" +FAKE_NOTIFICATION_ID = "a0e70d3a-b3a2-4616-b65d-a7c03a2c85fc" +FAKE_SERVER_ID = "1c2f1795-ce78-4d4c-afd0-ce141fdb3952" + +VMOVE = { + 'id': FAKE_ID, + 'uuid': FAKE_UUID, + 'notification_id': FAKE_NOTIFICATION_ID, + 'created_at': "2023-01-28T14:55:26.000000", + 'updated_at': "2023-01-28T14:55:31.000000", + 'server_id': FAKE_SERVER_ID, + 'server_name': 'vm1', + 'source_host': 'host1', + 'dest_host': 'host2', + 'start_time': "2023-01-28T14:55:27.000000", + 'end_time': "2023-01-28T14:55:31.000000", + 'status': 'succeeded', + 'type': 'evacuation', + 'message': None, +} + + +class TestVMove(base.TestCase): + def test_basic(self): + sot = vmove.VMove(VMOVE) + self.assertEqual("vmove", sot.resource_key) + self.assertEqual("vmoves", sot.resources_key) + self.assertEqual( + "/notifications/%(notification_id)s/vmoves", sot.base_path + ) + self.assertTrue(sot.allow_list) + self.assertTrue(sot.allow_fetch) + + self.assertDictEqual( + { + "status": "status", + "type": "type", + "limit": "limit", + "marker": "marker", + "sort_dir": "sort_dir", + "sort_key": "sort_key", + }, + sot._query_mapping._mapping, + ) + + def test_create(self): + sot = vmove.VMove(**VMOVE) + self.assertEqual(VMOVE["id"], sot.id) + self.assertEqual(VMOVE["uuid"], sot.uuid) + self.assertEqual(VMOVE["notification_id"], sot.notification_id) + self.assertEqual(VMOVE["created_at"], sot.created_at) + self.assertEqual(VMOVE["updated_at"], sot.updated_at) + self.assertEqual(VMOVE["server_id"], sot.server_id) + self.assertEqual(VMOVE["server_name"], sot.server_name) + self.assertEqual(VMOVE["source_host"], sot.source_host) + self.assertEqual(VMOVE["dest_host"], sot.dest_host) + self.assertEqual(VMOVE["start_time"], sot.start_time) + self.assertEqual(VMOVE["end_time"], sot.end_time) + self.assertEqual(VMOVE["status"], sot.status) + self.assertEqual(VMOVE["type"], sot.type) + self.assertEqual(VMOVE["message"], sot.message) diff --git a/releasenotes/notes/add-masakari-vmoves-873ad67830c92254.yaml b/releasenotes/notes/add-masakari-vmoves-873ad67830c92254.yaml new file mode 100644 index 000000000..ffe6d382c --- /dev/null +++ b/releasenotes/notes/add-masakari-vmoves-873ad67830c92254.yaml @@ -0,0 +1,4 @@ +--- +features: + - Add support for the new ``VMove`` resource for the instance + HA service (Masakari).