Add server image create command
Translation of 'nova image-create', with tests! Change-Id: I8a833aeff6f291e4774063ed235876eb2ba9c13c
This commit is contained in:
parent
6460f1eb35
commit
200ed62054
@ -384,6 +384,73 @@ class CreateServer(show.ShowOne):
|
|||||||
return zip(*sorted(six.iteritems(details)))
|
return zip(*sorted(six.iteritems(details)))
|
||||||
|
|
||||||
|
|
||||||
|
class CreateServerImage(show.ShowOne):
|
||||||
|
"""Create a new disk image from a running server"""
|
||||||
|
|
||||||
|
log = logging.getLogger(__name__ + '.CreateServerImage')
|
||||||
|
|
||||||
|
def get_parser(self, prog_name):
|
||||||
|
parser = super(CreateServerImage, self).get_parser(prog_name)
|
||||||
|
parser.add_argument(
|
||||||
|
'server',
|
||||||
|
metavar='<server',
|
||||||
|
help='Server (name or ID)',
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'--name',
|
||||||
|
metavar='<image-name>',
|
||||||
|
help='Name of new image (default is server name)',
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'--wait',
|
||||||
|
action='store_true',
|
||||||
|
help='Wait for image create to complete',
|
||||||
|
)
|
||||||
|
return parser
|
||||||
|
|
||||||
|
def take_action(self, parsed_args):
|
||||||
|
self.log.debug('take_action(%s)' % parsed_args)
|
||||||
|
compute_client = self.app.client_manager.compute
|
||||||
|
image_client = self.app.client_manager.image
|
||||||
|
server = utils.find_resource(
|
||||||
|
compute_client.servers,
|
||||||
|
parsed_args.server,
|
||||||
|
)
|
||||||
|
if parsed_args.name:
|
||||||
|
name = parsed_args.name
|
||||||
|
else:
|
||||||
|
name = server.name
|
||||||
|
|
||||||
|
image = compute_client.servers.create_image(
|
||||||
|
server,
|
||||||
|
name,
|
||||||
|
)
|
||||||
|
|
||||||
|
if parsed_args.wait:
|
||||||
|
if utils.wait_for_status(
|
||||||
|
image_client.images.get,
|
||||||
|
image,
|
||||||
|
callback=_show_progress,
|
||||||
|
):
|
||||||
|
sys.stdout.write('\n')
|
||||||
|
else:
|
||||||
|
self.log.error(
|
||||||
|
'Error creating server snapshot: %s' %
|
||||||
|
parsed_args.image_name,
|
||||||
|
)
|
||||||
|
sys.stdout.write('\nError creating server snapshot')
|
||||||
|
raise SystemExit
|
||||||
|
|
||||||
|
image = utils.find_resource(
|
||||||
|
image_client.images,
|
||||||
|
image.id,
|
||||||
|
)
|
||||||
|
|
||||||
|
info = {}
|
||||||
|
info.update(image._info)
|
||||||
|
return zip(*sorted(six.iteritems(info)))
|
||||||
|
|
||||||
|
|
||||||
class DeleteServer(command.Command):
|
class DeleteServer(command.Command):
|
||||||
"""Delete server command"""
|
"""Delete server command"""
|
||||||
|
|
||||||
|
@ -16,16 +16,10 @@
|
|||||||
import mock
|
import mock
|
||||||
|
|
||||||
from openstackclient.tests import fakes
|
from openstackclient.tests import fakes
|
||||||
|
from openstackclient.tests.image.v2 import fakes as image_fakes
|
||||||
from openstackclient.tests import utils
|
from openstackclient.tests import utils
|
||||||
|
|
||||||
|
|
||||||
image_id = 'im1'
|
|
||||||
|
|
||||||
IMAGE = {
|
|
||||||
'id': image_id,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
server_id = 'serv1'
|
server_id = 'serv1'
|
||||||
server_name = 'waiter'
|
server_name = 'waiter'
|
||||||
|
|
||||||
@ -53,3 +47,8 @@ class TestComputev2(utils.TestCommand):
|
|||||||
endpoint=fakes.AUTH_URL,
|
endpoint=fakes.AUTH_URL,
|
||||||
token=fakes.AUTH_TOKEN,
|
token=fakes.AUTH_TOKEN,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
self.app.client_manager.image = image_fakes.FakeImagev2Client(
|
||||||
|
endpoint=fakes.AUTH_URL,
|
||||||
|
token=fakes.AUTH_TOKEN,
|
||||||
|
)
|
||||||
|
@ -18,6 +18,7 @@ import copy
|
|||||||
from openstackclient.compute.v2 import server
|
from openstackclient.compute.v2 import server
|
||||||
from openstackclient.tests.compute.v2 import fakes as compute_fakes
|
from openstackclient.tests.compute.v2 import fakes as compute_fakes
|
||||||
from openstackclient.tests import fakes
|
from openstackclient.tests import fakes
|
||||||
|
from openstackclient.tests.image.v2 import fakes as image_fakes
|
||||||
|
|
||||||
|
|
||||||
class TestServer(compute_fakes.TestComputev2):
|
class TestServer(compute_fakes.TestComputev2):
|
||||||
@ -29,6 +30,10 @@ class TestServer(compute_fakes.TestComputev2):
|
|||||||
self.servers_mock = self.app.client_manager.compute.servers
|
self.servers_mock = self.app.client_manager.compute.servers
|
||||||
self.servers_mock.reset_mock()
|
self.servers_mock.reset_mock()
|
||||||
|
|
||||||
|
# Get a shortcut to the ImageManager Mock
|
||||||
|
self.images_mock = self.app.client_manager.image.images
|
||||||
|
self.images_mock.reset_mock()
|
||||||
|
|
||||||
|
|
||||||
class TestServerDelete(TestServer):
|
class TestServerDelete(TestServer):
|
||||||
|
|
||||||
@ -61,3 +66,89 @@ class TestServerDelete(TestServer):
|
|||||||
self.servers_mock.delete.assert_called_with(
|
self.servers_mock.delete.assert_called_with(
|
||||||
compute_fakes.server_id,
|
compute_fakes.server_id,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class TestServerImageCreate(TestServer):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(TestServerImageCreate, self).setUp()
|
||||||
|
|
||||||
|
# This is the return value for utils.find_resource()
|
||||||
|
self.servers_mock.get.return_value = fakes.FakeResource(
|
||||||
|
None,
|
||||||
|
copy.deepcopy(compute_fakes.SERVER),
|
||||||
|
loaded=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
self.servers_mock.create_image.return_value = fakes.FakeResource(
|
||||||
|
None,
|
||||||
|
copy.deepcopy(image_fakes.IMAGE),
|
||||||
|
loaded=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
self.images_mock.get.return_value = fakes.FakeResource(
|
||||||
|
None,
|
||||||
|
copy.deepcopy(image_fakes.IMAGE),
|
||||||
|
loaded=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Get the command object to test
|
||||||
|
self.cmd = server.CreateServerImage(self.app, None)
|
||||||
|
|
||||||
|
def test_server_image_create_no_options(self):
|
||||||
|
arglist = [
|
||||||
|
compute_fakes.server_id,
|
||||||
|
]
|
||||||
|
verifylist = [
|
||||||
|
('server', compute_fakes.server_id),
|
||||||
|
]
|
||||||
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
|
# DisplayCommandBase.take_action() returns two tuples
|
||||||
|
columns, data = self.cmd.take_action(parsed_args)
|
||||||
|
|
||||||
|
# ServerManager.create_image(server, image_name, metadata=)
|
||||||
|
self.servers_mock.create_image.assert_called_with(
|
||||||
|
self.servers_mock.get.return_value,
|
||||||
|
compute_fakes.server_name,
|
||||||
|
)
|
||||||
|
|
||||||
|
collist = ('id', 'is_public', 'name', 'owner')
|
||||||
|
self.assertEqual(columns, collist)
|
||||||
|
datalist = (
|
||||||
|
image_fakes.image_id,
|
||||||
|
False,
|
||||||
|
image_fakes.image_name,
|
||||||
|
image_fakes.image_owner,
|
||||||
|
)
|
||||||
|
self.assertEqual(data, datalist)
|
||||||
|
|
||||||
|
def test_server_image_create_name(self):
|
||||||
|
arglist = [
|
||||||
|
'--name', 'img-nam',
|
||||||
|
compute_fakes.server_id,
|
||||||
|
]
|
||||||
|
verifylist = [
|
||||||
|
('name', 'img-nam'),
|
||||||
|
('server', compute_fakes.server_id),
|
||||||
|
]
|
||||||
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
|
# DisplayCommandBase.take_action() returns two tuples
|
||||||
|
columns, data = self.cmd.take_action(parsed_args)
|
||||||
|
|
||||||
|
# ServerManager.create_image(server, image_name, metadata=)
|
||||||
|
self.servers_mock.create_image.assert_called_with(
|
||||||
|
self.servers_mock.get.return_value,
|
||||||
|
'img-nam',
|
||||||
|
)
|
||||||
|
|
||||||
|
collist = ('id', 'is_public', 'name', 'owner')
|
||||||
|
self.assertEqual(columns, collist)
|
||||||
|
datalist = (
|
||||||
|
image_fakes.image_id,
|
||||||
|
False,
|
||||||
|
image_fakes.image_name,
|
||||||
|
image_fakes.image_owner,
|
||||||
|
)
|
||||||
|
self.assertEqual(data, datalist)
|
||||||
|
@ -21,10 +21,13 @@ from openstackclient.tests import utils
|
|||||||
|
|
||||||
image_id = 'im1'
|
image_id = 'im1'
|
||||||
image_name = 'graven'
|
image_name = 'graven'
|
||||||
|
image_owner = 'baal'
|
||||||
|
|
||||||
IMAGE = {
|
IMAGE = {
|
||||||
'id': image_id,
|
'id': image_id,
|
||||||
'name': image_name
|
'name': image_name,
|
||||||
|
'is_public': False,
|
||||||
|
'owner': image_owner,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -94,6 +94,7 @@ openstack.compute.v2 =
|
|||||||
server_add_volume = openstackclient.compute.v2.server:AddServerVolume
|
server_add_volume = openstackclient.compute.v2.server:AddServerVolume
|
||||||
server_create = openstackclient.compute.v2.server:CreateServer
|
server_create = openstackclient.compute.v2.server:CreateServer
|
||||||
server_delete = openstackclient.compute.v2.server:DeleteServer
|
server_delete = openstackclient.compute.v2.server:DeleteServer
|
||||||
|
server_image_create = openstackclient.compute.v2.server:CreateServerImage
|
||||||
server_list = openstackclient.compute.v2.server:ListServer
|
server_list = openstackclient.compute.v2.server:ListServer
|
||||||
server_lock = openstackclient.compute.v2.server:LockServer
|
server_lock = openstackclient.compute.v2.server:LockServer
|
||||||
server_migrate = openstackclient.compute.v2.server:MigrateServer
|
server_migrate = openstackclient.compute.v2.server:MigrateServer
|
||||||
|
Loading…
x
Reference in New Issue
Block a user