Merge "Switch image to use SDK"
This commit is contained in:
commit
21c883b3d3
@ -38,7 +38,7 @@ jmespath==0.9.0
|
|||||||
jsonpatch==1.16
|
jsonpatch==1.16
|
||||||
jsonpointer==1.13
|
jsonpointer==1.13
|
||||||
jsonschema==2.6.0
|
jsonschema==2.6.0
|
||||||
keystoneauth1==3.14.0
|
keystoneauth1==3.16.0
|
||||||
kombu==4.0.0
|
kombu==4.0.0
|
||||||
linecache2==1.0.0
|
linecache2==1.0.0
|
||||||
MarkupSafe==1.1.0
|
MarkupSafe==1.1.0
|
||||||
@ -50,9 +50,9 @@ msgpack-python==0.4.0
|
|||||||
munch==2.1.0
|
munch==2.1.0
|
||||||
netaddr==0.7.18
|
netaddr==0.7.18
|
||||||
netifaces==0.10.4
|
netifaces==0.10.4
|
||||||
openstacksdk==0.17.0
|
openstacksdk==0.36.0
|
||||||
os-client-config==1.28.0
|
os-client-config==1.28.0
|
||||||
os-service-types==1.2.0
|
os-service-types==1.7.0
|
||||||
os-testr==1.0.0
|
os-testr==1.0.0
|
||||||
osc-lib==2.0.0
|
osc-lib==2.0.0
|
||||||
osc-placement==1.7.0
|
osc-placement==1.7.0
|
||||||
|
60
openstackclient/common/sdk_utils.py
Normal file
60
openstackclient/common/sdk_utils.py
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
# 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 six
|
||||||
|
|
||||||
|
|
||||||
|
def get_osc_show_columns_for_sdk_resource(
|
||||||
|
sdk_resource,
|
||||||
|
osc_column_map,
|
||||||
|
invisible_columns=None
|
||||||
|
):
|
||||||
|
"""Get and filter the display and attribute columns for an SDK resource.
|
||||||
|
|
||||||
|
Common utility function for preparing the output of an OSC show command.
|
||||||
|
Some of the columns may need to get renamed, others made invisible.
|
||||||
|
|
||||||
|
:param sdk_resource: An SDK resource
|
||||||
|
:param osc_column_map: A hash of mappings for display column names
|
||||||
|
:param invisible_columns: A list of invisible column names
|
||||||
|
|
||||||
|
:returns: Two tuples containing the names of the display and attribute
|
||||||
|
columns
|
||||||
|
"""
|
||||||
|
|
||||||
|
if getattr(sdk_resource, 'allow_get', None) is not None:
|
||||||
|
resource_dict = sdk_resource.to_dict(
|
||||||
|
body=True, headers=False, ignore_none=False)
|
||||||
|
else:
|
||||||
|
resource_dict = sdk_resource
|
||||||
|
|
||||||
|
# Build the OSC column names to display for the SDK resource.
|
||||||
|
attr_map = {}
|
||||||
|
display_columns = list(resource_dict.keys())
|
||||||
|
invisible_columns = [] if invisible_columns is None else invisible_columns
|
||||||
|
for col_name in invisible_columns:
|
||||||
|
if col_name in display_columns:
|
||||||
|
display_columns.remove(col_name)
|
||||||
|
for sdk_attr, osc_attr in six.iteritems(osc_column_map):
|
||||||
|
if sdk_attr in display_columns:
|
||||||
|
attr_map[osc_attr] = sdk_attr
|
||||||
|
display_columns.remove(sdk_attr)
|
||||||
|
if osc_attr not in display_columns:
|
||||||
|
display_columns.append(osc_attr)
|
||||||
|
sorted_display_columns = sorted(display_columns)
|
||||||
|
|
||||||
|
# Build the SDK attribute names for the OSC column names.
|
||||||
|
attr_columns = []
|
||||||
|
for column in sorted_display_columns:
|
||||||
|
new_column = attr_map[column] if column in attr_map else column
|
||||||
|
attr_columns.append(new_column)
|
||||||
|
return tuple(sorted_display_columns), tuple(attr_columns)
|
@ -143,7 +143,7 @@ def _prep_server_detail(compute_client, image_client, server, refresh=True):
|
|||||||
if image_info:
|
if image_info:
|
||||||
image_id = image_info.get('id', '')
|
image_id = image_info.get('id', '')
|
||||||
try:
|
try:
|
||||||
image = utils.find_resource(image_client.images, image_id)
|
image = image_client.get_image(image_id)
|
||||||
info['image'] = "%s (%s)" % (image.name, image_id)
|
info['image'] = "%s (%s)" % (image.name, image_id)
|
||||||
except Exception:
|
except Exception:
|
||||||
info['image'] = image_id
|
info['image'] = image_id
|
||||||
@ -735,10 +735,8 @@ class CreateServer(command.ShowOne):
|
|||||||
# Lookup parsed_args.image
|
# Lookup parsed_args.image
|
||||||
image = None
|
image = None
|
||||||
if parsed_args.image:
|
if parsed_args.image:
|
||||||
image = utils.find_resource(
|
image = image_client.find_image(
|
||||||
image_client.images,
|
parsed_args.image, ignore_missing=False)
|
||||||
parsed_args.image,
|
|
||||||
)
|
|
||||||
|
|
||||||
if not image and parsed_args.image_property:
|
if not image and parsed_args.image_property:
|
||||||
def emit_duplicated_warning(img, image_property):
|
def emit_duplicated_warning(img, image_property):
|
||||||
@ -749,7 +747,7 @@ class CreateServer(command.ShowOne):
|
|||||||
'chosen_one': img_uuid_list[0]})
|
'chosen_one': img_uuid_list[0]})
|
||||||
|
|
||||||
def _match_image(image_api, wanted_properties):
|
def _match_image(image_api, wanted_properties):
|
||||||
image_list = image_api.image_list()
|
image_list = image_api.images()
|
||||||
images_matched = []
|
images_matched = []
|
||||||
for img in image_list:
|
for img in image_list:
|
||||||
img_dict = {}
|
img_dict = {}
|
||||||
@ -768,7 +766,7 @@ class CreateServer(command.ShowOne):
|
|||||||
return []
|
return []
|
||||||
return images_matched
|
return images_matched
|
||||||
|
|
||||||
images = _match_image(image_client.api, parsed_args.image_property)
|
images = _match_image(image_client, parsed_args.image_property)
|
||||||
if len(images) > 1:
|
if len(images) > 1:
|
||||||
emit_duplicated_warning(images,
|
emit_duplicated_warning(images,
|
||||||
parsed_args.image_property)
|
parsed_args.image_property)
|
||||||
@ -890,8 +888,8 @@ class CreateServer(command.ShowOne):
|
|||||||
# one specified by --image, then the compute service will
|
# one specified by --image, then the compute service will
|
||||||
# create a volume from the image and attach it to the
|
# create a volume from the image and attach it to the
|
||||||
# server as a non-root volume.
|
# server as a non-root volume.
|
||||||
image_id = utils.find_resource(
|
image_id = image_client.find_image(dev_map[0],
|
||||||
image_client.images, dev_map[0]).id
|
ignore_missing=False).id
|
||||||
mapping['uuid'] = image_id
|
mapping['uuid'] = image_id
|
||||||
# 3. append size and delete_on_termination if exist
|
# 3. append size and delete_on_termination if exist
|
||||||
if len(dev_map) > 2 and dev_map[2]:
|
if len(dev_map) > 2 and dev_map[2]:
|
||||||
@ -1324,8 +1322,8 @@ class ListServer(command.Lister):
|
|||||||
# image name is given, map it to ID.
|
# image name is given, map it to ID.
|
||||||
image_id = None
|
image_id = None
|
||||||
if parsed_args.image:
|
if parsed_args.image:
|
||||||
image_id = utils.find_resource(image_client.images,
|
image_id = image_client.find_image(parsed_args.image,
|
||||||
parsed_args.image).id
|
ignore_missing=False).id
|
||||||
|
|
||||||
search_opts = {
|
search_opts = {
|
||||||
'reservation_id': parsed_args.reservation_id,
|
'reservation_id': parsed_args.reservation_id,
|
||||||
@ -1476,12 +1474,12 @@ class ListServer(command.Lister):
|
|||||||
(s.image.get('id') for s in data
|
(s.image.get('id') for s in data
|
||||||
if s.image))):
|
if s.image))):
|
||||||
try:
|
try:
|
||||||
images[i_id] = image_client.images.get(i_id)
|
images[i_id] = image_client.get_image(i_id)
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
images_list = image_client.images.list()
|
images_list = image_client.images()
|
||||||
for i in images_list:
|
for i in images_list:
|
||||||
images[i.id] = i
|
images[i.id] = i
|
||||||
except Exception:
|
except Exception:
|
||||||
@ -1925,7 +1923,7 @@ class RebuildServer(command.ShowOne):
|
|||||||
# If parsed_args.image is not set, default to the currently used one.
|
# If parsed_args.image is not set, default to the currently used one.
|
||||||
image_id = parsed_args.image or server.to_dict().get(
|
image_id = parsed_args.image or server.to_dict().get(
|
||||||
'image', {}).get('id')
|
'image', {}).get('id')
|
||||||
image = utils.find_resource(image_client.images, image_id)
|
image = image_client.get_image(image_id)
|
||||||
|
|
||||||
kwargs = {}
|
kwargs = {}
|
||||||
if parsed_args.property:
|
if parsed_args.property:
|
||||||
@ -2195,10 +2193,7 @@ class RescueServer(command.Command):
|
|||||||
|
|
||||||
image = None
|
image = None
|
||||||
if parsed_args.image:
|
if parsed_args.image:
|
||||||
image = utils.find_resource(
|
image = image_client.find_image(parsed_args.image)
|
||||||
image_client.images,
|
|
||||||
parsed_args.image,
|
|
||||||
)
|
|
||||||
|
|
||||||
utils.find_resource(
|
utils.find_resource(
|
||||||
compute_client.servers,
|
compute_client.servers,
|
||||||
|
@ -100,14 +100,11 @@ class CreateServerBackup(command.ShowOne):
|
|||||||
)
|
)
|
||||||
|
|
||||||
image_client = self.app.client_manager.image
|
image_client = self.app.client_manager.image
|
||||||
image = utils.find_resource(
|
image = image_client.find_image(backup_name, ignore_missing=False)
|
||||||
image_client.images,
|
|
||||||
backup_name,
|
|
||||||
)
|
|
||||||
|
|
||||||
if parsed_args.wait:
|
if parsed_args.wait:
|
||||||
if utils.wait_for_status(
|
if utils.wait_for_status(
|
||||||
image_client.images.get,
|
image_client.get_image,
|
||||||
image.id,
|
image.id,
|
||||||
callback=_show_progress,
|
callback=_show_progress,
|
||||||
):
|
):
|
||||||
|
@ -79,14 +79,11 @@ class CreateServerImage(command.ShowOne):
|
|||||||
)
|
)
|
||||||
|
|
||||||
image_client = self.app.client_manager.image
|
image_client = self.app.client_manager.image
|
||||||
image = utils.find_resource(
|
image = image_client.find_image(image_id)
|
||||||
image_client.images,
|
|
||||||
image_id,
|
|
||||||
)
|
|
||||||
|
|
||||||
if parsed_args.wait:
|
if parsed_args.wait:
|
||||||
if utils.wait_for_status(
|
if utils.wait_for_status(
|
||||||
image_client.images.get,
|
image_client.get_image,
|
||||||
image_id,
|
image_id,
|
||||||
callback=_show_progress,
|
callback=_show_progress,
|
||||||
):
|
):
|
||||||
|
@ -27,7 +27,7 @@ API_VERSION_OPTION = 'os_image_api_version'
|
|||||||
API_NAME = "image"
|
API_NAME = "image"
|
||||||
API_VERSIONS = {
|
API_VERSIONS = {
|
||||||
"1": "glanceclient.v1.client.Client",
|
"1": "glanceclient.v1.client.Client",
|
||||||
"2": "glanceclient.v2.client.Client",
|
"2": "openstack.connection.Connection",
|
||||||
}
|
}
|
||||||
|
|
||||||
IMAGE_API_TYPE = 'image'
|
IMAGE_API_TYPE = 'image'
|
||||||
@ -38,44 +38,52 @@ IMAGE_API_VERSIONS = {
|
|||||||
|
|
||||||
|
|
||||||
def make_client(instance):
|
def make_client(instance):
|
||||||
"""Returns an image service client"""
|
|
||||||
image_client = utils.get_client_class(
|
|
||||||
API_NAME,
|
|
||||||
instance._api_version[API_NAME],
|
|
||||||
API_VERSIONS)
|
|
||||||
LOG.debug('Instantiating image client: %s', image_client)
|
|
||||||
|
|
||||||
endpoint = instance.get_endpoint_for_service_type(
|
if instance._api_version[API_NAME] != '1':
|
||||||
API_NAME,
|
LOG.debug(
|
||||||
region_name=instance.region_name,
|
'Image client initialized using OpenStack SDK: %s',
|
||||||
interface=instance.interface,
|
instance.sdk_connection.image,
|
||||||
)
|
)
|
||||||
|
return instance.sdk_connection.image
|
||||||
|
else:
|
||||||
|
"""Returns an image service client"""
|
||||||
|
image_client = utils.get_client_class(
|
||||||
|
API_NAME,
|
||||||
|
instance._api_version[API_NAME],
|
||||||
|
API_VERSIONS)
|
||||||
|
LOG.debug('Instantiating image client: %s', image_client)
|
||||||
|
|
||||||
client = image_client(
|
endpoint = instance.get_endpoint_for_service_type(
|
||||||
endpoint,
|
API_NAME,
|
||||||
token=instance.auth.get_token(instance.session),
|
|
||||||
cacert=instance.cacert,
|
|
||||||
insecure=not instance.verify,
|
|
||||||
)
|
|
||||||
|
|
||||||
# Create the low-level API
|
|
||||||
|
|
||||||
image_api = utils.get_client_class(
|
|
||||||
API_NAME,
|
|
||||||
instance._api_version[API_NAME],
|
|
||||||
IMAGE_API_VERSIONS)
|
|
||||||
LOG.debug('Instantiating image api: %s', image_api)
|
|
||||||
|
|
||||||
client.api = image_api(
|
|
||||||
session=instance.session,
|
|
||||||
endpoint=instance.get_endpoint_for_service_type(
|
|
||||||
IMAGE_API_TYPE,
|
|
||||||
region_name=instance.region_name,
|
region_name=instance.region_name,
|
||||||
interface=instance.interface,
|
interface=instance.interface,
|
||||||
)
|
)
|
||||||
)
|
|
||||||
|
|
||||||
return client
|
client = image_client(
|
||||||
|
endpoint,
|
||||||
|
token=instance.auth.get_token(instance.session),
|
||||||
|
cacert=instance.cacert,
|
||||||
|
insecure=not instance.verify,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Create the low-level API
|
||||||
|
|
||||||
|
image_api = utils.get_client_class(
|
||||||
|
API_NAME,
|
||||||
|
instance._api_version[API_NAME],
|
||||||
|
IMAGE_API_VERSIONS)
|
||||||
|
LOG.debug('Instantiating image api: %s', image_api)
|
||||||
|
|
||||||
|
client.api = image_api(
|
||||||
|
session=instance.session,
|
||||||
|
endpoint=instance.get_endpoint_for_service_type(
|
||||||
|
IMAGE_API_TYPE,
|
||||||
|
region_name=instance.region_name,
|
||||||
|
interface=instance.interface,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
return client
|
||||||
|
|
||||||
|
|
||||||
def build_option_parser(parser):
|
def build_option_parser(parser):
|
||||||
|
@ -18,8 +18,9 @@
|
|||||||
import argparse
|
import argparse
|
||||||
from base64 import b64encode
|
from base64 import b64encode
|
||||||
import logging
|
import logging
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
from glanceclient.common import utils as gc_utils
|
|
||||||
from openstack.image import image_signer
|
from openstack.image import image_signer
|
||||||
from osc_lib.api import utils as api_utils
|
from osc_lib.api import utils as api_utils
|
||||||
from osc_lib.cli import format_columns
|
from osc_lib.cli import format_columns
|
||||||
@ -27,11 +28,16 @@ from osc_lib.cli import parseractions
|
|||||||
from osc_lib.command import command
|
from osc_lib.command import command
|
||||||
from osc_lib import exceptions
|
from osc_lib import exceptions
|
||||||
from osc_lib import utils
|
from osc_lib import utils
|
||||||
import six
|
|
||||||
|
|
||||||
|
from openstackclient.common import sdk_utils
|
||||||
from openstackclient.i18n import _
|
from openstackclient.i18n import _
|
||||||
from openstackclient.identity import common
|
from openstackclient.identity import common
|
||||||
|
|
||||||
|
if os.name == "nt":
|
||||||
|
import msvcrt
|
||||||
|
else:
|
||||||
|
msvcrt = None
|
||||||
|
|
||||||
|
|
||||||
CONTAINER_CHOICES = ["ami", "ari", "aki", "bare", "docker", "ova", "ovf"]
|
CONTAINER_CHOICES = ["ami", "ari", "aki", "bare", "docker", "ova", "ovf"]
|
||||||
DEFAULT_CONTAINER_FORMAT = 'bare'
|
DEFAULT_CONTAINER_FORMAT = 'bare'
|
||||||
@ -44,7 +50,7 @@ MEMBER_STATUS_CHOICES = ["accepted", "pending", "rejected", "all"]
|
|||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def _format_image(image):
|
def _format_image(image, human_readable=False):
|
||||||
"""Format an image to make it more consistent with OSC operations."""
|
"""Format an image to make it more consistent with OSC operations."""
|
||||||
|
|
||||||
info = {}
|
info = {}
|
||||||
@ -56,15 +62,25 @@ def _format_image(image):
|
|||||||
'min_disk', 'protected', 'id', 'file', 'checksum',
|
'min_disk', 'protected', 'id', 'file', 'checksum',
|
||||||
'owner', 'virtual_size', 'min_ram', 'schema']
|
'owner', 'virtual_size', 'min_ram', 'schema']
|
||||||
|
|
||||||
|
# TODO(gtema/anybody): actually it should be possible to drop this method,
|
||||||
|
# since SDK already delivers a proper object
|
||||||
|
image = image.to_dict(ignore_none=True, original_names=True)
|
||||||
|
|
||||||
# split out the usual key and the properties which are top-level
|
# split out the usual key and the properties which are top-level
|
||||||
for key in six.iterkeys(image):
|
for key in image:
|
||||||
if key in fields_to_show:
|
if key in fields_to_show:
|
||||||
info[key] = image.get(key)
|
info[key] = image.get(key)
|
||||||
elif key == 'tags':
|
elif key == 'tags':
|
||||||
continue # handle this later
|
continue # handle this later
|
||||||
else:
|
elif key == 'properties':
|
||||||
|
# NOTE(gtema): flatten content of properties
|
||||||
|
properties.update(image.get(key))
|
||||||
|
elif key != 'location':
|
||||||
properties[key] = image.get(key)
|
properties[key] = image.get(key)
|
||||||
|
|
||||||
|
if human_readable:
|
||||||
|
info['size'] = utils.format_size(image['size'])
|
||||||
|
|
||||||
# format the tags if they are there
|
# format the tags if they are there
|
||||||
info['tags'] = format_columns.ListColumn(image.get('tags'))
|
info['tags'] = format_columns.ListColumn(image.get('tags'))
|
||||||
|
|
||||||
@ -75,6 +91,51 @@ def _format_image(image):
|
|||||||
return info
|
return info
|
||||||
|
|
||||||
|
|
||||||
|
_formatters = {
|
||||||
|
'tags': format_columns.ListColumn,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def _get_member_columns(item):
|
||||||
|
# Trick sdk_utils to return URI attribute
|
||||||
|
column_map = {
|
||||||
|
'image_id': 'image_id'
|
||||||
|
}
|
||||||
|
hidden_columns = ['id', 'location', 'name']
|
||||||
|
return sdk_utils.get_osc_show_columns_for_sdk_resource(
|
||||||
|
item.to_dict(), column_map, hidden_columns)
|
||||||
|
|
||||||
|
|
||||||
|
def get_data_file(args):
|
||||||
|
if args.file:
|
||||||
|
return (open(args.file, 'rb'), args.file)
|
||||||
|
else:
|
||||||
|
# distinguish cases where:
|
||||||
|
# (1) stdin is not valid (as in cron jobs):
|
||||||
|
# openstack ... <&-
|
||||||
|
# (2) image data is provided through stdin:
|
||||||
|
# openstack ... < /tmp/file
|
||||||
|
# (3) no image data provided
|
||||||
|
# openstack ...
|
||||||
|
try:
|
||||||
|
os.fstat(0)
|
||||||
|
except OSError:
|
||||||
|
# (1) stdin is not valid
|
||||||
|
return (None, None)
|
||||||
|
if not sys.stdin.isatty():
|
||||||
|
# (2) image data is provided through stdin
|
||||||
|
image = sys.stdin
|
||||||
|
if hasattr(sys.stdin, 'buffer'):
|
||||||
|
image = sys.stdin.buffer
|
||||||
|
if msvcrt:
|
||||||
|
msvcrt.setmode(sys.stdin.fileno(), os.O_BINARY)
|
||||||
|
|
||||||
|
return (image, None)
|
||||||
|
else:
|
||||||
|
# (3)
|
||||||
|
return (None, None)
|
||||||
|
|
||||||
|
|
||||||
class AddProjectToImage(command.ShowOne):
|
class AddProjectToImage(command.ShowOne):
|
||||||
_description = _("Associate project with image")
|
_description = _("Associate project with image")
|
||||||
|
|
||||||
@ -101,16 +162,18 @@ class AddProjectToImage(command.ShowOne):
|
|||||||
parsed_args.project,
|
parsed_args.project,
|
||||||
parsed_args.project_domain).id
|
parsed_args.project_domain).id
|
||||||
|
|
||||||
image_id = utils.find_resource(
|
image = image_client.find_image(parsed_args.image,
|
||||||
image_client.images,
|
ignore_missing=False)
|
||||||
parsed_args.image).id
|
|
||||||
|
|
||||||
image_member = image_client.image_members.create(
|
obj = image_client.add_member(
|
||||||
image_id,
|
image=image.id,
|
||||||
project_id,
|
member_id=project_id,
|
||||||
)
|
)
|
||||||
|
|
||||||
return zip(*sorted(image_member.items()))
|
display_columns, columns = _get_member_columns(obj)
|
||||||
|
data = utils.get_item_properties(obj, columns, formatters={})
|
||||||
|
|
||||||
|
return (display_columns, data)
|
||||||
|
|
||||||
|
|
||||||
class CreateImage(command.ShowOne):
|
class CreateImage(command.ShowOne):
|
||||||
@ -302,9 +365,9 @@ class CreateImage(command.ShowOne):
|
|||||||
# to do nothing when no options are present as opposed to always
|
# to do nothing when no options are present as opposed to always
|
||||||
# setting a default.
|
# setting a default.
|
||||||
if parsed_args.protected:
|
if parsed_args.protected:
|
||||||
kwargs['protected'] = True
|
kwargs['is_protected'] = True
|
||||||
if parsed_args.unprotected:
|
if parsed_args.unprotected:
|
||||||
kwargs['protected'] = False
|
kwargs['is_protected'] = False
|
||||||
if parsed_args.public:
|
if parsed_args.public:
|
||||||
kwargs['visibility'] = 'public'
|
kwargs['visibility'] = 'public'
|
||||||
if parsed_args.private:
|
if parsed_args.private:
|
||||||
@ -314,24 +377,30 @@ class CreateImage(command.ShowOne):
|
|||||||
if parsed_args.shared:
|
if parsed_args.shared:
|
||||||
kwargs['visibility'] = 'shared'
|
kwargs['visibility'] = 'shared'
|
||||||
if parsed_args.project:
|
if parsed_args.project:
|
||||||
kwargs['owner'] = common.find_project(
|
kwargs['owner_id'] = common.find_project(
|
||||||
identity_client,
|
identity_client,
|
||||||
parsed_args.project,
|
parsed_args.project,
|
||||||
parsed_args.project_domain,
|
parsed_args.project_domain,
|
||||||
).id
|
).id
|
||||||
|
|
||||||
# open the file first to ensure any failures are handled before the
|
# open the file first to ensure any failures are handled before the
|
||||||
# image is created
|
# image is created. Get the file name (if it is file, and not stdin)
|
||||||
fp = gc_utils.get_data_file(parsed_args)
|
# for easier further handling.
|
||||||
|
(fp, fname) = get_data_file(parsed_args)
|
||||||
info = {}
|
info = {}
|
||||||
|
|
||||||
if fp is not None and parsed_args.volume:
|
if fp is not None and parsed_args.volume:
|
||||||
raise exceptions.CommandError(_("Uploading data and using "
|
raise exceptions.CommandError(_("Uploading data and using "
|
||||||
"container are not allowed at "
|
"container are not allowed at "
|
||||||
"the same time"))
|
"the same time"))
|
||||||
|
|
||||||
if fp is None and parsed_args.file:
|
if fp is None and parsed_args.file:
|
||||||
LOG.warning(_("Failed to get an image file."))
|
LOG.warning(_("Failed to get an image file."))
|
||||||
return {}, {}
|
return {}, {}
|
||||||
|
elif fname:
|
||||||
|
kwargs['filename'] = fname
|
||||||
|
elif fp:
|
||||||
|
kwargs['validate_checksum'] = False
|
||||||
|
kwargs['data'] = fp
|
||||||
|
|
||||||
# sign an image using a given local private key file
|
# sign an image using a given local private key file
|
||||||
if parsed_args.sign_key_path or parsed_args.sign_cert_id:
|
if parsed_args.sign_key_path or parsed_args.sign_cert_id:
|
||||||
@ -361,8 +430,8 @@ class CreateImage(command.ShowOne):
|
|||||||
sign_key_path,
|
sign_key_path,
|
||||||
password=pw)
|
password=pw)
|
||||||
except Exception:
|
except Exception:
|
||||||
msg = (_("Error during sign operation: private key could "
|
msg = (_("Error during sign operation: private key "
|
||||||
"not be loaded."))
|
"could not be loaded."))
|
||||||
raise exceptions.CommandError(msg)
|
raise exceptions.CommandError(msg)
|
||||||
|
|
||||||
signature = signer.generate_signature(fp)
|
signature = signer.generate_signature(fp)
|
||||||
@ -371,7 +440,8 @@ class CreateImage(command.ShowOne):
|
|||||||
kwargs['img_signature_certificate_uuid'] = sign_cert_id
|
kwargs['img_signature_certificate_uuid'] = sign_cert_id
|
||||||
kwargs['img_signature_hash_method'] = signer.hash_method
|
kwargs['img_signature_hash_method'] = signer.hash_method
|
||||||
if signer.padding_method:
|
if signer.padding_method:
|
||||||
kwargs['img_signature_key_type'] = signer.padding_method
|
kwargs['img_signature_key_type'] = \
|
||||||
|
signer.padding_method
|
||||||
|
|
||||||
# If a volume is specified.
|
# If a volume is specified.
|
||||||
if parsed_args.volume:
|
if parsed_args.volume:
|
||||||
@ -393,26 +463,7 @@ class CreateImage(command.ShowOne):
|
|||||||
except TypeError:
|
except TypeError:
|
||||||
info['volume_type'] = None
|
info['volume_type'] = None
|
||||||
else:
|
else:
|
||||||
image = image_client.images.create(**kwargs)
|
image = image_client.create_image(**kwargs)
|
||||||
|
|
||||||
if fp is not None:
|
|
||||||
with fp:
|
|
||||||
try:
|
|
||||||
image_client.images.upload(image.id, fp)
|
|
||||||
except Exception:
|
|
||||||
# If the upload fails for some reason attempt to remove the
|
|
||||||
# dangling queued image made by the create() call above but
|
|
||||||
# only if the user did not specify an id which indicates
|
|
||||||
# the Image already exists and should be left alone.
|
|
||||||
try:
|
|
||||||
if 'id' not in kwargs:
|
|
||||||
image_client.images.delete(image.id)
|
|
||||||
except Exception:
|
|
||||||
pass # we don't care about this one
|
|
||||||
raise # now, throw the upload exception again
|
|
||||||
|
|
||||||
# update the image after the data has been uploaded
|
|
||||||
image = image_client.images.get(image.id)
|
|
||||||
|
|
||||||
if not info:
|
if not info:
|
||||||
info = _format_image(image)
|
info = _format_image(image)
|
||||||
@ -439,11 +490,9 @@ class DeleteImage(command.Command):
|
|||||||
image_client = self.app.client_manager.image
|
image_client = self.app.client_manager.image
|
||||||
for image in parsed_args.images:
|
for image in parsed_args.images:
|
||||||
try:
|
try:
|
||||||
image_obj = utils.find_resource(
|
image_obj = image_client.find_image(image,
|
||||||
image_client.images,
|
ignore_missing=False)
|
||||||
image,
|
image_client.delete_image(image_obj.id)
|
||||||
)
|
|
||||||
image_client.images.delete(image_obj.id)
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
del_result += 1
|
del_result += 1
|
||||||
LOG.error(_("Failed to delete image with name or "
|
LOG.error(_("Failed to delete image with name or "
|
||||||
@ -569,18 +618,17 @@ class ListImage(command.Lister):
|
|||||||
|
|
||||||
kwargs = {}
|
kwargs = {}
|
||||||
if parsed_args.public:
|
if parsed_args.public:
|
||||||
kwargs['public'] = True
|
kwargs['visibility'] = 'public'
|
||||||
if parsed_args.private:
|
if parsed_args.private:
|
||||||
kwargs['private'] = True
|
kwargs['visibility'] = 'private'
|
||||||
if parsed_args.community:
|
if parsed_args.community:
|
||||||
kwargs['community'] = True
|
kwargs['visibility'] = 'community'
|
||||||
if parsed_args.shared:
|
if parsed_args.shared:
|
||||||
kwargs['shared'] = True
|
kwargs['visibility'] = 'shared'
|
||||||
if parsed_args.limit:
|
if parsed_args.limit:
|
||||||
kwargs['limit'] = parsed_args.limit
|
kwargs['limit'] = parsed_args.limit
|
||||||
if parsed_args.marker:
|
if parsed_args.marker:
|
||||||
kwargs['marker'] = utils.find_resource(image_client.images,
|
kwargs['marker'] = image_client.find_image(parsed_args.marker).id
|
||||||
parsed_args.marker).id
|
|
||||||
if parsed_args.name:
|
if parsed_args.name:
|
||||||
kwargs['name'] = parsed_args.name
|
kwargs['name'] = parsed_args.name
|
||||||
if parsed_args.status:
|
if parsed_args.status:
|
||||||
@ -599,8 +647,8 @@ class ListImage(command.Lister):
|
|||||||
'Checksum',
|
'Checksum',
|
||||||
'Status',
|
'Status',
|
||||||
'visibility',
|
'visibility',
|
||||||
'protected',
|
'is_protected',
|
||||||
'owner',
|
'owner_id',
|
||||||
'tags',
|
'tags',
|
||||||
)
|
)
|
||||||
column_headers = (
|
column_headers = (
|
||||||
@ -621,24 +669,10 @@ class ListImage(command.Lister):
|
|||||||
column_headers = columns
|
column_headers = columns
|
||||||
|
|
||||||
# List of image data received
|
# List of image data received
|
||||||
data = []
|
|
||||||
limit = None
|
|
||||||
if 'limit' in kwargs:
|
if 'limit' in kwargs:
|
||||||
limit = kwargs['limit']
|
# Disable automatic pagination in SDK
|
||||||
if 'marker' in kwargs:
|
kwargs['paginated'] = False
|
||||||
data = image_client.api.image_list(**kwargs)
|
data = list(image_client.images(**kwargs))
|
||||||
else:
|
|
||||||
# No pages received yet, so start the page marker at None.
|
|
||||||
marker = None
|
|
||||||
while True:
|
|
||||||
page = image_client.api.image_list(marker=marker, **kwargs)
|
|
||||||
if not page:
|
|
||||||
break
|
|
||||||
data.extend(page)
|
|
||||||
# Set the marker to the id of the last item we received
|
|
||||||
marker = page[-1]['id']
|
|
||||||
if limit:
|
|
||||||
break
|
|
||||||
|
|
||||||
if parsed_args.property:
|
if parsed_args.property:
|
||||||
for attr, value in parsed_args.property.items():
|
for attr, value in parsed_args.property.items():
|
||||||
@ -653,12 +687,10 @@ class ListImage(command.Lister):
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
column_headers,
|
column_headers,
|
||||||
(utils.get_dict_properties(
|
(utils.get_item_properties(
|
||||||
s,
|
s,
|
||||||
columns,
|
columns,
|
||||||
formatters={
|
formatters=_formatters,
|
||||||
'tags': format_columns.ListColumn,
|
|
||||||
},
|
|
||||||
) for s in data)
|
) for s in data)
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -684,11 +716,9 @@ class ListImageProjects(command.Lister):
|
|||||||
"Status"
|
"Status"
|
||||||
)
|
)
|
||||||
|
|
||||||
image_id = utils.find_resource(
|
image_id = image_client.find_image(parsed_args.image).id
|
||||||
image_client.images,
|
|
||||||
parsed_args.image).id
|
|
||||||
|
|
||||||
data = image_client.image_members.list(image_id)
|
data = image_client.members(image=image_id)
|
||||||
|
|
||||||
return (columns,
|
return (columns,
|
||||||
(utils.get_item_properties(
|
(utils.get_item_properties(
|
||||||
@ -722,11 +752,12 @@ class RemoveProjectImage(command.Command):
|
|||||||
parsed_args.project,
|
parsed_args.project,
|
||||||
parsed_args.project_domain).id
|
parsed_args.project_domain).id
|
||||||
|
|
||||||
image_id = utils.find_resource(
|
image = image_client.find_image(parsed_args.image,
|
||||||
image_client.images,
|
ignore_missing=False)
|
||||||
parsed_args.image).id
|
|
||||||
|
|
||||||
image_client.image_members.delete(image_id, project_id)
|
image_client.remove_member(
|
||||||
|
member=project_id,
|
||||||
|
image=image.id)
|
||||||
|
|
||||||
|
|
||||||
class SaveImage(command.Command):
|
class SaveImage(command.Command):
|
||||||
@ -748,19 +779,9 @@ class SaveImage(command.Command):
|
|||||||
|
|
||||||
def take_action(self, parsed_args):
|
def take_action(self, parsed_args):
|
||||||
image_client = self.app.client_manager.image
|
image_client = self.app.client_manager.image
|
||||||
image = utils.find_resource(
|
image = image_client.find_image(parsed_args.image)
|
||||||
image_client.images,
|
|
||||||
parsed_args.image,
|
|
||||||
)
|
|
||||||
data = image_client.images.data(image.id)
|
|
||||||
|
|
||||||
if data.wrapped is None:
|
image_client.download_image(image.id, output=parsed_args.file)
|
||||||
msg = _('Image %s has no data.') % image.id
|
|
||||||
LOG.error(msg)
|
|
||||||
self.app.stdout.write(msg + '\n')
|
|
||||||
raise SystemExit
|
|
||||||
|
|
||||||
gc_utils.save_image(data, parsed_args.file)
|
|
||||||
|
|
||||||
|
|
||||||
class SetImage(command.Command):
|
class SetImage(command.Command):
|
||||||
@ -979,9 +1000,9 @@ class SetImage(command.Command):
|
|||||||
# to do nothing when no options are present as opposed to always
|
# to do nothing when no options are present as opposed to always
|
||||||
# setting a default.
|
# setting a default.
|
||||||
if parsed_args.protected:
|
if parsed_args.protected:
|
||||||
kwargs['protected'] = True
|
kwargs['is_protected'] = True
|
||||||
if parsed_args.unprotected:
|
if parsed_args.unprotected:
|
||||||
kwargs['protected'] = False
|
kwargs['is_protected'] = False
|
||||||
if parsed_args.public:
|
if parsed_args.public:
|
||||||
kwargs['visibility'] = 'public'
|
kwargs['visibility'] = 'public'
|
||||||
if parsed_args.private:
|
if parsed_args.private:
|
||||||
@ -997,17 +1018,20 @@ class SetImage(command.Command):
|
|||||||
parsed_args.project,
|
parsed_args.project,
|
||||||
parsed_args.project_domain,
|
parsed_args.project_domain,
|
||||||
).id
|
).id
|
||||||
kwargs['owner'] = project_id
|
kwargs['owner_id'] = project_id
|
||||||
|
|
||||||
image = utils.find_resource(
|
image = image_client.find_image(parsed_args.image,
|
||||||
image_client.images, parsed_args.image)
|
ignore_missing=False)
|
||||||
|
|
||||||
|
# image = utils.find_resource(
|
||||||
|
# image_client.images, parsed_args.image)
|
||||||
|
|
||||||
activation_status = None
|
activation_status = None
|
||||||
if parsed_args.deactivate:
|
if parsed_args.deactivate:
|
||||||
image_client.images.deactivate(image.id)
|
image_client.deactivate_image(image.id)
|
||||||
activation_status = "deactivated"
|
activation_status = "deactivated"
|
||||||
if parsed_args.activate:
|
if parsed_args.activate:
|
||||||
image_client.images.reactivate(image.id)
|
image_client.reactivate_image(image.id)
|
||||||
activation_status = "activated"
|
activation_status = "activated"
|
||||||
|
|
||||||
membership_group_args = ('accept', 'reject', 'pending')
|
membership_group_args = ('accept', 'reject', 'pending')
|
||||||
@ -1022,15 +1046,15 @@ class SetImage(command.Command):
|
|||||||
# most one item in the membership_status list.
|
# most one item in the membership_status list.
|
||||||
if membership_status[0] != 'pending':
|
if membership_status[0] != 'pending':
|
||||||
membership_status[0] += 'ed' # Glance expects the past form
|
membership_status[0] += 'ed' # Glance expects the past form
|
||||||
image_client.image_members.update(
|
image_client.update_member(
|
||||||
image.id, project_id, membership_status[0])
|
image=image.id, member=project_id, status=membership_status[0])
|
||||||
|
|
||||||
if parsed_args.tags:
|
if parsed_args.tags:
|
||||||
# Tags should be extended, but duplicates removed
|
# Tags should be extended, but duplicates removed
|
||||||
kwargs['tags'] = list(set(image.tags).union(set(parsed_args.tags)))
|
kwargs['tags'] = list(set(image.tags).union(set(parsed_args.tags)))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
image = image_client.images.update(image.id, **kwargs)
|
image = image_client.update_image(image.id, **kwargs)
|
||||||
except Exception:
|
except Exception:
|
||||||
if activation_status is not None:
|
if activation_status is not None:
|
||||||
LOG.info(_("Image %(id)s was %(status)s."),
|
LOG.info(_("Image %(id)s was %(status)s."),
|
||||||
@ -1058,14 +1082,11 @@ class ShowImage(command.ShowOne):
|
|||||||
|
|
||||||
def take_action(self, parsed_args):
|
def take_action(self, parsed_args):
|
||||||
image_client = self.app.client_manager.image
|
image_client = self.app.client_manager.image
|
||||||
image = utils.find_resource(
|
|
||||||
image_client.images,
|
|
||||||
parsed_args.image,
|
|
||||||
)
|
|
||||||
if parsed_args.human_readable:
|
|
||||||
image['size'] = utils.format_size(image['size'])
|
|
||||||
|
|
||||||
info = _format_image(image)
|
image = image_client.find_image(parsed_args.image,
|
||||||
|
ignore_missing=False)
|
||||||
|
|
||||||
|
info = _format_image(image, parsed_args.human_readable)
|
||||||
return zip(*sorted(info.items()))
|
return zip(*sorted(info.items()))
|
||||||
|
|
||||||
|
|
||||||
@ -1101,10 +1122,8 @@ class UnsetImage(command.Command):
|
|||||||
|
|
||||||
def take_action(self, parsed_args):
|
def take_action(self, parsed_args):
|
||||||
image_client = self.app.client_manager.image
|
image_client = self.app.client_manager.image
|
||||||
image = utils.find_resource(
|
image = image_client.find_image(parsed_args.image,
|
||||||
image_client.images,
|
ignore_missing=False)
|
||||||
parsed_args.image,
|
|
||||||
)
|
|
||||||
|
|
||||||
kwargs = {}
|
kwargs = {}
|
||||||
tagret = 0
|
tagret = 0
|
||||||
@ -1112,7 +1131,7 @@ class UnsetImage(command.Command):
|
|||||||
if parsed_args.tags:
|
if parsed_args.tags:
|
||||||
for k in parsed_args.tags:
|
for k in parsed_args.tags:
|
||||||
try:
|
try:
|
||||||
image_client.image_tags.delete(image.id, k)
|
image_client.remove_tag(image.id, k)
|
||||||
except Exception:
|
except Exception:
|
||||||
LOG.error(_("tag unset failed, '%s' is a "
|
LOG.error(_("tag unset failed, '%s' is a "
|
||||||
"nonexistent tag "), k)
|
"nonexistent tag "), k)
|
||||||
@ -1120,13 +1139,26 @@ class UnsetImage(command.Command):
|
|||||||
|
|
||||||
if parsed_args.properties:
|
if parsed_args.properties:
|
||||||
for k in parsed_args.properties:
|
for k in parsed_args.properties:
|
||||||
if k not in image:
|
if k in image:
|
||||||
|
kwargs[k] = None
|
||||||
|
elif k in image.properties:
|
||||||
|
# Since image is an "evil" object from SDK POV we need to
|
||||||
|
# pass modified properties object, so that SDK can figure
|
||||||
|
# out, what was changed inside
|
||||||
|
# NOTE: ping gtema to improve that in SDK
|
||||||
|
new_props = kwargs.get('properties',
|
||||||
|
image.get('properties').copy())
|
||||||
|
new_props.pop(k, None)
|
||||||
|
kwargs['properties'] = new_props
|
||||||
|
else:
|
||||||
LOG.error(_("property unset failed, '%s' is a "
|
LOG.error(_("property unset failed, '%s' is a "
|
||||||
"nonexistent property "), k)
|
"nonexistent property "), k)
|
||||||
propret += 1
|
propret += 1
|
||||||
image_client.images.update(
|
|
||||||
image.id,
|
# We must give to update a current image for the reference on what
|
||||||
parsed_args.properties,
|
# has changed
|
||||||
|
image_client.update_image(
|
||||||
|
image,
|
||||||
**kwargs)
|
**kwargs)
|
||||||
|
|
||||||
tagtotal = len(parsed_args.tags)
|
tagtotal = len(parsed_args.tags)
|
||||||
|
@ -55,6 +55,12 @@ class TestServer(compute_fakes.TestComputev2):
|
|||||||
self.images_mock = self.app.client_manager.image.images
|
self.images_mock = self.app.client_manager.image.images
|
||||||
self.images_mock.reset_mock()
|
self.images_mock.reset_mock()
|
||||||
|
|
||||||
|
self.find_image_mock = self.app.client_manager.image.find_image
|
||||||
|
self.find_image_mock.reset_mock()
|
||||||
|
|
||||||
|
self.get_image_mock = self.app.client_manager.image.get_image
|
||||||
|
self.get_image_mock.reset_mock()
|
||||||
|
|
||||||
# Get a shortcut to the volume client VolumeManager Mock
|
# Get a shortcut to the volume client VolumeManager Mock
|
||||||
self.volumes_mock = self.app.client_manager.volume.volumes
|
self.volumes_mock = self.app.client_manager.volume.volumes
|
||||||
self.volumes_mock.reset_mock()
|
self.volumes_mock.reset_mock()
|
||||||
@ -770,7 +776,8 @@ class TestServerCreate(TestServer):
|
|||||||
self.servers_mock.create.return_value = self.new_server
|
self.servers_mock.create.return_value = self.new_server
|
||||||
|
|
||||||
self.image = image_fakes.FakeImage.create_one_image()
|
self.image = image_fakes.FakeImage.create_one_image()
|
||||||
self.images_mock.get.return_value = self.image
|
self.find_image_mock.return_value = self.image
|
||||||
|
self.get_image_mock.return_value = self.image
|
||||||
|
|
||||||
self.flavor = compute_fakes.FakeFlavor.create_one_flavor()
|
self.flavor = compute_fakes.FakeFlavor.create_one_flavor()
|
||||||
self.flavors_mock.get.return_value = self.flavor
|
self.flavors_mock.get.return_value = self.flavor
|
||||||
@ -1916,19 +1923,13 @@ class TestServerCreate(TestServer):
|
|||||||
('config_drive', False),
|
('config_drive', False),
|
||||||
('server_name', self.new_server.name),
|
('server_name', self.new_server.name),
|
||||||
]
|
]
|
||||||
_image = image_fakes.FakeImage.create_one_image()
|
|
||||||
# create a image_info as the side_effect of the fake image_list()
|
# create a image_info as the side_effect of the fake image_list()
|
||||||
image_info = {
|
image_info = {
|
||||||
'id': _image.id,
|
|
||||||
'name': _image.name,
|
|
||||||
'owner': _image.owner,
|
|
||||||
'hypervisor_type': 'qemu',
|
'hypervisor_type': 'qemu',
|
||||||
}
|
}
|
||||||
self.api_mock = mock.Mock()
|
|
||||||
self.api_mock.image_list.side_effect = [
|
_image = image_fakes.FakeImage.create_one_image(image_info)
|
||||||
[image_info], [],
|
self.images_mock.return_value = [_image]
|
||||||
]
|
|
||||||
self.app.client_manager.image.api = self.api_mock
|
|
||||||
|
|
||||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
@ -1953,7 +1954,7 @@ class TestServerCreate(TestServer):
|
|||||||
# ServerManager.create(name, image, flavor, **kwargs)
|
# ServerManager.create(name, image, flavor, **kwargs)
|
||||||
self.servers_mock.create.assert_called_with(
|
self.servers_mock.create.assert_called_with(
|
||||||
self.new_server.name,
|
self.new_server.name,
|
||||||
image_info,
|
_image,
|
||||||
self.flavor,
|
self.flavor,
|
||||||
**kwargs
|
**kwargs
|
||||||
)
|
)
|
||||||
@ -1977,20 +1978,13 @@ class TestServerCreate(TestServer):
|
|||||||
('config_drive', False),
|
('config_drive', False),
|
||||||
('server_name', self.new_server.name),
|
('server_name', self.new_server.name),
|
||||||
]
|
]
|
||||||
_image = image_fakes.FakeImage.create_one_image()
|
|
||||||
# create a image_info as the side_effect of the fake image_list()
|
# create a image_info as the side_effect of the fake image_list()
|
||||||
image_info = {
|
image_info = {
|
||||||
'id': _image.id,
|
|
||||||
'name': _image.name,
|
|
||||||
'owner': _image.owner,
|
|
||||||
'hypervisor_type': 'qemu',
|
'hypervisor_type': 'qemu',
|
||||||
'hw_disk_bus': 'ide',
|
'hw_disk_bus': 'ide',
|
||||||
}
|
}
|
||||||
self.api_mock = mock.Mock()
|
_image = image_fakes.FakeImage.create_one_image(image_info)
|
||||||
self.api_mock.image_list.side_effect = [
|
self.images_mock.return_value = [_image]
|
||||||
[image_info], [],
|
|
||||||
]
|
|
||||||
self.app.client_manager.image.api = self.api_mock
|
|
||||||
|
|
||||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
@ -2015,7 +2009,7 @@ class TestServerCreate(TestServer):
|
|||||||
# ServerManager.create(name, image, flavor, **kwargs)
|
# ServerManager.create(name, image, flavor, **kwargs)
|
||||||
self.servers_mock.create.assert_called_with(
|
self.servers_mock.create.assert_called_with(
|
||||||
self.new_server.name,
|
self.new_server.name,
|
||||||
image_info,
|
_image,
|
||||||
self.flavor,
|
self.flavor,
|
||||||
**kwargs
|
**kwargs
|
||||||
)
|
)
|
||||||
@ -2039,20 +2033,14 @@ class TestServerCreate(TestServer):
|
|||||||
('config_drive', False),
|
('config_drive', False),
|
||||||
('server_name', self.new_server.name),
|
('server_name', self.new_server.name),
|
||||||
]
|
]
|
||||||
_image = image_fakes.FakeImage.create_one_image()
|
|
||||||
# create a image_info as the side_effect of the fake image_list()
|
# create a image_info as the side_effect of the fake image_list()
|
||||||
image_info = {
|
image_info = {
|
||||||
'id': _image.id,
|
|
||||||
'name': _image.name,
|
|
||||||
'owner': _image.owner,
|
|
||||||
'hypervisor_type': 'qemu',
|
'hypervisor_type': 'qemu',
|
||||||
'hw_disk_bus': 'ide',
|
'hw_disk_bus': 'ide',
|
||||||
}
|
}
|
||||||
self.api_mock = mock.Mock()
|
|
||||||
self.api_mock.image_list.side_effect = [
|
_image = image_fakes.FakeImage.create_one_image(image_info)
|
||||||
[image_info], [],
|
self.images_mock.return_value = [_image]
|
||||||
]
|
|
||||||
self.app.client_manager.image.api = self.api_mock
|
|
||||||
|
|
||||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
@ -2585,7 +2573,10 @@ class TestServerList(TestServer):
|
|||||||
self.servers_mock.list.return_value = self.servers
|
self.servers_mock.list.return_value = self.servers
|
||||||
|
|
||||||
self.image = image_fakes.FakeImage.create_one_image()
|
self.image = image_fakes.FakeImage.create_one_image()
|
||||||
self.images_mock.get.return_value = self.image
|
|
||||||
|
# self.images_mock.return_value = [self.image]
|
||||||
|
self.find_image_mock.return_value = self.image
|
||||||
|
self.get_image_mock.return_value = self.image
|
||||||
|
|
||||||
self.flavor = compute_fakes.FakeFlavor.create_one_flavor()
|
self.flavor = compute_fakes.FakeFlavor.create_one_flavor()
|
||||||
self.flavors_mock.get.return_value = self.flavor
|
self.flavors_mock.get.return_value = self.flavor
|
||||||
@ -2599,7 +2590,7 @@ class TestServerList(TestServer):
|
|||||||
self.data_no_name_lookup = []
|
self.data_no_name_lookup = []
|
||||||
|
|
||||||
Image = collections.namedtuple('Image', 'id name')
|
Image = collections.namedtuple('Image', 'id name')
|
||||||
self.images_mock.list.return_value = [
|
self.images_mock.return_value = [
|
||||||
Image(id=s.image['id'], name=self.image.name)
|
Image(id=s.image['id'], name=self.image.name)
|
||||||
# Image will be an empty string if boot-from-volume
|
# Image will be an empty string if boot-from-volume
|
||||||
for s in self.servers if s.image
|
for s in self.servers if s.image
|
||||||
@ -2662,11 +2653,11 @@ class TestServerList(TestServer):
|
|||||||
columns, data = self.cmd.take_action(parsed_args)
|
columns, data = self.cmd.take_action(parsed_args)
|
||||||
|
|
||||||
self.servers_mock.list.assert_called_with(**self.kwargs)
|
self.servers_mock.list.assert_called_with(**self.kwargs)
|
||||||
self.images_mock.list.assert_called()
|
self.images_mock.assert_called()
|
||||||
self.flavors_mock.list.assert_called()
|
self.flavors_mock.list.assert_called()
|
||||||
# we did not pass image or flavor, so gets on those must be absent
|
# we did not pass image or flavor, so gets on those must be absent
|
||||||
self.assertFalse(self.flavors_mock.get.call_count)
|
self.assertFalse(self.flavors_mock.get.call_count)
|
||||||
self.assertFalse(self.images_mock.get.call_count)
|
self.assertFalse(self.get_image_mock.call_count)
|
||||||
self.assertEqual(self.columns, columns)
|
self.assertEqual(self.columns, columns)
|
||||||
self.assertEqual(tuple(self.data), tuple(data))
|
self.assertEqual(tuple(self.data), tuple(data))
|
||||||
|
|
||||||
@ -2753,7 +2744,7 @@ class TestServerList(TestServer):
|
|||||||
self.servers_mock.list.assert_called_with(**self.kwargs)
|
self.servers_mock.list.assert_called_with(**self.kwargs)
|
||||||
self.assertFalse(self.images_mock.list.call_count)
|
self.assertFalse(self.images_mock.list.call_count)
|
||||||
self.assertFalse(self.flavors_mock.list.call_count)
|
self.assertFalse(self.flavors_mock.list.call_count)
|
||||||
self.images_mock.get.assert_called()
|
self.get_image_mock.assert_called()
|
||||||
self.flavors_mock.get.assert_called()
|
self.flavors_mock.get.assert_called()
|
||||||
|
|
||||||
self.assertEqual(self.columns, columns)
|
self.assertEqual(self.columns, columns)
|
||||||
@ -2771,7 +2762,8 @@ class TestServerList(TestServer):
|
|||||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
columns, data = self.cmd.take_action(parsed_args)
|
columns, data = self.cmd.take_action(parsed_args)
|
||||||
|
|
||||||
self.images_mock.get.assert_any_call(self.image.id)
|
self.find_image_mock.assert_called_with(self.image.id,
|
||||||
|
ignore_missing=False)
|
||||||
|
|
||||||
self.search_opts['image'] = self.image.id
|
self.search_opts['image'] = self.image.id
|
||||||
self.servers_mock.list.assert_called_with(**self.kwargs)
|
self.servers_mock.list.assert_called_with(**self.kwargs)
|
||||||
@ -3558,7 +3550,7 @@ class TestServerRebuild(TestServer):
|
|||||||
|
|
||||||
# Return value for utils.find_resource for image
|
# Return value for utils.find_resource for image
|
||||||
self.image = image_fakes.FakeImage.create_one_image()
|
self.image = image_fakes.FakeImage.create_one_image()
|
||||||
self.images_mock.get.return_value = self.image
|
self.get_image_mock.return_value = self.image
|
||||||
|
|
||||||
# Fake the rebuilt new server.
|
# Fake the rebuilt new server.
|
||||||
attrs = {
|
attrs = {
|
||||||
@ -3598,7 +3590,7 @@ class TestServerRebuild(TestServer):
|
|||||||
self.cmd.take_action(parsed_args)
|
self.cmd.take_action(parsed_args)
|
||||||
|
|
||||||
self.servers_mock.get.assert_called_with(self.server.id)
|
self.servers_mock.get.assert_called_with(self.server.id)
|
||||||
self.images_mock.get.assert_called_with(self.image.id)
|
self.get_image_mock.assert_called_with(self.image.id)
|
||||||
self.server.rebuild.assert_called_with(self.image, None)
|
self.server.rebuild.assert_called_with(self.image, None)
|
||||||
|
|
||||||
def test_rebuild_with_current_image_and_password(self):
|
def test_rebuild_with_current_image_and_password(self):
|
||||||
@ -3617,7 +3609,7 @@ class TestServerRebuild(TestServer):
|
|||||||
self.cmd.take_action(parsed_args)
|
self.cmd.take_action(parsed_args)
|
||||||
|
|
||||||
self.servers_mock.get.assert_called_with(self.server.id)
|
self.servers_mock.get.assert_called_with(self.server.id)
|
||||||
self.images_mock.get.assert_called_with(self.image.id)
|
self.get_image_mock.assert_called_with(self.image.id)
|
||||||
self.server.rebuild.assert_called_with(self.image, password)
|
self.server.rebuild.assert_called_with(self.image, password)
|
||||||
|
|
||||||
def test_rebuild_with_description_api_older(self):
|
def test_rebuild_with_description_api_older(self):
|
||||||
@ -3665,7 +3657,7 @@ class TestServerRebuild(TestServer):
|
|||||||
self.cmd.take_action(parsed_args)
|
self.cmd.take_action(parsed_args)
|
||||||
|
|
||||||
self.servers_mock.get.assert_called_with(self.server.id)
|
self.servers_mock.get.assert_called_with(self.server.id)
|
||||||
self.images_mock.get.assert_called_with(self.image.id)
|
self.get_image_mock.assert_called_with(self.image.id)
|
||||||
self.server.rebuild.assert_called_with(self.image, None,
|
self.server.rebuild.assert_called_with(self.image, None,
|
||||||
description=description)
|
description=description)
|
||||||
|
|
||||||
@ -3694,7 +3686,7 @@ class TestServerRebuild(TestServer):
|
|||||||
)
|
)
|
||||||
|
|
||||||
self.servers_mock.get.assert_called_with(self.server.id)
|
self.servers_mock.get.assert_called_with(self.server.id)
|
||||||
self.images_mock.get.assert_called_with(self.image.id)
|
self.get_image_mock.assert_called_with(self.image.id)
|
||||||
self.server.rebuild.assert_called_with(self.image, None)
|
self.server.rebuild.assert_called_with(self.image, None)
|
||||||
|
|
||||||
@mock.patch.object(common_utils, 'wait_for_status', return_value=False)
|
@mock.patch.object(common_utils, 'wait_for_status', return_value=False)
|
||||||
@ -3718,7 +3710,7 @@ class TestServerRebuild(TestServer):
|
|||||||
)
|
)
|
||||||
|
|
||||||
self.servers_mock.get.assert_called_with(self.server.id)
|
self.servers_mock.get.assert_called_with(self.server.id)
|
||||||
self.images_mock.get.assert_called_with(self.image.id)
|
self.get_image_mock.assert_called_with(self.image.id)
|
||||||
self.server.rebuild.assert_called_with(self.image, None)
|
self.server.rebuild.assert_called_with(self.image, None)
|
||||||
|
|
||||||
def test_rebuild_with_property(self):
|
def test_rebuild_with_property(self):
|
||||||
@ -3738,7 +3730,7 @@ class TestServerRebuild(TestServer):
|
|||||||
self.cmd.take_action(parsed_args)
|
self.cmd.take_action(parsed_args)
|
||||||
|
|
||||||
self.servers_mock.get.assert_called_with(self.server.id)
|
self.servers_mock.get.assert_called_with(self.server.id)
|
||||||
self.images_mock.get.assert_called_with(self.image.id)
|
self.get_image_mock.assert_called_with(self.image.id)
|
||||||
self.server.rebuild.assert_called_with(
|
self.server.rebuild.assert_called_with(
|
||||||
self.image, None, meta=expected_property)
|
self.image, None, meta=expected_property)
|
||||||
|
|
||||||
@ -3767,7 +3759,7 @@ class TestServerRebuild(TestServer):
|
|||||||
key_name=self.server.key_name,
|
key_name=self.server.key_name,
|
||||||
)
|
)
|
||||||
self.servers_mock.get.assert_called_with(self.server.id)
|
self.servers_mock.get.assert_called_with(self.server.id)
|
||||||
self.images_mock.get.assert_called_with(self.image.id)
|
self.get_image_mock.assert_called_with(self.image.id)
|
||||||
self.server.rebuild.assert_called_with(*args, **kwargs)
|
self.server.rebuild.assert_called_with(*args, **kwargs)
|
||||||
|
|
||||||
def test_rebuild_with_keypair_name_older_version(self):
|
def test_rebuild_with_keypair_name_older_version(self):
|
||||||
@ -3814,7 +3806,7 @@ class TestServerRebuild(TestServer):
|
|||||||
key_name=None,
|
key_name=None,
|
||||||
)
|
)
|
||||||
self.servers_mock.get.assert_called_with(self.server.id)
|
self.servers_mock.get.assert_called_with(self.server.id)
|
||||||
self.images_mock.get.assert_called_with(self.image.id)
|
self.get_image_mock.assert_called_with(self.image.id)
|
||||||
self.server.rebuild.assert_called_with(*args, **kwargs)
|
self.server.rebuild.assert_called_with(*args, **kwargs)
|
||||||
|
|
||||||
def test_rebuild_with_key_name_and_unset(self):
|
def test_rebuild_with_key_name_and_unset(self):
|
||||||
@ -3872,7 +3864,7 @@ class TestServerRescue(TestServer):
|
|||||||
|
|
||||||
# Return value for utils.find_resource for image
|
# Return value for utils.find_resource for image
|
||||||
self.image = image_fakes.FakeImage.create_one_image()
|
self.image = image_fakes.FakeImage.create_one_image()
|
||||||
self.images_mock.get.return_value = self.image
|
self.get_image_mock.return_value = self.image
|
||||||
|
|
||||||
new_server = compute_fakes.FakeServer.create_one_server()
|
new_server = compute_fakes.FakeServer.create_one_server()
|
||||||
attrs = {
|
attrs = {
|
||||||
@ -3913,7 +3905,7 @@ class TestServerRescue(TestServer):
|
|||||||
|
|
||||||
def test_rescue_with_new_image(self):
|
def test_rescue_with_new_image(self):
|
||||||
new_image = image_fakes.FakeImage.create_one_image()
|
new_image = image_fakes.FakeImage.create_one_image()
|
||||||
self.images_mock.get.return_value = new_image
|
self.find_image_mock.return_value = new_image
|
||||||
arglist = [
|
arglist = [
|
||||||
'--image', new_image.id,
|
'--image', new_image.id,
|
||||||
self.server.id,
|
self.server.id,
|
||||||
@ -3928,7 +3920,7 @@ class TestServerRescue(TestServer):
|
|||||||
self.cmd.take_action(parsed_args)
|
self.cmd.take_action(parsed_args)
|
||||||
|
|
||||||
self.servers_mock.get.assert_called_with(self.server.id)
|
self.servers_mock.get.assert_called_with(self.server.id)
|
||||||
self.images_mock.get.assert_called_with(new_image.id)
|
self.find_image_mock.assert_called_with(new_image.id)
|
||||||
self.server.rescue.assert_called_with(image=new_image, password=None)
|
self.server.rescue.assert_called_with(image=new_image, password=None)
|
||||||
|
|
||||||
def test_rescue_with_current_image_and_password(self):
|
def test_rescue_with_current_image_and_password(self):
|
||||||
@ -4679,7 +4671,7 @@ class TestServerShow(TestServer):
|
|||||||
|
|
||||||
# This is the return value for utils.find_resource()
|
# This is the return value for utils.find_resource()
|
||||||
self.servers_mock.get.return_value = self.server
|
self.servers_mock.get.return_value = self.server
|
||||||
self.images_mock.get.return_value = self.image
|
self.get_image_mock.return_value = self.image
|
||||||
self.flavors_mock.get.return_value = self.flavor
|
self.flavors_mock.get.return_value = self.flavor
|
||||||
|
|
||||||
# Get the command object to test
|
# Get the command object to test
|
||||||
@ -5140,7 +5132,8 @@ class TestServerGeneral(TestServer):
|
|||||||
'links': u'http://xxx.yyy.com',
|
'links': u'http://xxx.yyy.com',
|
||||||
}
|
}
|
||||||
_server = compute_fakes.FakeServer.create_one_server(attrs=server_info)
|
_server = compute_fakes.FakeServer.create_one_server(attrs=server_info)
|
||||||
find_resource.side_effect = [_server, _image, _flavor]
|
find_resource.side_effect = [_server, _flavor]
|
||||||
|
self.get_image_mock.return_value = _image
|
||||||
|
|
||||||
# Prepare result data.
|
# Prepare result data.
|
||||||
info = {
|
info = {
|
||||||
|
@ -32,8 +32,8 @@ class TestServerBackup(compute_fakes.TestComputev2):
|
|||||||
self.servers_mock.reset_mock()
|
self.servers_mock.reset_mock()
|
||||||
|
|
||||||
# Get a shortcut to the image client ImageManager Mock
|
# Get a shortcut to the image client ImageManager Mock
|
||||||
self.images_mock = self.app.client_manager.image.images
|
self.images_mock = self.app.client_manager.image
|
||||||
self.images_mock.reset_mock()
|
self.images_mock.find_image.reset_mock()
|
||||||
|
|
||||||
# Set object attributes to be tested. Could be overwritten in subclass.
|
# Set object attributes to be tested. Could be overwritten in subclass.
|
||||||
self.attrs = {}
|
self.attrs = {}
|
||||||
@ -60,15 +60,18 @@ class TestServerBackupCreate(TestServerBackup):
|
|||||||
|
|
||||||
# Just return whatever Image is testing with these days
|
# Just return whatever Image is testing with these days
|
||||||
def image_columns(self, image):
|
def image_columns(self, image):
|
||||||
columnlist = tuple(sorted(image.keys()))
|
# columnlist = tuple(sorted(image.keys()))
|
||||||
|
columnlist = (
|
||||||
|
'id', 'name', 'owner', 'protected', 'status', 'tags', 'visibility'
|
||||||
|
)
|
||||||
return columnlist
|
return columnlist
|
||||||
|
|
||||||
def image_data(self, image):
|
def image_data(self, image):
|
||||||
datalist = (
|
datalist = (
|
||||||
image['id'],
|
image['id'],
|
||||||
image['name'],
|
image['name'],
|
||||||
image['owner'],
|
image['owner_id'],
|
||||||
image['protected'],
|
image['is_protected'],
|
||||||
'active',
|
'active',
|
||||||
format_columns.ListColumn(image.get('tags')),
|
format_columns.ListColumn(image.get('tags')),
|
||||||
image['visibility'],
|
image['visibility'],
|
||||||
@ -102,7 +105,8 @@ class TestServerBackupCreate(TestServerBackup):
|
|||||||
count=count,
|
count=count,
|
||||||
)
|
)
|
||||||
|
|
||||||
self.images_mock.get = mock.Mock(side_effect=images)
|
# self.images_mock.get = mock.Mock(side_effect=images)
|
||||||
|
self.images_mock.find_image = mock.Mock(side_effect=images)
|
||||||
return images
|
return images
|
||||||
|
|
||||||
def test_server_backup_defaults(self):
|
def test_server_backup_defaults(self):
|
||||||
@ -174,16 +178,18 @@ class TestServerBackupCreate(TestServerBackup):
|
|||||||
@mock.patch.object(common_utils, 'wait_for_status', return_value=False)
|
@mock.patch.object(common_utils, 'wait_for_status', return_value=False)
|
||||||
def test_server_backup_wait_fail(self, mock_wait_for_status):
|
def test_server_backup_wait_fail(self, mock_wait_for_status):
|
||||||
servers = self.setup_servers_mock(count=1)
|
servers = self.setup_servers_mock(count=1)
|
||||||
images = image_fakes.FakeImage.create_images(
|
images = self.setup_images_mock(count=1, servers=servers)
|
||||||
attrs={
|
# images = image_fakes.FakeImage.create_images(
|
||||||
'name': servers[0].name,
|
# attrs={
|
||||||
'status': 'active',
|
# 'name': servers[0].name,
|
||||||
},
|
# 'status': 'active',
|
||||||
count=5,
|
# },
|
||||||
)
|
# count=1,
|
||||||
|
# )
|
||||||
self.images_mock.get = mock.Mock(
|
#
|
||||||
side_effect=images,
|
# self.images_mock.find_image.return_value = images[0]
|
||||||
|
self.images_mock.get_image = mock.Mock(
|
||||||
|
side_effect=images[0],
|
||||||
)
|
)
|
||||||
|
|
||||||
arglist = [
|
arglist = [
|
||||||
@ -215,7 +221,7 @@ class TestServerBackupCreate(TestServerBackup):
|
|||||||
)
|
)
|
||||||
|
|
||||||
mock_wait_for_status.assert_called_once_with(
|
mock_wait_for_status.assert_called_once_with(
|
||||||
self.images_mock.get,
|
self.images_mock.get_image,
|
||||||
images[0].id,
|
images[0].id,
|
||||||
callback=mock.ANY
|
callback=mock.ANY
|
||||||
)
|
)
|
||||||
@ -223,16 +229,10 @@ class TestServerBackupCreate(TestServerBackup):
|
|||||||
@mock.patch.object(common_utils, 'wait_for_status', return_value=True)
|
@mock.patch.object(common_utils, 'wait_for_status', return_value=True)
|
||||||
def test_server_backup_wait_ok(self, mock_wait_for_status):
|
def test_server_backup_wait_ok(self, mock_wait_for_status):
|
||||||
servers = self.setup_servers_mock(count=1)
|
servers = self.setup_servers_mock(count=1)
|
||||||
images = image_fakes.FakeImage.create_images(
|
images = self.setup_images_mock(count=1, servers=servers)
|
||||||
attrs={
|
|
||||||
'name': servers[0].name,
|
|
||||||
'status': 'active',
|
|
||||||
},
|
|
||||||
count=5,
|
|
||||||
)
|
|
||||||
|
|
||||||
self.images_mock.get = mock.Mock(
|
self.images_mock.get_image = mock.Mock(
|
||||||
side_effect=images,
|
side_effect=images[0],
|
||||||
)
|
)
|
||||||
|
|
||||||
arglist = [
|
arglist = [
|
||||||
@ -263,7 +263,7 @@ class TestServerBackupCreate(TestServerBackup):
|
|||||||
)
|
)
|
||||||
|
|
||||||
mock_wait_for_status.assert_called_once_with(
|
mock_wait_for_status.assert_called_once_with(
|
||||||
self.images_mock.get,
|
self.images_mock.get_image,
|
||||||
images[0].id,
|
images[0].id,
|
||||||
callback=mock.ANY
|
callback=mock.ANY
|
||||||
)
|
)
|
||||||
|
@ -31,8 +31,8 @@ class TestServerImage(compute_fakes.TestComputev2):
|
|||||||
self.servers_mock.reset_mock()
|
self.servers_mock.reset_mock()
|
||||||
|
|
||||||
# Get a shortcut to the image client ImageManager Mock
|
# Get a shortcut to the image client ImageManager Mock
|
||||||
self.images_mock = self.app.client_manager.image.images
|
self.images_mock = self.app.client_manager.image
|
||||||
self.images_mock.reset_mock()
|
self.images_mock.find_image.reset_mock()
|
||||||
|
|
||||||
# Set object attributes to be tested. Could be overwritten in subclass.
|
# Set object attributes to be tested. Could be overwritten in subclass.
|
||||||
self.attrs = {}
|
self.attrs = {}
|
||||||
@ -58,15 +58,18 @@ class TestServerImage(compute_fakes.TestComputev2):
|
|||||||
class TestServerImageCreate(TestServerImage):
|
class TestServerImageCreate(TestServerImage):
|
||||||
|
|
||||||
def image_columns(self, image):
|
def image_columns(self, image):
|
||||||
columnlist = tuple(sorted(image.keys()))
|
# columnlist = tuple(sorted(image.keys()))
|
||||||
|
columnlist = (
|
||||||
|
'id', 'name', 'owner', 'protected', 'status', 'tags', 'visibility'
|
||||||
|
)
|
||||||
return columnlist
|
return columnlist
|
||||||
|
|
||||||
def image_data(self, image):
|
def image_data(self, image):
|
||||||
datalist = (
|
datalist = (
|
||||||
image['id'],
|
image['id'],
|
||||||
image['name'],
|
image['name'],
|
||||||
image['owner'],
|
image['owner_id'],
|
||||||
image['protected'],
|
image['is_protected'],
|
||||||
'active',
|
'active',
|
||||||
format_columns.ListColumn(image.get('tags')),
|
format_columns.ListColumn(image.get('tags')),
|
||||||
image['visibility'],
|
image['visibility'],
|
||||||
@ -100,7 +103,7 @@ class TestServerImageCreate(TestServerImage):
|
|||||||
count=count,
|
count=count,
|
||||||
)
|
)
|
||||||
|
|
||||||
self.images_mock.get = mock.Mock(side_effect=images)
|
self.images_mock.find_image = mock.Mock(side_effect=images)
|
||||||
self.servers_mock.create_image = mock.Mock(
|
self.servers_mock.create_image = mock.Mock(
|
||||||
return_value=images[0].id,
|
return_value=images[0].id,
|
||||||
)
|
)
|
||||||
@ -188,7 +191,7 @@ class TestServerImageCreate(TestServerImage):
|
|||||||
)
|
)
|
||||||
|
|
||||||
mock_wait_for_status.assert_called_once_with(
|
mock_wait_for_status.assert_called_once_with(
|
||||||
self.images_mock.get,
|
self.images_mock.get_image,
|
||||||
images[0].id,
|
images[0].id,
|
||||||
callback=mock.ANY
|
callback=mock.ANY
|
||||||
)
|
)
|
||||||
@ -220,7 +223,7 @@ class TestServerImageCreate(TestServerImage):
|
|||||||
)
|
)
|
||||||
|
|
||||||
mock_wait_for_status.assert_called_once_with(
|
mock_wait_for_status.assert_called_once_with(
|
||||||
self.images_mock.get,
|
self.images_mock.get_image,
|
||||||
images[0].id,
|
images[0].id,
|
||||||
callback=mock.ANY
|
callback=mock.ANY
|
||||||
)
|
)
|
||||||
|
@ -18,9 +18,9 @@ import random
|
|||||||
from unittest import mock
|
from unittest import mock
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
from glanceclient.v2 import schemas
|
from openstack.image.v2 import image
|
||||||
|
from openstack.image.v2 import member
|
||||||
from osc_lib.cli import format_columns
|
from osc_lib.cli import format_columns
|
||||||
import warlock
|
|
||||||
|
|
||||||
from openstackclient.tests.unit import fakes
|
from openstackclient.tests.unit import fakes
|
||||||
from openstackclient.tests.unit.identity.v3 import fakes as identity_fakes
|
from openstackclient.tests.unit.identity.v3 import fakes as identity_fakes
|
||||||
@ -154,6 +154,12 @@ class FakeImagev2Client(object):
|
|||||||
self.image_members.resource_class = fakes.FakeResource(None, {})
|
self.image_members.resource_class = fakes.FakeResource(None, {})
|
||||||
self.image_tags = mock.Mock()
|
self.image_tags = mock.Mock()
|
||||||
self.image_tags.resource_class = fakes.FakeResource(None, {})
|
self.image_tags.resource_class = fakes.FakeResource(None, {})
|
||||||
|
|
||||||
|
self.find_image = mock.Mock()
|
||||||
|
self.find_image.resource_class = fakes.FakeResource(None, {})
|
||||||
|
|
||||||
|
self.get_image = mock.Mock()
|
||||||
|
self.get_image.resource_class = fakes.FakeResource(None, {})
|
||||||
self.auth_token = kwargs['token']
|
self.auth_token = kwargs['token']
|
||||||
self.management_url = kwargs['endpoint']
|
self.management_url = kwargs['endpoint']
|
||||||
self.version = 2.0
|
self.version = 2.0
|
||||||
@ -197,8 +203,8 @@ class FakeImage(object):
|
|||||||
image_info = {
|
image_info = {
|
||||||
'id': str(uuid.uuid4()),
|
'id': str(uuid.uuid4()),
|
||||||
'name': 'image-name' + uuid.uuid4().hex,
|
'name': 'image-name' + uuid.uuid4().hex,
|
||||||
'owner': 'image-owner' + uuid.uuid4().hex,
|
'owner_id': 'image-owner' + uuid.uuid4().hex,
|
||||||
'protected': bool(random.choice([0, 1])),
|
'is_protected': bool(random.choice([0, 1])),
|
||||||
'visibility': random.choice(['public', 'private']),
|
'visibility': random.choice(['public', 'private']),
|
||||||
'tags': [uuid.uuid4().hex for r in range(2)],
|
'tags': [uuid.uuid4().hex for r in range(2)],
|
||||||
}
|
}
|
||||||
@ -206,13 +212,7 @@ class FakeImage(object):
|
|||||||
# Overwrite default attributes if there are some attributes set
|
# Overwrite default attributes if there are some attributes set
|
||||||
image_info.update(attrs)
|
image_info.update(attrs)
|
||||||
|
|
||||||
# Set up the schema
|
return image.Image(**image_info)
|
||||||
model = warlock.model_factory(
|
|
||||||
IMAGE_schema,
|
|
||||||
schemas.SchemaBasedModel,
|
|
||||||
)
|
|
||||||
|
|
||||||
return model(**image_info)
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def create_images(attrs=None, count=2):
|
def create_images(attrs=None, count=2):
|
||||||
@ -307,6 +307,8 @@ class FakeImage(object):
|
|||||||
# Overwrite default attributes if there are some attributes set
|
# Overwrite default attributes if there are some attributes set
|
||||||
image_member_info.update(attrs)
|
image_member_info.update(attrs)
|
||||||
|
|
||||||
|
return member.Member(**image_member_info)
|
||||||
|
|
||||||
image_member = fakes.FakeModel(
|
image_member = fakes.FakeModel(
|
||||||
copy.deepcopy(image_member_info))
|
copy.deepcopy(image_member_info))
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -41,8 +41,8 @@ class TestVolume(volume_fakes.TestVolume):
|
|||||||
self.users_mock = self.app.client_manager.identity.users
|
self.users_mock = self.app.client_manager.identity.users
|
||||||
self.users_mock.reset_mock()
|
self.users_mock.reset_mock()
|
||||||
|
|
||||||
self.images_mock = self.app.client_manager.image.images
|
self.find_image_mock = self.app.client_manager.image.find_image
|
||||||
self.images_mock.reset_mock()
|
self.find_image_mock.reset_mock()
|
||||||
|
|
||||||
self.snapshots_mock = self.app.client_manager.volume.volume_snapshots
|
self.snapshots_mock = self.app.client_manager.volume.volume_snapshots
|
||||||
self.snapshots_mock.reset_mock()
|
self.snapshots_mock.reset_mock()
|
||||||
@ -222,7 +222,7 @@ class TestVolumeCreate(TestVolume):
|
|||||||
|
|
||||||
def test_volume_create_image_id(self):
|
def test_volume_create_image_id(self):
|
||||||
image = image_fakes.FakeImage.create_one_image()
|
image = image_fakes.FakeImage.create_one_image()
|
||||||
self.images_mock.get.return_value = image
|
self.find_image_mock.return_value = image
|
||||||
|
|
||||||
arglist = [
|
arglist = [
|
||||||
'--image', image.id,
|
'--image', image.id,
|
||||||
@ -260,7 +260,7 @@ class TestVolumeCreate(TestVolume):
|
|||||||
|
|
||||||
def test_volume_create_image_name(self):
|
def test_volume_create_image_name(self):
|
||||||
image = image_fakes.FakeImage.create_one_image()
|
image = image_fakes.FakeImage.create_one_image()
|
||||||
self.images_mock.get.return_value = image
|
self.find_image_mock.return_value = image
|
||||||
|
|
||||||
arglist = [
|
arglist = [
|
||||||
'--image', image.name,
|
'--image', image.name,
|
||||||
|
@ -193,9 +193,8 @@ class CreateVolume(command.ShowOne):
|
|||||||
|
|
||||||
image = None
|
image = None
|
||||||
if parsed_args.image:
|
if parsed_args.image:
|
||||||
image = utils.find_resource(
|
image = image_client.find_image(parsed_args.image,
|
||||||
image_client.images,
|
ignore_missing=False).id
|
||||||
parsed_args.image).id
|
|
||||||
|
|
||||||
size = parsed_args.size
|
size = parsed_args.size
|
||||||
|
|
||||||
|
@ -0,0 +1,4 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- |
|
||||||
|
Image service for v2 is switched from using glanceclient to OpenStackSDK.
|
@ -6,8 +6,7 @@ six>=1.10.0 # MIT
|
|||||||
|
|
||||||
Babel!=2.4.0,>=2.3.4 # BSD
|
Babel!=2.4.0,>=2.3.4 # BSD
|
||||||
cliff!=2.9.0,>=2.8.0 # Apache-2.0
|
cliff!=2.9.0,>=2.8.0 # Apache-2.0
|
||||||
keystoneauth1>=3.14.0 # Apache-2.0
|
openstacksdk>=0.36.0 # Apache-2.0
|
||||||
openstacksdk>=0.17.0 # Apache-2.0
|
|
||||||
osc-lib>=2.0.0 # Apache-2.0
|
osc-lib>=2.0.0 # Apache-2.0
|
||||||
oslo.i18n>=3.15.3 # Apache-2.0
|
oslo.i18n>=3.15.3 # Apache-2.0
|
||||||
oslo.utils>=3.33.0 # Apache-2.0
|
oslo.utils>=3.33.0 # Apache-2.0
|
||||||
|
Loading…
Reference in New Issue
Block a user