Skip to content

Commit b9a3181

Browse files
Jenkinsopenstack-gerrit
authored andcommitted
Merge "Move server image create command to its own resource file."
2 parents ed38aa6 + eef2054 commit b9a3181

7 files changed

Lines changed: 346 additions & 224 deletions

File tree

doc/source/command-objects/server-image.rst

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ Compute v2
1010
server image create
1111
-------------------
1212

13-
Create a new disk image from a running server
13+
Create a new server disk image from an existing server
1414

1515
.. program:: server image create
1616
.. code:: bash
@@ -22,12 +22,12 @@ Create a new disk image from a running server
2222
2323
.. option:: --name <image-name>
2424

25-
Name of new image (default is server name)
25+
Name of new disk image (default: server name)
2626

2727
.. option:: --wait
2828

29-
Wait for image create to complete
29+
Wait for operation to complete
3030

3131
.. describe:: <server>
3232

33-
Server (name or ID)
33+
Server to create image (name or ID)

functional/tests/common/test_help.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,12 @@ class HelpTests(test.TestCase):
1919
SERVER_COMMANDS = [
2020
('server add security group', 'Add security group to server'),
2121
('server add volume', 'Add volume to server'),
22+
('server backup create', 'Create a server backup image'),
2223
('server create', 'Create a new server'),
2324
('server delete', 'Delete server(s)'),
2425
('server dump create', 'Create a dump file in server(s)'),
2526
('server image create',
26-
'Create a new disk image from a running server'),
27+
'Create a new server disk image from an existing server'),
2728
('server list', 'List servers'),
2829
('server lock',
2930
'Lock server(s). '

openstackclient/compute/v2/server.py

Lines changed: 0 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -164,23 +164,6 @@ def _prep_server_detail(compute_client, server):
164164
return info
165165

166166

167-
def _prep_image_detail(image_client, image_id):
168-
"""Prepare the detailed image dict for printing
169-
170-
:param image_client: an image client instance
171-
:param image_id: id of image created
172-
:rtype: a dict of image details
173-
"""
174-
175-
info = utils.find_resource(
176-
image_client.images,
177-
image_id,
178-
)
179-
# Glance client V2 doesn't have _info attribute
180-
# The following condition deals with it.
181-
return getattr(info, "_info", info)
182-
183-
184167
def _show_progress(progress):
185168
if progress:
186169
sys.stdout.write('\rProgress: %s' % progress)
@@ -597,63 +580,6 @@ def take_action(self, parsed_args):
597580
).trigger_crash_dump()
598581

599582

