Support server unshelve to specific availability zone
Closes-Bug: #2100345 Change-Id: I6d16b9251ea342ea921c9a508965eba681ca76e8
This commit is contained in:

committed by
Stephen Finucane

parent
149e96917f
commit
5a0f3f1dd5
@@ -42,6 +42,7 @@ from openstack.identity.v3 import user as _user
|
||||
from openstack.network.v2 import security_group as _sg
|
||||
from openstack import proxy
|
||||
from openstack import resource
|
||||
from openstack import types
|
||||
from openstack import utils
|
||||
from openstack import warnings as os_warnings
|
||||
|
||||
@@ -1194,7 +1195,9 @@ class Proxy(proxy.Proxy):
|
||||
server = self._get_resource(_server.Server, server)
|
||||
server.shelve_offload(self)
|
||||
|
||||
def unshelve_server(self, server, *, host=None):
|
||||
def unshelve_server(
|
||||
self, server, *, host=None, availability_zone=types.UNSET
|
||||
):
|
||||
"""Unshelves or restores a shelved server.
|
||||
|
||||
Policy defaults enable only users with administrative role or the
|
||||
@@ -1208,7 +1211,7 @@ class Proxy(proxy.Proxy):
|
||||
:returns: None
|
||||
"""
|
||||
server = self._get_resource(_server.Server, server)
|
||||
server.unshelve(self, host=host)
|
||||
server.unshelve(self, host=host, availability_zone=availability_zone)
|
||||
|
||||
def trigger_server_crash_dump(self, server):
|
||||
"""Trigger a crash dump in a server.
|
||||
|
@@ -19,18 +19,10 @@ from openstack.compute.v2 import volume_attachment
|
||||
from openstack import exceptions
|
||||
from openstack.image.v2 import image
|
||||
from openstack import resource
|
||||
from openstack import types
|
||||
from openstack import utils
|
||||
|
||||
|
||||
# Workaround Python's lack of an undefined sentinel
|
||||
# https://python-patterns.guide/python/sentinel-object/
|
||||
class Unset:
|
||||
def __bool__(self) -> ty.Literal[False]:
|
||||
return False
|
||||
|
||||
|
||||
UNSET: Unset = Unset()
|
||||
|
||||
CONSOLE_TYPE_ACTION_MAPPING = {
|
||||
'novnc': 'os-getVNCConsole',
|
||||
'xvpvnc': 'os-getVNCConsole',
|
||||
@@ -52,11 +44,6 @@ class Server(resource.Resource, metadata.MetadataMixin, tag.TagMixin):
|
||||
allow_delete = True
|
||||
allow_list = True
|
||||
|
||||
# Sentinel used to differentiate API called without parameter or None
|
||||
# Ex unshelve API can be called without an availability_zone or with
|
||||
# availability_zone = None to unpin the az.
|
||||
_sentinel = object()
|
||||
|
||||
_query_mapping = resource.QueryParameters(
|
||||
"auto_disk_config",
|
||||
"availability_zone",
|
||||
@@ -409,17 +396,17 @@ class Server(resource.Resource, metadata.MetadataMixin, tag.TagMixin):
|
||||
self,
|
||||
session,
|
||||
image,
|
||||
name=UNSET,
|
||||
admin_password=UNSET,
|
||||
preserve_ephemeral=UNSET,
|
||||
access_ipv4=UNSET,
|
||||
access_ipv6=UNSET,
|
||||
metadata=UNSET,
|
||||
user_data=UNSET,
|
||||
key_name=UNSET,
|
||||
description=UNSET,
|
||||
trusted_image_certificates=UNSET,
|
||||
hostname=UNSET,
|
||||
name=types.UNSET,
|
||||
admin_password=types.UNSET,
|
||||
preserve_ephemeral=types.UNSET,
|
||||
access_ipv4=types.UNSET,
|
||||
access_ipv6=types.UNSET,
|
||||
metadata=types.UNSET,
|
||||
user_data=types.UNSET,
|
||||
key_name=types.UNSET,
|
||||
description=types.UNSET,
|
||||
trusted_image_certificates=types.UNSET,
|
||||
hostname=types.UNSET,
|
||||
):
|
||||
"""Rebuild the server with the given arguments.
|
||||
|
||||
@@ -448,27 +435,27 @@ class Server(resource.Resource, metadata.MetadataMixin, tag.TagMixin):
|
||||
:returns: The updated server.
|
||||
"""
|
||||
action = {'imageRef': resource.Resource._get_id(image)}
|
||||
if preserve_ephemeral is not UNSET:
|
||||
if preserve_ephemeral is not types.UNSET:
|
||||
action['preserve_ephemeral'] = preserve_ephemeral
|
||||
if name is not UNSET:
|
||||
if name is not types.UNSET:
|
||||
action['name'] = name
|
||||
if admin_password is not UNSET:
|
||||
if admin_password is not types.UNSET:
|
||||
action['adminPass'] = admin_password
|
||||
if access_ipv4 is not UNSET:
|
||||
if access_ipv4 is not types.UNSET:
|
||||
action['accessIPv4'] = access_ipv4
|
||||
if access_ipv6 is not UNSET:
|
||||
if access_ipv6 is not types.UNSET:
|
||||
action['accessIPv6'] = access_ipv6
|
||||
if metadata is not UNSET:
|
||||
if metadata is not types.UNSET:
|
||||
action['metadata'] = metadata
|
||||
if user_data is not UNSET:
|
||||
if user_data is not types.UNSET:
|
||||
action['user_data'] = user_data
|
||||
if key_name is not UNSET:
|
||||
if key_name is not types.UNSET:
|
||||
action['key_name'] = key_name
|
||||
if description is not UNSET:
|
||||
if description is not types.UNSET:
|
||||
action['description'] = description
|
||||
if trusted_image_certificates is not UNSET:
|
||||
if trusted_image_certificates is not types.UNSET:
|
||||
action['trusted_image_certificates'] = trusted_image_certificates
|
||||
if hostname is not UNSET:
|
||||
if hostname is not types.UNSET:
|
||||
action['hostname'] = hostname
|
||||
|
||||
body = {'rebuild': action}
|
||||
@@ -820,7 +807,7 @@ class Server(resource.Resource, metadata.MetadataMixin, tag.TagMixin):
|
||||
body = {"shelveOffload": None}
|
||||
self._action(session, body)
|
||||
|
||||
def unshelve(self, session, availability_zone=_sentinel, host=None):
|
||||
def unshelve(self, session, availability_zone=types.UNSET, host=None):
|
||||
"""Unshelve the server.
|
||||
|
||||
:param session: The session to use for making this request.
|
||||
|
@@ -43,6 +43,7 @@ from openstack.identity.v3 import project
|
||||
from openstack import proxy as proxy_base
|
||||
from openstack.tests.unit import base
|
||||
from openstack.tests.unit import test_proxy_base
|
||||
from openstack import types
|
||||
from openstack import warnings as os_warnings
|
||||
|
||||
|
||||
@@ -1371,6 +1372,7 @@ class TestCompute(TestComputeProxy):
|
||||
expected_args=[self.proxy],
|
||||
expected_kwargs={
|
||||
"host": None,
|
||||
"availability_zone": types.UNSET,
|
||||
},
|
||||
)
|
||||
|
||||
@@ -1379,11 +1381,9 @@ class TestCompute(TestComputeProxy):
|
||||
"openstack.compute.v2.server.Server.unshelve",
|
||||
self.proxy.unshelve_server,
|
||||
method_args=["value"],
|
||||
method_kwargs={"host": "HOST2"},
|
||||
method_kwargs={"host": "HOST2", "availability_zone": "AZ2"},
|
||||
expected_args=[self.proxy],
|
||||
expected_kwargs={
|
||||
"host": "HOST2",
|
||||
},
|
||||
expected_kwargs={"host": "HOST2", "availability_zone": "AZ2"},
|
||||
)
|
||||
|
||||
def test_server_trigger_dump(self):
|
||||
|
23
openstack/types.py
Normal file
23
openstack/types.py
Normal file
@@ -0,0 +1,23 @@
|
||||
# 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.
|
||||
|
||||
import typing as ty
|
||||
|
||||
|
||||
# Workaround Python's lack of an undefined sentinel
|
||||
# https://python-patterns.guide/python/sentinel-object/
|
||||
class Unset:
|
||||
def __bool__(self) -> ty.Literal[False]:
|
||||
return False
|
||||
|
||||
|
||||
UNSET: Unset = Unset()
|
5
releasenotes/notes/fix-bug-9e1a976958d2543b.yaml
Normal file
5
releasenotes/notes/fix-bug-9e1a976958d2543b.yaml
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
fixes:
|
||||
- |
|
||||
Fixed the issue that unshelving a server to a specific availability zone
|
||||
was failed due to unhandled ``availability_zone`` option.
|
Reference in New Issue
Block a user