Merge "Support whole disk images in TripleO"

This commit is contained in:
Jenkins 2016-11-18 00:04:55 +00:00 committed by Gerrit Code Review
commit c212fbd065
3 changed files with 217 additions and 53 deletions

View File

@ -0,0 +1,15 @@
---
features:
- Allow client to support whole disk images. Client
will now accept a --whole-disk flag on the
overcloud image upload command. When this flag is
set, it will only look for qcow2 image, not enforcing
the upload of initrd and vmlinuz images. It will also
not set these properties on the qcow2 image on glance.
This will allow Ironic to consider the uploaded image
as full disk image, giving the possibility to provide
full disk images in TripleO instead of single partition
ones.
Please look at `Ironic documentation <http://docs.openstack.org/project-install-guide/baremetal/draft/configure-integration.html#create-and-add-images-to-the-image-service>`_
for reference

View File

@ -594,3 +594,119 @@ class TestUploadOvercloudImage(TestPluginV1):
self.app.client_manager.image.images.update.call_count
)
self.assertEqual(mock_subprocess_call.call_count, 2)
class TestUploadOvercloudImageFull(TestPluginV1):
def setUp(self):
super(TestUploadOvercloudImageFull, self).setUp()
# 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={},
created_at='2015-07-31T14:37:22.000000'))
self.cmd._read_image_file_pointer = mock.Mock(return_value=b'IMGDATA')
self.cmd._check_file_exists = mock.Mock(return_value=True)
@mock.patch('subprocess.check_call', autospec=True)
def test_overcloud_create_images(self, mock_subprocess_call):
parsed_args = self.check_parser(self.cmd, ['--whole-disk'], [])
os.path.isfile = mock.Mock(return_value=False)
self.cmd._get_image = mock.Mock(return_value=None)
self.cmd.take_action(parsed_args)
self.assertEqual(
0,
self.app.client_manager.image.images.delete.call_count
)
self.assertEqual(
3,
self.app.client_manager.image.images.create.call_count
)
self.assertEqual(
[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_noupdate_images(self, mock_subprocess_call):
parsed_args = self.check_parser(self.cmd, ['--whole-disk'], [])
os.path.isfile = mock.Mock(return_value=True)
self.cmd._files_changed = mock.Mock(return_value=True)
existing_image = mock.Mock(id=10, name='imgname',
properties={})
self.cmd._get_image = mock.Mock(return_value=existing_image)
self.cmd._image_changed = mock.Mock(return_value=True)
self.cmd.take_action(parsed_args)
self.assertEqual(
0,
self.app.client_manager.image.images.delete.call_count
)
self.assertEqual(
0,
self.app.client_manager.image.images.create.call_count
)
self.assertEqual(
0,
self.app.client_manager.image.images.update.call_count
)
self.assertEqual(mock_subprocess_call.call_count, 0)
@mock.patch('subprocess.check_call', autospec=True)
def test_overcloud_create_update_images(self, mock_subprocess_call):
parsed_args = self.check_parser(
self.cmd, ['--update-existing', '--whole-disk'], [])
self.cmd._files_changed = mock.Mock(return_value=True)
existing_image = mock.Mock(id=10, name='imgname',
properties={},
created_at='2015-07-31T14:37:22.000000')
self.cmd._get_image = mock.Mock(return_value=existing_image)
self.cmd._image_changed = mock.Mock(return_value=True)
self.app.client_manager.image.images.update.return_value = (
existing_image)
self.cmd.take_action(parsed_args)
self.assertEqual(
0,
self.app.client_manager.image.images.delete.call_count
)
self.assertEqual(
3,
self.app.client_manager.image.images.create.call_count
)
self.assertEqual(
3,
self.app.client_manager.image.images.update.call_count
)
self.assertEqual(mock_subprocess_call.call_count, 2)

View File

@ -771,6 +771,14 @@ class UploadOvercloudImage(command.Command):
action="store_true",
help=_("Update images if already exist"),
)
parser.add_argument(
"--whole-disk",
dest="whole_disk",
action="store_true",
default=False,
help=_("When set, the overcloud-full image to be uploaded "
"will be considered as a whole disk one"),
)
return parser
def take_action(self, parsed_args):
@ -781,11 +789,18 @@ class UploadOvercloudImage(command.Command):
self.log.debug("checking if image files exist")
image_files = [
'%s.initramfs' % os.environ['AGENT_NAME'],
'%s.kernel' % os.environ['AGENT_NAME'],
parsed_args.os_image
]
if parsed_args.whole_disk:
image_files = [
parsed_args.os_image
]
overcloud_image_type = 'whole disk'
else:
image_files = [
'%s.initramfs' % os.environ['AGENT_NAME'],
'%s.kernel' % os.environ['AGENT_NAME'],
parsed_args.os_image
]
overcloud_image_type = 'partition'
for image in image_files:
self._check_file_exists(os.path.join(parsed_args.image_path,
@ -793,58 +808,76 @@ class UploadOvercloudImage(command.Command):
image_name = parsed_args.os_image.split('.')[0]
self.log.debug("uploading overcloud images to glance")
self.log.debug("uploading %s overcloud images to glance" %
overcloud_image_type)
oc_vmlinuz_name = '%s-vmlinuz' % image_name
oc_vmlinuz_file = '%s.vmlinuz' % image_name
kernel = (self._image_try_update(oc_vmlinuz_name,
oc_vmlinuz_file,
parsed_args) or
glance_client_adaptor.upload_image(
name=oc_vmlinuz_name,
is_public=True,
disk_format='aki',
data=self._read_image_file_pointer(
parsed_args.image_path, oc_vmlinuz_file)
))
# vmlinuz and initrd only need to be uploaded for a partition image
if not parsed_args.whole_disk:
oc_vmlinuz_name = '%s-vmlinuz' % image_name
oc_vmlinuz_file = '%s.vmlinuz' % image_name
kernel = (self._image_try_update(oc_vmlinuz_name,
oc_vmlinuz_file,
parsed_args) or
glance_client_adaptor.upload_image(
name=oc_vmlinuz_name,
is_public=True,
disk_format='aki',
data=self._read_image_file_pointer(
parsed_args.image_path, oc_vmlinuz_file)
))
oc_initrd_name = '%s-initrd' % image_name
oc_initrd_file = '%s.initrd' % image_name
ramdisk = (self._image_try_update(oc_initrd_name,
oc_initrd_file,
parsed_args) or
glance_client_adaptor.upload_image(
name=oc_initrd_name,
is_public=True,
disk_format='ari',
data=self._read_image_file_pointer(
parsed_args.image_path, oc_initrd_file)
))
oc_initrd_name = '%s-initrd' % image_name
oc_initrd_file = '%s.initrd' % image_name
ramdisk = (self._image_try_update(oc_initrd_name,
oc_initrd_file,
parsed_args) or
glance_client_adaptor.upload_image(
name=oc_initrd_name,
is_public=True,
disk_format='ari',
data=self._read_image_file_pointer(
parsed_args.image_path, oc_initrd_file)
))
oc_name = image_name
oc_file = '%s.qcow2' % image_name
overcloud_image = (self._image_try_update(oc_name, oc_file,
parsed_args) or
glance_client_adaptor.upload_image(
name=oc_name,
is_public=True,
disk_format='qcow2',
container_format='bare',
properties={'kernel_id': kernel.id,
'ramdisk_id': ramdisk.id},
data=self._read_image_file_pointer(
parsed_args.image_path, oc_file)
))
oc_name = image_name
oc_file = '%s.qcow2' % image_name
overcloud_image = (self._image_try_update(oc_name, oc_file,
parsed_args) or
glance_client_adaptor.upload_image(
name=oc_name,
is_public=True,
disk_format='qcow2',
container_format='bare',
properties={'kernel_id': kernel.id,
'ramdisk_id': ramdisk.id},
data=self._read_image_file_pointer(
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 (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.')
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 (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.')
else:
oc_name = image_name
oc_file = '%s.qcow2' % image_name
overcloud_image = (self._image_try_update(oc_name, oc_file,
parsed_args) or
glance_client_adaptor.upload_image(
name=oc_name,
is_public=True,
disk_format='qcow2',
container_format='bare',
properties={},
data=self._read_image_file_pointer(
parsed_args.image_path, oc_file)
))
self.log.debug("uploading bm images to glance")