Merge "Add server image create command"
This commit is contained in:
commit
d45187a0c1
@ -384,6 +384,73 @@ class CreateServer(show.ShowOne):
|
||||
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):
|
||||
"""Delete server command"""
|
||||
|
||||
|
@ -16,16 +16,10 @@
|
||||
import mock
|
||||
|
||||
from openstackclient.tests import fakes
|
||||
from openstackclient.tests.image.v2 import fakes as image_fakes
|
||||
from openstackclient.tests import utils
|
||||
|
||||
|
||||
image_id = 'im1'
|
||||
|
||||
IMAGE = {
|
||||
'id': image_id,
|
||||
}
|
||||
|
||||
|
||||
server_id = 'serv1'
|
||||
server_name = 'waiter'
|
||||
|
||||
@ -53,3 +47,8 @@ class TestComputev2(utils.TestCommand):
|
||||
endpoint=fakes.AUTH_URL,
|
||||
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.tests.compute.v2 import fakes as compute_fakes
|
||||
from openstackclient.tests import fakes
|
||||
from openstackclient.tests.image.v2 import fakes as image_fakes
|
||||
|
||||
|
||||
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.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):
|
||||
|
||||
@ -61,3 +66,89 @@ class TestServerDelete(TestServer):
|
||||
self.servers_mock.delete.assert_called_with(
|
||||
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_name = 'graven'
|
||||
image_owner = 'baal'
|
||||
|
||||
IMAGE = {
|
||||
'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_create = openstackclient.compute.v2.server:CreateServer
|
||||
server_delete = openstackclient.compute.v2.server:DeleteServer
|
||||
server_image_create = openstackclient.compute.v2.server:CreateServerImage
|
||||
server_list = openstackclient.compute.v2.server:ListServer
|
||||
server_lock = openstackclient.compute.v2.server:LockServer
|
||||
server_migrate = openstackclient.compute.v2.server:MigrateServer
|
||||
|
Loading…
Reference in New Issue
Block a user