Merge "Enable creating images with Glance v2"

This commit is contained in:
Jenkins 2016-11-16 15:49:26 +00:00 committed by Gerrit Code Review
commit 6a15a7728f
2 changed files with 130 additions and 33 deletions

View File

@ -361,6 +361,7 @@ class TestUploadOvercloudImage(TestPluginV1):
# Get the command object to test
self.cmd = overcloud_image.UploadOvercloudImage(self.app, None)
self.app.client_manager.image = mock.Mock()
self.app.client_manager.image.version = 2.0
self.app.client_manager.image.images.create.return_value = (
mock.Mock(id=10, name='imgname', properties={'kernel_id': 10,
'ramdisk_id': 10},
@ -433,7 +434,7 @@ class TestUploadOvercloudImage(TestPluginV1):
)
@mock.patch('subprocess.check_call', autospec=True)
def test_overcloud_create_images(self, mock_subprocess_call):
def test_overcloud_create_images_v2(self, mock_subprocess_call):
parsed_args = self.check_parser(self.cmd, [], [])
os.path.isfile = mock.Mock(return_value=False)
@ -441,6 +442,57 @@ class TestUploadOvercloudImage(TestPluginV1):
self.cmd.take_action(parsed_args)
self.assertEqual(
0,
self.app.client_manager.image.images.delete.call_count
)
self.assertEqual(
5,
self.app.client_manager.image.images.create.call_count
)
self.assertEqual(
[mock.call(name='overcloud-full-vmlinuz',
disk_format='aki',
container_format='bare',
visibility='public'),
mock.call(name='overcloud-full-initrd',
disk_format='ari',
container_format='bare',
visibility='public'),
mock.call(name='overcloud-full',
disk_format='qcow2',
container_format='bare',
visibility='public'),
mock.call(name='bm-deploy-kernel',
disk_format='aki',
container_format='bare',
visibility='public'),
mock.call(name='bm-deploy-ramdisk',
disk_format='ari',
container_format='bare',
visibility='public')
], self.app.client_manager.image.images.create.call_args_list
)
self.assertEqual(mock_subprocess_call.call_count, 2)
self.assertEqual(
mock_subprocess_call.call_args_list, [
mock.call('sudo cp -f "./ironic-python-agent.kernel" '
'"/httpboot/agent.kernel"', shell=True),
mock.call('sudo cp -f "./ironic-python-agent.initramfs" '
'"/httpboot/agent.ramdisk"', shell=True)
])
@mock.patch('subprocess.check_call', autospec=True)
def test_overcloud_create_images_v1(self, mock_subprocess_call):
parsed_args = self.check_parser(self.cmd, [], [])
os.path.isfile = mock.Mock(return_value=False)
self.cmd._get_image = mock.Mock(return_value=None)
self.app.client_manager.image.version = 1.0
self.cmd.take_action(parsed_args)
self.assertEqual(
0,
self.app.client_manager.image.images.delete.call_count
@ -538,7 +590,7 @@ class TestUploadOvercloudImage(TestPluginV1):
self.app.client_manager.image.images.create.call_count
)
self.assertEqual(
5,
6,
self.app.client_manager.image.images.update.call_count
)
self.assertEqual(mock_subprocess_call.call_count, 2)

View File

@ -603,6 +603,53 @@ class BuildOvercloudImage(command.Command):
manager.build()
class GlanceBaseClientAdapter(object):
def __init__(self, client):
self.client = client
def print_image_info(self, image):
table = PrettyTable(['ID', 'Name', 'Disk Format', 'Size', 'Status'])
table.add_row([image.id, image.name, image.disk_format, image.size,
image.status])
print(table, file=sys.stdout)
class GlanceV1ClientAdapter(GlanceBaseClientAdapter):
def upload_image(self, *args, **kwargs):
image = self.client.images.create(*args, **kwargs)
print('Image "%s" was uploaded.' % image.name, file=sys.stdout)
self.print_image_info(image)
return image
def get_image_property(self, image, prop):
return image.properties[prop]
class GlanceV2ClientAdapter(GlanceBaseClientAdapter):
def upload_image(self, *args, **kwargs):
is_public = kwargs.pop('is_public')
data = kwargs.pop('data')
properties = kwargs.pop('properties', None)
kwargs['visibility'] = 'public' if is_public else 'private'
kwargs.setdefault('container_format', 'bare')
image = self.client.images.create(*args, **kwargs)
self.client.images.upload(image.id, image_data=data)
if properties:
self.client.images.update(image.id, **properties)
# Refresh image info
image = self.client.images.get(image.id)
print('Image "%s" was uploaded.' % image.name, file=sys.stdout)
self.print_image_info(image)
return image
def get_image_property(self, image, prop):
return getattr(image, prop)
class UploadOvercloudImage(command.Command):
"""Create overcloud glance images from existing image files."""
log = logging.getLogger(__name__ + ".UploadOvercloudImage")
@ -695,17 +742,11 @@ class UploadOvercloudImage(command.Command):
else:
self._copy_file(src_file, dest_file)
def _print_image_info(self, image):
table = PrettyTable(['ID', 'Name', 'Disk Format', 'Size', 'Status'])
table.add_row([image.id, image.name, image.disk_format, image.size,
image.status])
print(table, file=sys.stdout)
def _upload_image(self, *args, **kwargs):
image = self.app.client_manager.image.images.create(*args, **kwargs)
print('Image "%s" was uploaded.' % image.name, file=sys.stdout)
self._print_image_info(image)
return image
def _get_glance_client_adaptor(self):
if self.app.client_manager.image.version >= 2.0:
return GlanceV2ClientAdapter(self.app.client_manager.image)
else:
return GlanceV1ClientAdapter(self.app.client_manager.image)
def get_parser(self, prog_name):
parser = super(UploadOvercloudImage, self).get_parser(prog_name)
@ -734,6 +775,7 @@ class UploadOvercloudImage(command.Command):
def take_action(self, parsed_args):
self.log.debug("take_action(%s)" % parsed_args)
glance_client_adaptor = self._get_glance_client_adaptor()
self._env_variable_or_set('AGENT_NAME', 'ironic-python-agent')
@ -758,7 +800,7 @@ class UploadOvercloudImage(command.Command):
kernel = (self._image_try_update(oc_vmlinuz_name,
oc_vmlinuz_file,
parsed_args) or
self._upload_image(
glance_client_adaptor.upload_image(
name=oc_vmlinuz_name,
is_public=True,
disk_format='aki',
@ -771,7 +813,7 @@ class UploadOvercloudImage(command.Command):
ramdisk = (self._image_try_update(oc_initrd_name,
oc_initrd_file,
parsed_args) or
self._upload_image(
glance_client_adaptor.upload_image(
name=oc_initrd_name,
is_public=True,
disk_format='ari',
@ -783,7 +825,7 @@ class UploadOvercloudImage(command.Command):
oc_file = '%s.qcow2' % image_name
overcloud_image = (self._image_try_update(oc_name, oc_file,
parsed_args) or
self._upload_image(
glance_client_adaptor.upload_image(
name=oc_name,
is_public=True,
disk_format='qcow2',
@ -794,9 +836,12 @@ class UploadOvercloudImage(command.Command):
parsed_args.image_path, oc_file)
))
img_kernel_id = glance_client_adaptor.get_image_property(
overcloud_image, 'kernel_id')
img_ramdisk_id = glance_client_adaptor.get_image_property(
overcloud_image, 'ramdisk_id')
# check overcloud image links
if (overcloud_image.properties['kernel_id'] != kernel.id or
overcloud_image.properties['ramdisk_id'] != ramdisk.id):
if (img_kernel_id != kernel.id or img_ramdisk_id != ramdisk.id):
self.log.error('Link overcloud image to it\'s initrd and kernel'
' images is MISSING OR leads to OLD image.'
' You can keep it or fix it manually.')
@ -806,25 +851,25 @@ class UploadOvercloudImage(command.Command):
deploy_kernel_name = 'bm-deploy-kernel'
deploy_kernel_file = '%s.kernel' % os.environ['AGENT_NAME']
self._image_try_update(deploy_kernel_name, deploy_kernel_file,
parsed_args) or self._upload_image(
name=deploy_kernel_name,
is_public=True,
disk_format='aki',
data=self._read_image_file_pointer(
parsed_args.image_path,
deploy_kernel_file)
)
parsed_args) or \
glance_client_adaptor.upload_image(
name=deploy_kernel_name,
is_public=True,
disk_format='aki',
data=self._read_image_file_pointer(
parsed_args.image_path,
deploy_kernel_file))
deploy_ramdisk_name = 'bm-deploy-ramdisk'
deploy_ramdisk_file = '%s.initramfs' % os.environ['AGENT_NAME']
self._image_try_update(deploy_ramdisk_name, deploy_ramdisk_file,
parsed_args) or self._upload_image(
name=deploy_ramdisk_name,
is_public=True,
disk_format='ari',
data=self._read_image_file_pointer(parsed_args.image_path,
deploy_ramdisk_file)
)
parsed_args) or \
glance_client_adaptor.upload_image(
name=deploy_ramdisk_name,
is_public=True,
disk_format='ari',
data=self._read_image_file_pointer(parsed_args.image_path,
deploy_ramdisk_file))
self.log.debug("copy agent images to HTTP BOOT dir")