Add overcloud image create method
Adding overcloud image create method to replace instack code (method instack-prepare-for-overcloud) and do overcloud deployment via rdomanager commands. Main functionality is to take locally stored image files and upload them to glance. Change-Id: Icc39744c511013d663242f5b544b0ac4a2fd6893
This commit is contained in:
parent
bb804c6ce8
commit
937e848460
@ -13,6 +13,7 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
#
|
#
|
||||||
|
|
||||||
|
import mock
|
||||||
from rdomanager_oscplugin.tests.v1.test_plugin import TestPluginV1
|
from rdomanager_oscplugin.tests.v1.test_plugin import TestPluginV1
|
||||||
|
|
||||||
# Load the plugin init module for the plugin list and show commands
|
# Load the plugin init module for the plugin list and show commands
|
||||||
@ -39,4 +40,58 @@ class TestOvercloudImageCreate(TestPluginV1):
|
|||||||
super(TestOvercloudImageCreate, self).setUp()
|
super(TestOvercloudImageCreate, self).setUp()
|
||||||
|
|
||||||
# Get the command object to test
|
# Get the command object to test
|
||||||
self.cmd = overcloud_image.CreatePlugin(self.app, None)
|
self.cmd = overcloud_image.CreateOvercloud(self.app, None)
|
||||||
|
self.app.client_manager.image = mock.Mock()
|
||||||
|
self.app.client_manager.image.images.create.return_value = \
|
||||||
|
mock.Mock(id=10)
|
||||||
|
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.call')
|
||||||
|
def test_overcloud_create_images(self, mock_subprocess_call):
|
||||||
|
parsed_args = self.check_parser(self.cmd, [], [])
|
||||||
|
|
||||||
|
self.cmd.take_action(parsed_args)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
2,
|
||||||
|
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(data=b'IMGDATA',
|
||||||
|
name='overcloud-full-vmlinuz',
|
||||||
|
disk_format='aki',
|
||||||
|
is_public=True),
|
||||||
|
mock.call(data=b'IMGDATA',
|
||||||
|
name='overcloud-full-initrd',
|
||||||
|
disk_format='ari',
|
||||||
|
is_public=True),
|
||||||
|
mock.call(properties={'kernel_id': 10, 'ramdisk_id': 10},
|
||||||
|
name='overcloud-full',
|
||||||
|
data=b'IMGDATA',
|
||||||
|
container_format='bare',
|
||||||
|
disk_format='qcow2',
|
||||||
|
is_public=True),
|
||||||
|
mock.call(data=b'IMGDATA',
|
||||||
|
name='bm-deploy-kernel',
|
||||||
|
disk_format='aki',
|
||||||
|
is_public=True),
|
||||||
|
mock.call(data=b'IMGDATA',
|
||||||
|
name='bm-deploy-ramdisk',
|
||||||
|
disk_format='ari',
|
||||||
|
is_public=True)
|
||||||
|
], 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 "./discovery-ramdisk.kernel" '
|
||||||
|
'"/tftpboot/discovery.kernel"', shell=True),
|
||||||
|
mock.call('sudo cp -f "./discovery-ramdisk.initramfs" '
|
||||||
|
'"/tftpboot/discovery.ramdisk"', shell=True)
|
||||||
|
])
|
||||||
|
@ -16,8 +16,12 @@
|
|||||||
"""Plugin action implementation"""
|
"""Plugin action implementation"""
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
import os
|
||||||
|
import subprocess
|
||||||
|
|
||||||
from cliff import command
|
from cliff import command
|
||||||
|
from openstackclient.common import exceptions
|
||||||
|
from openstackclient.common import utils
|
||||||
|
|
||||||
|
|
||||||
class BuildPlugin(command.Command):
|
class BuildPlugin(command.Command):
|
||||||
@ -31,11 +35,137 @@ class BuildPlugin(command.Command):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class CreatePlugin(command.Command):
|
class CreateOvercloud(command.Command):
|
||||||
"""Overcloud Image Create plugin"""
|
"""Create overcloud glance images from existing image files."""
|
||||||
auth_required = False
|
auth_required = False
|
||||||
log = logging.getLogger(__name__ + ".CreatePlugin")
|
log = logging.getLogger(__name__ + ".CreateOvercloud")
|
||||||
|
|
||||||
|
def _env_variable_or_set(self, key_name, default_value):
|
||||||
|
os.environ[key_name] = os.environ.get(key_name, default_value)
|
||||||
|
|
||||||
|
def _delete_image_if_exists(self, image_client, name):
|
||||||
|
try:
|
||||||
|
image = utils.find_resource(image_client.images, name)
|
||||||
|
image_client.images.delete(image.id)
|
||||||
|
except exceptions.CommandError:
|
||||||
|
self.log.debug('Image "%s" have already not existed, '
|
||||||
|
'no problem.' % name)
|
||||||
|
|
||||||
|
def _check_file_exists(self, file_path):
|
||||||
|
if not os.path.isfile(file_path):
|
||||||
|
print('ERROR: Required file "%s" does not exist' % file_path)
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
def _read_image_file_pointer(self, dirname, filename):
|
||||||
|
filepath = os.path.join(dirname, filename)
|
||||||
|
self._check_file_exists(filepath)
|
||||||
|
return open(filepath, 'rb')
|
||||||
|
|
||||||
|
def _copy_file(self, src, dest):
|
||||||
|
subprocess.call('sudo cp -f "{0}" "{1}"'.format(src, dest), shell=True)
|
||||||
|
|
||||||
|
def _load_image(self, image_path, image_name, image_client):
|
||||||
|
self.log.debug("uploading images to glance")
|
||||||
|
|
||||||
|
kernel_id = image_client.images.create(
|
||||||
|
name='%s-vmlinuz' % image_name,
|
||||||
|
is_public=True,
|
||||||
|
disk_format='aki',
|
||||||
|
data=self._read_image_file_pointer(image_path,
|
||||||
|
'%s.vmlinuz' % image_name)
|
||||||
|
).id
|
||||||
|
|
||||||
|
ramdisk_id = image_client.images.create(
|
||||||
|
name='%s-initrd' % image_name,
|
||||||
|
is_public=True,
|
||||||
|
disk_format='ari',
|
||||||
|
data=self._read_image_file_pointer(image_path,
|
||||||
|
'%s.initrd' % image_name)
|
||||||
|
).id
|
||||||
|
|
||||||
|
image_client.images.create(
|
||||||
|
name=image_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(image_path,
|
||||||
|
'%s.qcow2' % image_name)
|
||||||
|
)
|
||||||
|
|
||||||
|
def get_parser(self, prog_name):
|
||||||
|
parser = super(CreateOvercloud, self).get_parser(prog_name)
|
||||||
|
parser.add_argument(
|
||||||
|
"--image-path",
|
||||||
|
default='./',
|
||||||
|
help="Path to directory containing image files",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--os-image",
|
||||||
|
default='overcloud-full.qcow2',
|
||||||
|
help="OpenStack disk image filename",
|
||||||
|
)
|
||||||
|
return parser
|
||||||
|
|
||||||
def take_action(self, parsed_args):
|
def take_action(self, parsed_args):
|
||||||
self.log.debug("take_action(%s)" % parsed_args)
|
self.log.debug("take_action(%s)" % parsed_args)
|
||||||
pass
|
image_client = self.app.client_manager.image
|
||||||
|
|
||||||
|
self._env_variable_or_set('DEPLOY_NAME', 'deploy-ramdisk-ironic')
|
||||||
|
self._env_variable_or_set('DISCOVERY_NAME', 'discovery-ramdisk')
|
||||||
|
self._env_variable_or_set('TFTP_ROOT', '/tftpboot')
|
||||||
|
|
||||||
|
self.log.debug("check image files")
|
||||||
|
|
||||||
|
image_files = [
|
||||||
|
'%s.initramfs' % os.environ['DEPLOY_NAME'],
|
||||||
|
'%s.kernel' % os.environ['DEPLOY_NAME'],
|
||||||
|
'%s.initramfs' % os.environ['DISCOVERY_NAME'],
|
||||||
|
'%s.kernel' % os.environ['DISCOVERY_NAME'],
|
||||||
|
parsed_args.os_image
|
||||||
|
]
|
||||||
|
|
||||||
|
for image in image_files:
|
||||||
|
self._check_file_exists(os.path.join(parsed_args.image_path,
|
||||||
|
image))
|
||||||
|
|
||||||
|
self.log.debug("prepare glance images")
|
||||||
|
|
||||||
|
self._load_image(parsed_args.image_path,
|
||||||
|
parsed_args.os_image.split('.')[0],
|
||||||
|
image_client)
|
||||||
|
|
||||||
|
self._delete_image_if_exists(image_client, 'bm_deploy_kernel')
|
||||||
|
self._delete_image_if_exists(image_client, 'bm_deploy_ramdisk')
|
||||||
|
|
||||||
|
image_client.images.create(
|
||||||
|
name='bm-deploy-kernel',
|
||||||
|
is_public=True,
|
||||||
|
disk_format='aki',
|
||||||
|
data=self._read_image_file_pointer(parsed_args.image_path,
|
||||||
|
'%s.kernel' %
|
||||||
|
os.environ['DEPLOY_NAME'])
|
||||||
|
)
|
||||||
|
|
||||||
|
image_client.images.create(
|
||||||
|
name='bm-deploy-ramdisk',
|
||||||
|
is_public=True,
|
||||||
|
disk_format='ari',
|
||||||
|
data=self._read_image_file_pointer(parsed_args.image_path,
|
||||||
|
'%s.initramfs' %
|
||||||
|
os.environ['DEPLOY_NAME'])
|
||||||
|
)
|
||||||
|
|
||||||
|
self.log.debug("copy discovery images to TFTP")
|
||||||
|
|
||||||
|
self._copy_file(
|
||||||
|
os.path.join(parsed_args.image_path,
|
||||||
|
'%s.kernel' % os.environ['DISCOVERY_NAME']),
|
||||||
|
os.path.join(os.environ['TFTP_ROOT'], 'discovery.kernel')
|
||||||
|
)
|
||||||
|
|
||||||
|
self._copy_file(
|
||||||
|
os.path.join(parsed_args.image_path,
|
||||||
|
'%s.initramfs' % os.environ['DISCOVERY_NAME']),
|
||||||
|
os.path.join(os.environ['TFTP_ROOT'], 'discovery.ramdisk')
|
||||||
|
)
|
||||||
|
@ -60,5 +60,5 @@ openstack.rdomanager_oscplugin.v1 =
|
|||||||
baremetal_configure_boot = rdomanager_oscplugin.v1.baremetal:ConfigureBootPlugin
|
baremetal_configure_boot = rdomanager_oscplugin.v1.baremetal:ConfigureBootPlugin
|
||||||
overcloud_deploy = rdomanager_oscplugin.v1.overcloud_deploy:DeployPlugin
|
overcloud_deploy = rdomanager_oscplugin.v1.overcloud_deploy:DeployPlugin
|
||||||
overcloud_image_build = rdomanager_oscplugin.v1.overcloud_image:BuildPlugin
|
overcloud_image_build = rdomanager_oscplugin.v1.overcloud_image:BuildPlugin
|
||||||
overcloud_image_create = rdomanager_oscplugin.v1.overcloud_image:CreatePlugin
|
overcloud_image_create = rdomanager_oscplugin.v1.overcloud_image:CreateOvercloud
|
||||||
undercloud_install = rdomanager_oscplugin.v1.undercloud:InstallPlugin
|
undercloud_install = rdomanager_oscplugin.v1.undercloud:InstallPlugin
|
||||||
|
Loading…
Reference in New Issue
Block a user