600-
class CreateServerImage(command.ShowOne):
601-
"""Create a new disk image from a running server"""
602-
603-
def get_parser(self, prog_name):
604-
parser = super(CreateServerImage, self).get_parser(prog_name)
605-
parser.add_argument(
606-
'server',
607-
metavar='<server>',
608-
help=_('Server (name or ID)'),
609-
)
610-
parser.add_argument(
611-
'--name',
612-
metavar='<image-name>',
613-
help=_('Name of new image (default is server name)'),
614-
)
615-
parser.add_argument(
616-
'--wait',
617-
action='store_true',
618-
help=_('Wait for image create to complete'),
619-
)
620-
return parser
621-
622-
def take_action(self, parsed_args):
623-
compute_client = self.app.client_manager.compute
624-
image_client = self.app.client_manager.image
625-
server = utils.find_resource(
626-
compute_client.servers,
627-
parsed_args.server,
628-
)
629-
if parsed_args.name:
630-
name = parsed_args.name
631-
else:
632-
name = server.name
633-
634-
image_id = compute_client.servers.create_image(
635-
server,
636-
name,
637-
)
638-
639-
if parsed_args.wait:
640-
if utils.wait_for_status(
641-
image_client.images.get,
642-
image_id,
643-
callback=_show_progress,
644-
):
645-
sys.stdout.write('\n')
646-
else:
647-
self.log.error(_('Error creating snapshot of server: %s'),
648-
parsed_args.server)
649-
sys.stdout.write(_('Error creating server snapshot\n'))
650-
raise SystemExit
651-
652-
image = _prep_image_detail(image_client, image_id)
653-
654-
return zip(*sorted(six.iteritems(image)))
655-
656-
657583
class DeleteServer(command.Command):
658584
"""Delete server(s)"""
659585

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
# Copyright 2012-2013 OpenStack Foundation
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License"); you may
4+
# not use this file except in compliance with the License. You may obtain
5+
# a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12+
# License for the specific language governing permissions and limitations
13+
# under the License.
14+
#
15+
16+
"""Compute v2 Server action implementations"""
17+
18+
import sys
19+
20+
from oslo_utils import importutils
21+
import six
22+
23+
from openstackclient.common import command
24+
from openstackclient.common import exceptions
25+
from openstackclient.common import utils
26+
from openstackclient.i18n import _
27+
28+
29+
def _show_progress(progress):
30+
if progress:
31+
sys.stdout.write('\rProgress: %s' % progress)
32+
sys.stdout.flush()
33+
34+
35+
class CreateServerImage(command.ShowOne):
36+
"""Create a new server disk image from an existing server"""
37+
38+
IMAGE_API_VERSIONS = {
39+
"1": "openstackclient.image.v1.image",
40+
"2": "openstackclient.image.v2.image",
41+
}
42+
43+
def get_parser(self, prog_name):
44+
parser = super(CreateServerImage, self).get_parser(prog_name)
45+
parser.add_argument(
46+
'server',
47+
metavar='<server>',
48+
help=_('Server to create image (name or ID)'),
49+
)
50+
parser.add_argument(
51+
'--name',
52+
metavar='<image-name>',
53+
help=_('Name of new disk image (default: server name)'),
54+
)
55+
parser.add_argument(
56+
'--wait',
57+
action='store_true',
58+
help=_('Wait for operation to complete'),
59+
)
60+
return parser
61+
62+
def take_action(self, parsed_args):
63+
compute_client = self.app.client_manager.compute
64+
65+
server = utils.find_resource(
66+
compute_client.servers,
67+
parsed_args.server,
68+
)
69+
if parsed_args.name:
70+
image_name = parsed_args.name
71+
else:
72+
image_name = server.name
73+
74+
image_id = compute_client.servers.create_image(
75+
server.id,
76+
image_name,
77+
)
78+
79+
image_client = self.app.client_manager.image
80+
image = utils.find_resource(
81+
image_client.images,
82+
image_id,
83+
)
84+
85+
if parsed_args.wait:
86+
if utils.wait_for_status(
87+
image_client.images.get,
88+
image_id,
89+
callback=_show_progress,
90+
):
91+
sys.stdout.write('\n')
92+
else:
93+
self.log.error(
94+
_('Error creating server image: %s') %
95+
parsed_args.server,
96+
)
97+
raise exceptions.CommandError
98+
99+
if self.app.client_manager._api_version['image'] == '1':
100+
info = {}
101+
info.update(image._info)
102+
info['properties'] = utils.format_dict(info.get('properties', {}))
103+
else:
104+
# Get the right image module to format the output
105+
image_module = importutils.import_module(
106+
self.IMAGE_API_VERSIONS[
107+
self.app.client_manager._api_version['image']
108+
]
109+
)
110+
info = image_module._format_image(image)
111+
return zip(*sorted(six.iteritems(info)))

openstackclient/tests/compute/v2/test_server.py

Lines changed: 0 additions & 144 deletions
Original file line numberDiff line numberDiff line change
@@ -511,150 +511,6 @@ def test_server_dump_multi_servers(self):
511511
self.run_method_with_servers('trigger_crash_dump', 3)
512512

513513

