summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJenkins <jenkins@review.openstack.org>2013-11-20 06:37:25 +0000
committerGerrit Code Review <review@openstack.org>2013-11-20 06:37:25 +0000
commitd45187a0c163187649e29931d21c4607379d1e73 (patch)
treea693cd9d92735a2e0ec750c79563978a95b0bca5
parentb70b1d04e447bb3748fcfd8cf25794fb8ea64b65 (diff)
parent200ed62054847336235288c7785424be416bed06 (diff)
downloadpython-openstackclient-d45187a0c163187649e29931d21c4607379d1e73.tar.gz
Merge "Add server image create command"
-rw-r--r--openstackclient/compute/v2/server.py67
-rw-r--r--openstackclient/tests/compute/v2/fakes.py13
-rw-r--r--openstackclient/tests/compute/v2/test_server.py91
-rw-r--r--openstackclient/tests/image/v2/fakes.py5
-rw-r--r--setup.cfg1
5 files changed, 169 insertions, 8 deletions
diff --git a/openstackclient/compute/v2/server.py b/openstackclient/compute/v2/server.py
index 1de9f1ba..87f5f689 100644
--- a/openstackclient/compute/v2/server.py
+++ b/openstackclient/compute/v2/server.py
@@ -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"""
diff --git a/openstackclient/tests/compute/v2/fakes.py b/openstackclient/tests/compute/v2/fakes.py
index 8154449f..03ebd67c 100644
--- a/openstackclient/tests/compute/v2/fakes.py
+++ b/openstackclient/tests/compute/v2/fakes.py
@@ -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,
+ )
diff --git a/openstackclient/tests/compute/v2/test_server.py b/openstackclient/tests/compute/v2/test_server.py
index 7e68808e..4cd294cc 100644
--- a/openstackclient/tests/compute/v2/test_server.py
+++ b/openstackclient/tests/compute/v2/test_server.py
@@ -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)
diff --git a/openstackclient/tests/image/v2/fakes.py b/openstackclient/tests/image/v2/fakes.py
index df6b8072..96255cd4 100644
--- a/openstackclient/tests/image/v2/fakes.py
+++ b/openstackclient/tests/image/v2/fakes.py
@@ -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,
}
diff --git a/setup.cfg b/setup.cfg
index 35a4d207..95a585be 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -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