514-
class TestServerImageCreate(TestServer):
515-
516-
columns = (
517-
'id',
518-
'name',
519-
'owner',
520-
'protected',
521-
'tags',
522-
'visibility',
523-
)
524-
525-
def datalist(self):
526-
datalist = (
527-
self.image.id,
528-
self.image.name,
529-
self.image.owner,
530-
self.image.protected,
531-
self.image.tags,
532-
self.image.visibility,
533-
)
534-
return datalist
535-
536-
def setUp(self):
537-
super(TestServerImageCreate, self).setUp()
538-
539-
self.server = compute_fakes.FakeServer.create_one_server()
540-
541-
# This is the return value for utils.find_resource()
542-
self.servers_mock.get.return_value = self.server
543-
544-
self.image = image_fakes.FakeImage.create_one_image()
545-
self.images_mock.get.return_value = self.image
546-
self.servers_mock.create_image.return_value = self.image.id
547-
548-
# Get the command object to test
549-
self.cmd = server.CreateServerImage(self.app, None)
550-
551-
def test_server_image_create_no_options(self):
552-
arglist = [
553-
self.server.id,
554-
]
555-
verifylist = [
556-
('server', self.server.id),
557-
]
558-
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
559-
560-
# In base command class ShowOne in cliff, abstract method take_action()
561-
# returns a two-part tuple with a tuple of column names and a tuple of
562-
# data to be shown.
563-
columns, data = self.cmd.take_action(parsed_args)
564-
565-
# ServerManager.create_image(server, image_name, metadata=)
566-
self.servers_mock.create_image.assert_called_with(
567-
self.servers_mock.get.return_value,
568-
self.server.name,
569-
)
570-
571-
self.assertEqual(self.columns, columns)
572-
self.assertEqual(self.datalist(), data)
573-
574-
def test_server_image_create_name(self):
575-
arglist = [
576-
'--name', 'img-nam',
577-
self.server.id,
578-
]
579-
verifylist = [
580-
('name', 'img-nam'),
581-
('server', self.server.id),
582-
]
583-
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
584-
585-
# In base command class ShowOne in cliff, abstract method take_action()
586-
# returns a two-part tuple with a tuple of column names and a tuple of
587-
# data to be shown.
588-
columns, data = self.cmd.take_action(parsed_args)
589-
590-
# ServerManager.create_image(server, image_name, metadata=)
591-
self.servers_mock.create_image.assert_called_with(
592-
self.servers_mock.get.return_value,
593-
'img-nam',
594-
)
595-
596-
self.assertEqual(self.columns, columns)
597-
self.assertEqual(self.datalist(), data)
598-
599-
@mock.patch.object(common_utils, 'wait_for_status', return_value=False)
600-
def test_server_create_image_with_wait_fails(self, mock_wait_for_status):
601-
arglist = [
602-
'--wait',
603-
self.server.id,
604-
]
605-
verifylist = [
606-
('wait', True),
607-
('server', self.server.id),
608-
]
609-
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
610-
611-
self.assertRaises(SystemExit, self.cmd.take_action, parsed_args)
612-
613-
mock_wait_for_status.assert_called_once_with(
614-
self.images_mock.get,
615-
self.image.id,
616-
callback=server._show_progress
617-
)
618-
619-
# ServerManager.create_image(server, image_name, metadata=)
620-
self.servers_mock.create_image.assert_called_with(
621-
self.servers_mock.get.return_value,
622-
self.server.name,
623-
)
624-
625-
@mock.patch.object(common_utils, 'wait_for_status', return_value=True)
626-
def test_server_create_image_with_wait_ok(self, mock_wait_for_status):
627-
arglist = [
628-
'--wait',
629-
self.server.id,
630-
]
631-
verifylist = [
632-
('wait', True),
633-
('server', self.server.id),
634-
]
635-
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
636-
637-
# In base command class ShowOne in cliff, abstract method take_action()
638-
# returns a two-part tuple with a tuple of column names and a tuple of
639-
# data to be shown.
640-
columns, data = self.cmd.take_action(parsed_args)
641-
642-
# ServerManager.create_image(server, image_name, metadata=)
643-
self.servers_mock.create_image.assert_called_with(
644-
self.servers_mock.get.return_value,
645-
self.server.name,
646-
)
647-
648-
mock_wait_for_status.assert_called_once_with(
649-
self.images_mock.get,
650-
self.image.id,
651-
callback=server._show_progress
652-
)
653-
654-
self.assertEqual(self.columns, columns)
655-
self.assertEqual(self.datalist(), data)
656-
657-
658514
class TestServerList(TestServer):
659515

660516
# Columns to be listed up.

0 commit comments

Comments
 (0)