switch from xcat backend to smut backend
zvm cloud connector has dropped xcat backend support. Swtich to smut backend instead. Change-Id: Ie09070f4ff43db4c244305378352f34809c9be74
This commit is contained in:
parent
9704803789
commit
369b0b1674
|
@ -17,6 +17,7 @@
|
|||
|
||||
import os
|
||||
|
||||
from nova import exception
|
||||
from nova import test
|
||||
from oslo_utils import fileutils
|
||||
|
||||
|
@ -38,14 +39,13 @@ class ZVMConfigDriveTestCase(test.NoDBTestCase):
|
|||
super(ZVMConfigDriveTestCase, self).setUp()
|
||||
self.flags(config_drive_format='iso9660',
|
||||
tempdir='/tmp/os')
|
||||
|
||||
self._file_path = CONF.tempdir
|
||||
self._file_name = self._file_path + '/cfgdrive.tgz'
|
||||
self.inst_md = FakeInstMeta()
|
||||
|
||||
def test_create_configdrive_tgz(self):
|
||||
self._file_path = CONF.tempdir
|
||||
fileutils.ensure_tree(self._file_path)
|
||||
self._file_name = self._file_path + '/cfgdrive.tgz'
|
||||
|
||||
try:
|
||||
with zvmconfigdrive.ZVMConfigDriveBuilder(
|
||||
instance_md=self.inst_md) as c:
|
||||
|
@ -55,3 +55,13 @@ class ZVMConfigDriveTestCase(test.NoDBTestCase):
|
|||
|
||||
finally:
|
||||
fileutils.remove_path_on_error(self._file_path)
|
||||
|
||||
def test_make_drive_unknown_format(self):
|
||||
self.flags(config_drive_format='vfat')
|
||||
try:
|
||||
with zvmconfigdrive.ZVMConfigDriveBuilder(
|
||||
instance_md=self.inst_md) as c:
|
||||
self.assertRaises(exception.ConfigDriveUnknownFormat,
|
||||
c.make_drive, self._file_name)
|
||||
finally:
|
||||
fileutils.remove_path_on_error(self._file_path)
|
||||
|
|
|
@ -12,67 +12,37 @@
|
|||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
|
||||
"""Test suite for ZVMDriver."""
|
||||
|
||||
import copy
|
||||
import eventlet
|
||||
import mock
|
||||
|
||||
from nova.compute import power_state
|
||||
from nova import context
|
||||
from nova import exception as nova_exception
|
||||
from nova.image import api as image_api
|
||||
from nova import exception
|
||||
from nova.network import model as network_model
|
||||
from nova import objects
|
||||
from nova.objects import fields as obj_fields
|
||||
from nova import test
|
||||
from nova.tests.unit import fake_instance
|
||||
from nova.tests import uuidsentinel
|
||||
from nova.virt import fake
|
||||
from nova.virt import hardware
|
||||
from zvmsdk import api as sdkapi
|
||||
from zvmsdk import dist
|
||||
from zvmsdk import exception as sdkexception
|
||||
|
||||
from nova_zvm.virt.zvm import conf
|
||||
from nova_zvm.virt.zvm import const
|
||||
from nova_zvm.virt.zvm import driver
|
||||
from nova_zvm.virt.zvm import driver as zvmdriver
|
||||
from nova_zvm.virt.zvm import utils as zvmutils
|
||||
|
||||
|
||||
CONF = conf.CONF
|
||||
CONF.import_opt('host', 'nova.conf')
|
||||
CONF.import_opt('my_ip', 'nova.conf')
|
||||
class TestZVMDriver(test.NoDBTestCase):
|
||||
|
||||
|
||||
class ZVMDriverTestCases(test.NoDBTestCase):
|
||||
"""Unit tests for z/VM driver methods."""
|
||||
|
||||
@mock.patch.object(driver.ZVMDriver, 'update_host_status')
|
||||
def setUp(self, update_host_status):
|
||||
super(ZVMDriverTestCases, self).setUp()
|
||||
|
||||
self.flags(host='fakehost',
|
||||
my_ip='10.1.1.10',
|
||||
instance_name_template = 'test%04x')
|
||||
update_host_status.return_value = [{
|
||||
'host': 'fakehost',
|
||||
'allowed_vm_type': 'zLinux',
|
||||
'vcpus': 10,
|
||||
'vcpus_used': 10,
|
||||
'cpu_info': {'Architecture': 's390x', 'CEC model': '2097'},
|
||||
'disk_total': 406105,
|
||||
'disk_used': 367263,
|
||||
'disk_available': 38842,
|
||||
'host_memory_total': 16384,
|
||||
'host_memory_free': 8096,
|
||||
'hypervisor_type': 'zvm',
|
||||
'hypervisor_version': '630',
|
||||
'hypervisor_hostname': 'fakenode',
|
||||
'supported_instances': [('s390x', 'zvm', 'hvm')],
|
||||
'ipl_time': 'IPL at 03/13/14 21:43:12 EDT',
|
||||
}]
|
||||
self.driver = driver.ZVMDriver(fake.FakeVirtAPI())
|
||||
def setUp(self):
|
||||
super(TestZVMDriver, self).setUp()
|
||||
self.flags(zvm_cloud_connector_url='https://1.1.1.1:1111',
|
||||
zvm_image_tmp_path='/test/image',
|
||||
zvm_reachable_timeout=300)
|
||||
self.flags(my_ip='192.168.1.1',
|
||||
instance_name_template='test%04x')
|
||||
with mock.patch('nova_zvm.virt.zvm.utils.'
|
||||
'zVMConnectorRequestHandler.call') as mcall:
|
||||
mcall.return_value = {'hypervisor_hostname': 'TESTHOST',
|
||||
'ipl_time': 'TESTTIME'}
|
||||
self.driver = zvmdriver.ZVMDriver('virtapi')
|
||||
self._context = context.RequestContext('fake_user', 'fake_project')
|
||||
self._uuid = uuidsentinel.foo
|
||||
self._image_id = uuidsentinel.foo
|
||||
|
@ -82,7 +52,7 @@ class ZVMDriverTestCases(test.NoDBTestCase):
|
|||
'vcpus': 1,
|
||||
'memory_mb': 1024,
|
||||
'image_ref': self._image_id,
|
||||
'root_gb': 3,
|
||||
'root_gb': 0,
|
||||
}
|
||||
self._instance = fake_instance.fake_instance_obj(
|
||||
self._context, **self._instance_values)
|
||||
|
@ -91,7 +61,7 @@ class ZVMDriverTestCases(test.NoDBTestCase):
|
|||
swap=0, extra_specs={})
|
||||
self._instance.flavor = self._flavor
|
||||
|
||||
eph_disks = [{'guest_format': u'ext3',
|
||||
self._eph_disks = [{'guest_format': u'ext3',
|
||||
'device_name': u'/dev/sdb',
|
||||
'disk_bus': None,
|
||||
'device_type': None,
|
||||
|
@ -103,9 +73,8 @@ class ZVMDriverTestCases(test.NoDBTestCase):
|
|||
'size': 2}]
|
||||
self._block_device_info = {'swap': None,
|
||||
'root_device_name': u'/dev/sda',
|
||||
'ephemerals': eph_disks,
|
||||
'ephemerals': self._eph_disks,
|
||||
'block_device_mapping': []}
|
||||
|
||||
fake_image_meta = {'status': 'active',
|
||||
'properties': {'os_distro': 'rhel7.2'},
|
||||
'name': 'rhel72eckdimage',
|
||||
|
@ -148,226 +117,321 @@ class ZVMDriverTestCases(test.NoDBTestCase):
|
|||
network_model.VIF(**self._network_values)
|
||||
])
|
||||
|
||||
def test_init_driver(self):
|
||||
self.assertIsInstance(self.driver._sdk_api, sdkapi.SDKAPI)
|
||||
def test_driver_init(self):
|
||||
self.assertEqual(self.driver._hypervisor_hostname, 'TESTHOST')
|
||||
self.assertIsInstance(self.driver._reqh,
|
||||
zvmutils.zVMConnectorRequestHandler)
|
||||
self.assertIsInstance(self.driver._vmutils, zvmutils.VMUtils)
|
||||
self.assertIsInstance(self.driver._image_api, image_api.API)
|
||||
self.assertIsInstance(self.driver._pathutils, zvmutils.PathUtils)
|
||||
self.assertIsInstance(self.driver._imageutils, zvmutils.ImageUtils)
|
||||
self.assertIsInstance(self.driver._networkutils,
|
||||
zvmutils.NetworkUtils)
|
||||
self.assertIsInstance(self.driver._imageop_semaphore,
|
||||
eventlet.semaphore.Semaphore)
|
||||
self.assertEqual(self.driver._host_stats[0]['host'], "fakehost")
|
||||
self.assertEqual(self.driver._host_stats[0]['disk_available'], 38842)
|
||||
|
||||
@mock.patch.object(sdkapi.SDKAPI, 'host_get_info')
|
||||
def test_update_host_status(self, host_get_info):
|
||||
host_get_info.return_value = {
|
||||
'vcpus': 10,
|
||||
'vcpus_used': 10,
|
||||
'cpu_info': {'Architecture': 's390x', 'CEC model': '2097'},
|
||||
'disk_total': 406105,
|
||||
'disk_used': 367263,
|
||||
'disk_available': 38842,
|
||||
'memory_mb': 876543,
|
||||
'memory_mb_used': 111111,
|
||||
'hypervisor_type': 'zvm',
|
||||
'hypervisor_version': '630',
|
||||
'hypervisor_hostname': 'fakenode',
|
||||
'ipl_time': 'IPL at 03/13/14 21:43:12 EDT',
|
||||
}
|
||||
info = self.driver.update_host_status()
|
||||
host_get_info.assert_called_with()
|
||||
self.assertEqual(info[0]['host'], CONF.host)
|
||||
self.assertEqual(info[0]['hypervisor_hostname'], 'fakenode')
|
||||
self.assertEqual(info[0]['host_memory_free'], 765432)
|
||||
@mock.patch('nova_zvm.virt.zvm.utils.zVMConnectorRequestHandler.call')
|
||||
def test_list_instance(self, call):
|
||||
call.return_value = ['vm1', 'vm2']
|
||||
inst_list = self.driver.list_instances()
|
||||
self.assertEqual(['vm1', 'vm2'], inst_list)
|
||||
|
||||
@mock.patch.object(driver.ZVMDriver, 'update_host_status')
|
||||
def test_get_available_resource(self, update_host_status):
|
||||
update_host_status.return_value = [{
|
||||
'host': CONF.host,
|
||||
'allowed_vm_type': const.ALLOWED_VM_TYPE,
|
||||
'vcpus': 10,
|
||||
'vcpus_used': 10,
|
||||
'cpu_info': {'Architecture': 's390x', 'CEC model': '2097'},
|
||||
'disk_total': 406105,
|
||||
'disk_used': 367263,
|
||||
'disk_available': 38842,
|
||||
'host_memory_total': 876543,
|
||||
'host_memory_free': 111111,
|
||||
'hypervisor_type': 'zvm',
|
||||
'hypervisor_version': '630',
|
||||
'hypervisor_hostname': 'fakenode',
|
||||
'supported_instances': [(const.ARCHITECTURE,
|
||||
const.HYPERVISOR_TYPE,
|
||||
obj_fields.VMMode.HVM)],
|
||||
'ipl_time': 'IPL at 03/13/14 21:43:12 EDT',
|
||||
}]
|
||||
res = self.driver.get_available_resource('fakenode')
|
||||
self.assertEqual(res['vcpus'], 10)
|
||||
self.assertEqual(res['memory_mb_used'], 765432)
|
||||
self.assertEqual(res['disk_available_least'], 38842)
|
||||
@mock.patch('nova_zvm.virt.zvm.utils.zVMConnectorRequestHandler.call')
|
||||
def test_get_available_resource(self, call):
|
||||
host_info = {'disk_available': 1144,
|
||||
'ipl_time': u'IPL at 11/14/17 10:47:44 EST',
|
||||
'vcpus_used': 4,
|
||||
'hypervisor_type': u'zvm',
|
||||
'disk_total': 2000,
|
||||
'zvm_host': u'TESTHOST',
|
||||
'memory_mb': 78192.0,
|
||||
'cpu_info': {u'cec_model': u'2827',
|
||||
u'architecture': u's390x'},
|
||||
'vcpus': 84,
|
||||
'hypervisor_hostname': u'TESTHOST',
|
||||
'hypervisor_version': 640,
|
||||
'disk_used': 856,
|
||||
'memory_mb_used': 8192.0}
|
||||
call.return_value = host_info
|
||||
results = self.driver.get_available_resource()
|
||||
self.assertEqual(84, results['vcpus'])
|
||||
self.assertEqual(8192.0, results['memory_mb_used'])
|
||||
self.assertEqual(1144, results['disk_available_least'])
|
||||
self.assertEqual('TESTHOST', results['hypervisor_hostname'])
|
||||
|
||||
@mock.patch.object(sdkapi.SDKAPI, 'guest_list')
|
||||
def test_list_instances(self, guest_list):
|
||||
self.driver.list_instances()
|
||||
guest_list.assert_called_once_with()
|
||||
|
||||
@mock.patch.object(sdkapi.SDKAPI, 'guest_get_power_state')
|
||||
@mock.patch.object(zvmutils, 'mapping_power_stat')
|
||||
def test_get_instance_info_off(self, mapping_power_stat, get_power_state):
|
||||
get_power_state.return_value = 'off'
|
||||
mapping_power_stat.return_value = power_state.SHUTDOWN
|
||||
fake_inst = fake_instance.fake_instance_obj(self._context,
|
||||
name='fake', power_state=power_state.SHUTDOWN,
|
||||
memory_mb='1024',
|
||||
vcpus='4')
|
||||
inst_info = self.driver._get_instance_info(fake_inst)
|
||||
mapping_power_stat.assert_called_once_with('off')
|
||||
self.assertEqual(inst_info.state, power_state.SHUTDOWN)
|
||||
|
||||
@mock.patch.object(driver.ZVMDriver, '_get_instance_info')
|
||||
def test_get_info(self, _get_instance_info):
|
||||
_fake_inst_info = hardware.InstanceInfo(state=0x01)
|
||||
_get_instance_info.return_value = _fake_inst_info
|
||||
fake_inst = fake_instance.fake_instance_obj(self._context,
|
||||
name='fake', power_state=power_state.RUNNING,
|
||||
memory_mb='1024',
|
||||
vcpus='4')
|
||||
inst_info = self.driver.get_info(fake_inst)
|
||||
self.assertEqual(0x01, inst_info.state)
|
||||
|
||||
@mock.patch.object(driver.ZVMDriver, '_get_instance_info')
|
||||
def test_get_info_instance_not_exist_error(self, _get_instance_info):
|
||||
_get_instance_info.side_effect = sdkexception.ZVMVirtualMachineNotExist
|
||||
fake_inst = fake_instance.fake_instance_obj(self._context,
|
||||
name='fake', power_state=power_state.RUNNING,
|
||||
memory_mb='1024',
|
||||
vcpus='4')
|
||||
self.assertRaises(nova_exception.InstanceNotFound,
|
||||
self.driver.get_info,
|
||||
fake_inst)
|
||||
@mock.patch('nova_zvm.virt.zvm.utils.zVMConnectorRequestHandler.call')
|
||||
def test_get_available_resource_err_case(self, call):
|
||||
call.side_effect = exception.NovaException
|
||||
results = self.driver.get_available_resource()
|
||||
self.assertEqual(0, results['vcpus'])
|
||||
self.assertEqual(0, results['memory_mb_used'])
|
||||
self.assertEqual(0, results['disk_available_least'])
|
||||
self.assertEqual('', results['hypervisor_hostname'])
|
||||
|
||||
def test_get_available_nodes(self):
|
||||
nodes = self.driver.get_available_nodes()
|
||||
self.assertEqual(nodes[0], 'fakenode')
|
||||
self.assertEqual(['TESTHOST'], nodes)
|
||||
|
||||
@mock.patch.object(sdkapi.SDKAPI, 'guest_get_console_output')
|
||||
def test_get_console_output(self, gco):
|
||||
self.driver.get_console_output({}, self._instance)
|
||||
gco.assert_called_with('test0001')
|
||||
def test_private_mapping_power_stat(self):
|
||||
status = self.driver._mapping_power_stat('on')
|
||||
self.assertEqual(power_state.RUNNING, status)
|
||||
status = self.driver._mapping_power_stat('off')
|
||||
self.assertEqual(power_state.SHUTDOWN, status)
|
||||
status = self.driver._mapping_power_stat('bad')
|
||||
self.assertEqual(power_state.NOSTATE, status)
|
||||
|
||||
@mock.patch.object(sdkapi.SDKAPI, 'guest_start')
|
||||
@mock.patch.object(driver.ZVMDriver, '_wait_network_ready')
|
||||
@mock.patch.object(sdkapi.SDKAPI, 'guest_config_minidisks')
|
||||
@mock.patch.object(sdkapi.SDKAPI, 'guest_deploy')
|
||||
@mock.patch.object(driver.ZVMDriver, '_setup_network')
|
||||
@mock.patch.object(sdkapi.SDKAPI, 'guest_create')
|
||||
@mock.patch.object(zvmutils.ImageUtils, 'import_spawn_image')
|
||||
@mock.patch.object(sdkapi.SDKAPI, 'image_query')
|
||||
@mock.patch.object(zvmutils.VMUtils, 'generate_configdrive')
|
||||
@mock.patch.object(dist.LinuxDistManager, 'get_linux_dist')
|
||||
def _test_spawn(self, mock_linux_dist,
|
||||
generate_configdrive, image_query, import_spawn_image,
|
||||
guest_create, setup_network, guest_deploy,
|
||||
guest_config_minidisks, wait_network_ready,
|
||||
guest_start, image_query_result, eph_disks):
|
||||
generate_configdrive.return_value = '/tmp/fakecfg.tgz'
|
||||
image_query.side_effect = image_query_result
|
||||
@mock.patch('nova_zvm.virt.zvm.utils.zVMConnectorRequestHandler.call')
|
||||
def test_get_info_err_InstanceNotFound(self, call):
|
||||
call.side_effect = exception.NovaException(results={'overallRC': 404})
|
||||
self.assertRaises(exception.InstanceNotFound, self.driver.get_info,
|
||||
self._instance)
|
||||
|
||||
self._block_device_info['ephemerals'] = eph_disks
|
||||
root_disk = {'size': '3g', 'is_boot_disk': True}
|
||||
disk_list = [root_disk]
|
||||
eph_list = []
|
||||
for eph in eph_disks:
|
||||
eph_dict = {'size': '%ig' % eph['size'],
|
||||
'format': (eph['guest_format'] or
|
||||
CONF.default_ephemeral_format or
|
||||
const.DEFAULT_EPH_DISK_FMT)}
|
||||
eph_list.append(eph_dict)
|
||||
if eph_list:
|
||||
disk_list.extend(eph_list)
|
||||
@mock.patch('nova_zvm.virt.zvm.utils.zVMConnectorRequestHandler.call')
|
||||
def test_get_info_err_general(self, call):
|
||||
call.side_effect = exception.NovaException(results={'overallRC': 500})
|
||||
self.assertRaises(exception.NovaException, self.driver.get_info,
|
||||
self._instance)
|
||||
|
||||
os_distro = self._image_meta.properties.os_distro
|
||||
@mock.patch('nova.virt.hardware.InstanceInfo')
|
||||
@mock.patch('nova_zvm.virt.zvm.utils.zVMConnectorRequestHandler.call')
|
||||
def test_get_info(self, call, InstanceInfo):
|
||||
call.return_value = 'on'
|
||||
self.driver.get_info(self._instance)
|
||||
call.assert_called_once_with('guest_get_power_state',
|
||||
self._instance['name'])
|
||||
InstanceInfo.assert_called_once_with(power_state.RUNNING)
|
||||
|
||||
self.driver.spawn(self._context, self._instance, self._image_meta,
|
||||
injected_files=None, admin_password=None,
|
||||
allocations=None,
|
||||
network_info=self._network_info,
|
||||
block_device_info=self._block_device_info,
|
||||
flavor=self._flavor)
|
||||
generate_configdrive.assert_called_once_with(self._context,
|
||||
self._instance,
|
||||
os_distro,
|
||||
self._network_info,
|
||||
None, None)
|
||||
image_query.assert_called_with(self._image_meta.id)
|
||||
if not image_query_result[0]:
|
||||
import_spawn_image.assert_called_once_with(self._context,
|
||||
self._image_meta.id,
|
||||
os_distro)
|
||||
@mock.patch('nova_zvm.virt.zvm.driver.ZVMDriver.list_instances')
|
||||
def test_private_instance_exists_True(self, list_instances):
|
||||
list_instances.return_value = ['vm1', 'vm2']
|
||||
res = self.driver._instance_exists('vm1')
|
||||
self.assertTrue(res)
|
||||
|
||||
guest_create.assert_called_once_with('test0001', 1, 1024, disk_list)
|
||||
setup_network.assert_called_once_with('test0001', self._network_info)
|
||||
guest_deploy.assert_called_once_with('test0001',
|
||||
'rhel7.2-s390x-netboot-0a0c576a_157f_42c8_bde5_2a254d8b77fc',
|
||||
'/tmp/fakecfg.tgz', zvmutils.get_host())
|
||||
@mock.patch('nova_zvm.virt.zvm.driver.ZVMDriver.list_instances')
|
||||
def test_private_instance_exists_False(self, list_instances):
|
||||
list_instances.return_value = ['vm1', 'vm2']
|
||||
res = self.driver._instance_exists('vm3')
|
||||
self.assertFalse(res)
|
||||
|
||||
if eph_disks:
|
||||
guest_config_minidisks.assert_called_once_with('test0001',
|
||||
eph_list)
|
||||
@mock.patch('nova_zvm.virt.zvm.driver.ZVMDriver._instance_exists')
|
||||
def test_instance_exists(self, is_exists):
|
||||
is_exists_response = []
|
||||
is_exists_response.append(True)
|
||||
is_exists_response.append(False)
|
||||
is_exists.side_effect = is_exists_response
|
||||
res = self.driver.instance_exists(self._instance)
|
||||
is_exists.assert_any_call(self._instance.name)
|
||||
self.assertTrue(res)
|
||||
|
||||
wait_network_ready.assert_called_once_with('test0001',
|
||||
self._instance)
|
||||
guest_start.assert_called_once_with('test0001')
|
||||
res = self.driver.instance_exists(self._instance)
|
||||
is_exists.assert_any_call(self._instance.name)
|
||||
self.assertFalse(res)
|
||||
|
||||
def test_spawn_simple_path(self):
|
||||
self._test_spawn(image_query_result=(
|
||||
["rhel7.2-s390x-netboot-0a0c576a_157f_42c8_bde5_2a254d8b77fc"],
|
||||
["rhel7.2-s390x-netboot-0a0c576a_157f_42c8_bde5_2a254d8b77fc"]),
|
||||
eph_disks=[])
|
||||
@mock.patch('nova_zvm.virt.zvm.utils.zVMConnectorRequestHandler.call')
|
||||
def test_private_get_image_info_err(self, call):
|
||||
call.side_effect = exception.NovaException(results={'overallRC': 500})
|
||||
self.assertRaises(exception.NovaException, self.driver._get_image_info,
|
||||
'context', 'image_meta_id', 'os_distro')
|
||||
|
||||
def test_spawn_image_not_in_backend(self):
|
||||
self._test_spawn(image_query_result=(
|
||||
[],
|
||||
["rhel7.2-s390x-netboot-0a0c576a_157f_42c8_bde5_2a254d8b77fc"]),
|
||||
eph_disks=[])
|
||||
@mock.patch('nova_zvm.virt.zvm.utils.zVMConnectorRequestHandler.call')
|
||||
@mock.patch('nova_zvm.virt.zvm.driver.ZVMDriver._import_spawn_image')
|
||||
def test_private_get_image_info(self, image_import, call):
|
||||
call_response = []
|
||||
call_response.append(exception.NovaException(results=
|
||||
{'overallRC': 404}))
|
||||
call_response.append('Query_Result')
|
||||
call.side_effect = call_response
|
||||
self.driver._get_image_info('context', 'image_meta_id', 'os_distro')
|
||||
call.assert_any_call('image_query', imagename='image_meta_id')
|
||||
image_import.assert_called_once_with('context', 'image_meta_id',
|
||||
'os_distro')
|
||||
call.assert_any_call('image_query', imagename='image_meta_id')
|
||||
|
||||
def test_spawn_with_ephemeral_disks(self):
|
||||
self._test_spawn(image_query_result=(
|
||||
["rhel7.2-s390x-netboot-0a0c576a_157f_42c8_bde5_2a254d8b77fc"],
|
||||
["rhel7.2-s390x-netboot-0a0c576a_157f_42c8_bde5_2a254d8b77fc"]),
|
||||
eph_disks=[{'guest_format': u'ext3',
|
||||
'device_name': u'/dev/sdb',
|
||||
'disk_bus': None,
|
||||
'device_type': None,
|
||||
'size': 1},
|
||||
{'guest_format': u'ext4',
|
||||
'device_name': u'/dev/sdc',
|
||||
'disk_bus': None,
|
||||
'device_type': None,
|
||||
'size': 2}])
|
||||
@mock.patch('nova_zvm.virt.zvm.utils.zVMConnectorRequestHandler.call')
|
||||
def test_private_get_image_info_exist(self, call):
|
||||
call.return_value = 'image-info'
|
||||
res = self.driver._get_image_info('context', 'image_meta_id',
|
||||
'os_distro')
|
||||
call.assert_any_call('image_query', imagename='image_meta_id')
|
||||
self.assertEqual('image-info', res)
|
||||
|
||||
@mock.patch.object(driver.ZVMDriver, '_instance_exists')
|
||||
@mock.patch.object(sdkapi.SDKAPI, 'guest_delete')
|
||||
def test_destroy(self, guest_delete, instance_exists):
|
||||
@mock.patch('nova_zvm.virt.zvm.utils.zVMConnectorRequestHandler.call')
|
||||
def _test_set_disk_list(self, call, has_get_root_units=False,
|
||||
has_eph_disks=False):
|
||||
disk_list = [{'is_boot_disk': True, 'size': '3g'}]
|
||||
eph_disk_list = [{'format': u'ext3', 'size': '1g'},
|
||||
{'format': u'ext4', 'size': '2g'}]
|
||||
_inst = copy.copy(self._instance)
|
||||
_bdi = copy.copy(self._block_device_info)
|
||||
|
||||
if has_get_root_units:
|
||||
# overwrite
|
||||
disk_list = [{'is_boot_disk': True, 'size': '3338'}]
|
||||
call.return_value = '3338'
|
||||
_inst['root_gb'] = 0
|
||||
else:
|
||||
_inst['root_gb'] = 3
|
||||
|
||||
if has_eph_disks:
|
||||
disk_list += eph_disk_list
|
||||
else:
|
||||
_bdi['ephemerals'] = []
|
||||
eph_disk_list = []
|
||||
|
||||
res1, res2 = self.driver._set_disk_list(_inst, self._image_meta.id,
|
||||
_bdi)
|
||||
|
||||
if has_get_root_units:
|
||||
call.assert_called_once_with('image_get_root_disk_size',
|
||||
self._image_meta.id)
|
||||
self.assertEqual(disk_list, res1)
|
||||
self.assertEqual(eph_disk_list, res2)
|
||||
|
||||
def test_private_set_disk_list_simple(self):
|
||||
self._test_set_disk_list()
|
||||
|
||||
def test_private_set_disk_list_with_eph_disks(self):
|
||||
self._test_set_disk_list(has_eph_disks=True)
|
||||
|
||||
def test_private_set_disk_list_with_get_root_units(self):
|
||||
self._test_set_disk_list(has_get_root_units=True)
|
||||
|
||||
@mock.patch('nova_zvm.virt.zvm.utils.zVMConnectorRequestHandler.call')
|
||||
def test_private_setup_network(self, call):
|
||||
inst_nets = []
|
||||
_net = {'ip_addr': '192.168.0.100',
|
||||
'gateway_addr': '192.168.0.1',
|
||||
'cidr': '192.168.0.1/24',
|
||||
'mac_addr': 'DE:AD:BE:EF:00:00',
|
||||
'nic_id': None}
|
||||
inst_nets.append(_net)
|
||||
self.driver._setup_network('vm_name', 'os_distro', self._network_info,
|
||||
self._instance)
|
||||
call.assert_any_call('guest_create_network_interface',
|
||||
'vm_name', 'os_distro', inst_nets)
|
||||
|
||||
def test_private_nic_coupled(self):
|
||||
user_direct = {'user_direct':
|
||||
['User TEST',
|
||||
"NICDEF 1000 TYPE QDIO LAN SYSTEM TESTVS"]}
|
||||
res = self.driver._nic_coupled(user_direct, '1000', 'TESTVS')
|
||||
self.assertTrue(res)
|
||||
|
||||
res = self.driver._nic_coupled(user_direct, '2000', 'TESTVS')
|
||||
self.assertFalse(res)
|
||||
|
||||
res = self.driver._nic_coupled(user_direct, '1000', None)
|
||||
self.assertFalse(res)
|
||||
|
||||
@mock.patch('pwd.getpwuid')
|
||||
def test_private_get_host(self, getpwuid):
|
||||
class FakePwuid(object):
|
||||
def __init__(self):
|
||||
self.pw_name = 'test'
|
||||
getpwuid.return_value = FakePwuid()
|
||||
res = self.driver._get_host()
|
||||
self.assertEqual('test@192.168.1.1', res)
|
||||
|
||||
@mock.patch('nova.virt.images.fetch')
|
||||
@mock.patch('os.path.exists')
|
||||
@mock.patch('nova_zvm.virt.zvm.driver.ZVMDriver._get_host')
|
||||
@mock.patch('nova_zvm.virt.zvm.utils.zVMConnectorRequestHandler.call')
|
||||
def test_private_import_spawn_image(self, call, get_host, exists, fetch):
|
||||
get_host.return_value = 'test@192.168.1.1'
|
||||
exists.return_value = False
|
||||
|
||||
image_url = "file:///test/image/image_name"
|
||||
image_meta = {'os_version': 'os_version'}
|
||||
self.driver._import_spawn_image(self._context, 'image_name',
|
||||
'os_version')
|
||||
fetch.assert_called_once_with(self._context, 'image_name',
|
||||
"/test/image/image_name")
|
||||
get_host.assert_called_once_with()
|
||||
call.assert_called_once_with('image_import', 'image_name', image_url,
|
||||
image_meta, remote_host='test@192.168.1.1')
|
||||
|
||||
@mock.patch('nova_zvm.virt.zvm.driver.ZVMDriver._instance_exists')
|
||||
@mock.patch('nova_zvm.virt.zvm.utils.zVMConnectorRequestHandler.call')
|
||||
def test_destroy(self, call, instance_exists):
|
||||
instance_exists.return_value = True
|
||||
self.driver.destroy(self._context, self._instance,
|
||||
network_info=self._network_info)
|
||||
guest_delete.assert_called_once_with(self._instance['name'])
|
||||
call.assert_called_once_with('guest_delete', self._instance['name'])
|
||||
|
||||
@mock.patch.object(driver.ZVMDriver, '_instance_exists')
|
||||
@mock.patch.object(sdkapi.SDKAPI, 'guest_stop')
|
||||
def test_power_off(self, guest_stop, instance_exists):
|
||||
instance_exists.return_value = True
|
||||
self.driver.power_off(self._instance)
|
||||
guest_stop.assert_called_once_with(self._instance['name'], 0, 0)
|
||||
def test_get_host_uptime(self):
|
||||
with mock.patch('nova_zvm.virt.zvm.utils.'
|
||||
'zVMConnectorRequestHandler.call') as mcall:
|
||||
mcall.return_value = {'hypervisor_hostname': 'TESTHOST',
|
||||
'ipl_time': 'TESTTIME'}
|
||||
time = self.driver.get_host_uptime()
|
||||
self.assertEqual('TESTTIME', time)
|
||||
|
||||
@mock.patch.object(driver.ZVMDriver, '_instance_exists')
|
||||
@mock.patch.object(sdkapi.SDKAPI, 'guest_start')
|
||||
def test_power_on(self, guest_start, instance_exists):
|
||||
instance_exists.return_value = True
|
||||
self.driver.power_on(self._context, self._instance,
|
||||
network_info=self._network_info)
|
||||
guest_start.assert_called_once_with(self._instance['name'])
|
||||
def test_spawn_invalid_userid(self):
|
||||
self.flags(instance_name_template='test%05x')
|
||||
self.addCleanup(self.flags, instance_name_template='test%04x')
|
||||
invalid_inst = fake_instance.fake_instance_obj(self._context,
|
||||
name='123456789')
|
||||
self.assertRaises(exception.InvalidInput, self.driver.spawn,
|
||||
self._context, invalid_inst, self._image_meta,
|
||||
injected_files=None, admin_password=None,
|
||||
allocations=None, network_info=self._network_info,
|
||||
block_device_info=self._block_device_info,
|
||||
flavor=self._flavor)
|
||||
|
||||
@mock.patch('nova_zvm.virt.zvm.driver.ZVMDriver._wait_network_ready')
|
||||
@mock.patch('nova_zvm.virt.zvm.driver.ZVMDriver._setup_network')
|
||||
@mock.patch('nova_zvm.virt.zvm.driver.ZVMDriver._get_host')
|
||||
@mock.patch('nova_zvm.virt.zvm.driver.ZVMDriver._set_disk_list')
|
||||
@mock.patch.object(zvmutils.VMUtils, 'generate_configdrive')
|
||||
@mock.patch('nova_zvm.virt.zvm.driver.ZVMDriver._get_image_info')
|
||||
@mock.patch('nova_zvm.virt.zvm.utils.zVMConnectorRequestHandler.call')
|
||||
def test_spawn(self, call, get_image_info, gen_conf_file, set_disk_list,
|
||||
get_host, setup_network, wait_ready):
|
||||
_inst = copy.copy(self._instance)
|
||||
_bdi = copy.copy(self._block_device_info)
|
||||
get_image_info.return_value = [['image_name']]
|
||||
gen_conf_file.return_value = 'transportfiles'
|
||||
set_disk_list.return_value = 'disk_list', 'eph_list'
|
||||
get_host.return_value = 'test@192.168.1.1'
|
||||
setup_network.return_value = ''
|
||||
wait_ready.return_value = ''
|
||||
call_resp = ['', '', '', '']
|
||||
call.side_effect = call_resp
|
||||
|
||||
self.driver.spawn(self._context, _inst, self._image_meta,
|
||||
injected_files=None, admin_password=None,
|
||||
allocations=None, network_info=self._network_info,
|
||||
block_device_info=_bdi, flavor=self._flavor)
|
||||
gen_conf_file.assert_called_once_with(self._context, _inst,
|
||||
None, None)
|
||||
get_image_info.assert_called_once_with(self._context,
|
||||
self._image_meta.id,
|
||||
self._image_meta.properties.os_distro)
|
||||
set_disk_list.assert_called_once_with(_inst, 'image_name', _bdi)
|
||||
call.assert_any_call('guest_create', _inst['name'],
|
||||
1, 1024, disk_list='disk_list')
|
||||
get_host.assert_called_once_with()
|
||||
call.assert_any_call('guest_deploy', _inst['name'], 'image_name',
|
||||
transportfiles='transportfiles',
|
||||
remotehost='test@192.168.1.1')
|
||||
setup_network.assert_called_once_with(_inst['name'],
|
||||
self._image_meta.properties.os_distro,
|
||||
self._network_info, _inst)
|
||||
call.assert_any_call('guest_config_minidisks', _inst['name'],
|
||||
'eph_list')
|
||||
wait_ready.assert_called_once_with(_inst)
|
||||
call.assert_any_call('guest_start', _inst['name'])
|
||||
|
||||
@mock.patch('nova_zvm.virt.zvm.driver.ZVMDriver._nic_coupled')
|
||||
@mock.patch('nova_zvm.virt.zvm.utils.zVMConnectorRequestHandler.call')
|
||||
def test_private_wait_network_ready(self, call, nic_coupled):
|
||||
call_resp = []
|
||||
switch_dict = {'1000': 'TESTVM'}
|
||||
user_direct = {'user_direct':
|
||||
['User TEST',
|
||||
"NICDEF 1000 TYPE QDIO LAN SYSTEM TESTVS"]}
|
||||
call_resp.append(switch_dict)
|
||||
call_resp.append(user_direct)
|
||||
call.side_effect = call_resp
|
||||
nic_coupled.return_value = True
|
||||
self.driver._wait_network_ready(self._instance)
|
||||
call.assert_any_call('guest_get_nic_vswitch_info',
|
||||
self._instance['name'])
|
||||
|
||||
call.assert_any_call('guest_get_definition_info',
|
||||
self._instance['name'])
|
||||
|
|
|
@ -15,6 +15,11 @@
|
|||
from oslo_config import cfg
|
||||
|
||||
zvm_opts = [
|
||||
cfg.StrOpt('zvm_cloud_connector_url',
|
||||
help="""
|
||||
URL to be used to communicate with z/VM Cloud Connector.
|
||||
Example: https://10.10.10.1:8080.
|
||||
"""),
|
||||
cfg.StrOpt('zvm_image_tmp_path',
|
||||
default='/var/lib/nova/images',
|
||||
help="""
|
||||
|
|
|
@ -25,8 +25,6 @@ from oslo_log import log as logging
|
|||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
CONF = cfg.CONF
|
||||
|
||||
|
||||
|
|
|
@ -15,35 +15,31 @@
|
|||
|
||||
import datetime
|
||||
import eventlet
|
||||
import six
|
||||
import os
|
||||
import pwd
|
||||
import time
|
||||
|
||||
from nova import exception as nova_exception
|
||||
from nova.compute import power_state
|
||||
from nova import exception
|
||||
from nova.i18n import _
|
||||
from nova.image import api as image_api
|
||||
from nova.objects import fields as obj_fields
|
||||
from nova.virt import driver
|
||||
from nova.virt import hardware
|
||||
from nova.virt import images
|
||||
from oslo_log import log as logging
|
||||
from oslo_serialization import jsonutils
|
||||
from oslo_service import loopingcall
|
||||
from oslo_utils import excutils
|
||||
from oslo_utils import timeutils
|
||||
from zvmsdk import api as sdkapi
|
||||
from zvmsdk import exception as sdkexception
|
||||
|
||||
from nova_zvm.virt.zvm import conf
|
||||
from nova_zvm.virt.zvm import const
|
||||
from nova_zvm.virt.zvm import exception
|
||||
from nova_zvm.virt.zvm import utils as zvmutils
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
CONF = conf.CONF
|
||||
CONF.import_opt('default_ephemeral_format', 'nova.conf')
|
||||
CONF.import_opt('host', 'nova.conf')
|
||||
CONF.import_opt('my_ip', 'nova.conf')
|
||||
|
||||
|
||||
class ZVMDriver(driver.ComputeDriver):
|
||||
|
@ -58,34 +54,14 @@ class ZVMDriver(driver.ComputeDriver):
|
|||
|
||||
def __init__(self, virtapi):
|
||||
super(ZVMDriver, self).__init__(virtapi)
|
||||
self._sdk_api = sdkapi.SDKAPI()
|
||||
self._reqh = zvmutils.zVMConnectorRequestHandler()
|
||||
self._vmutils = zvmutils.VMUtils()
|
||||
|
||||
self._image_api = image_api.API()
|
||||
self._pathutils = zvmutils.PathUtils()
|
||||
self._imageutils = zvmutils.ImageUtils()
|
||||
self._networkutils = zvmutils.NetworkUtils()
|
||||
self._imageop_semaphore = eventlet.semaphore.Semaphore(1)
|
||||
|
||||
# incremental sleep interval list
|
||||
_inc_slp = [5, 10, 20, 30, 60]
|
||||
_slp = 5
|
||||
|
||||
self._host_stats = []
|
||||
_slp = 5
|
||||
|
||||
while (self._host_stats == []):
|
||||
try:
|
||||
self._host_stats = self.update_host_status()
|
||||
except Exception as e:
|
||||
# Ignore any exceptions and log as warning
|
||||
_slp = len(_inc_slp) != 0 and _inc_slp.pop(0) or _slp
|
||||
msg = _("Failed to get host stats while initializing zVM "
|
||||
"driver due to reason %(reason)s, will re-try in "
|
||||
"%(slp)d seconds")
|
||||
LOG.warning(msg, {'reason': six.text_type(e),
|
||||
'slp': _slp})
|
||||
time.sleep(_slp)
|
||||
# get hypervisor host name
|
||||
res = self._reqh.call('host_get_info')
|
||||
self._hypervisor_hostname = res['hypervisor_hostname']
|
||||
LOG.info("The zVM compute driver has been initialized.")
|
||||
|
||||
def init_host(self, host):
|
||||
"""Initialize anything that is necessary for the driver to function,
|
||||
|
@ -93,35 +69,92 @@ class ZVMDriver(driver.ComputeDriver):
|
|||
"""
|
||||
pass
|
||||
|
||||
def _get_instance_info(self, instance):
|
||||
power_stat = self._sdk_api.guest_get_power_state(instance['name'])
|
||||
power_stat = zvmutils.mapping_power_stat(power_stat)
|
||||
|
||||
_instance_info = hardware.InstanceInfo(power_stat)
|
||||
|
||||
return _instance_info
|
||||
|
||||
def get_info(self, instance):
|
||||
"""Get the current status of an instance."""
|
||||
inst_name = instance['name']
|
||||
|
||||
try:
|
||||
return self._get_instance_info(instance)
|
||||
except sdkexception.ZVMVirtualMachineNotExist:
|
||||
LOG.warning(_("z/VM instance %s does not exist") % inst_name,
|
||||
instance=instance)
|
||||
raise nova_exception.InstanceNotFound(instance_id=inst_name)
|
||||
except Exception as err:
|
||||
# TODO(YDY): raise nova_exception.InstanceNotFound
|
||||
LOG.warning(_("Failed to get the info of z/VM instance %s") %
|
||||
inst_name, instance=instance)
|
||||
raise err
|
||||
|
||||
def list_instances(self):
|
||||
"""Return the names of all the instances known to the virtualization
|
||||
layer, as a list.
|
||||
"""
|
||||
return self._sdk_api.guest_list()
|
||||
return self._reqh.call('guest_list')
|
||||
|
||||
def _get_host_status(self):
|
||||
LOG.debug("Getting host status for %s", CONF.host)
|
||||
|
||||
info = self._reqh.call('host_get_info')
|
||||
|
||||
host_status = {'host': CONF.host,
|
||||
'allowed_vm_type': const.ALLOWED_VM_TYPE}
|
||||
host_status['vcpus'] = info['vcpus']
|
||||
host_status['vcpus_used'] = info['vcpus_used']
|
||||
host_status['cpu_info'] = info['cpu_info']
|
||||
host_status['disk_total'] = info['disk_total']
|
||||
host_status['disk_used'] = info['disk_used']
|
||||
host_status['disk_available'] = info['disk_available']
|
||||
host_status['host_memory_total'] = info['memory_mb']
|
||||
host_status['host_memory_free'] = (info['memory_mb'] -
|
||||
info['memory_mb_used'])
|
||||
host_status['hypervisor_type'] = info['hypervisor_type']
|
||||
host_status['hypervisor_version'] = info['hypervisor_version']
|
||||
host_status['hypervisor_hostname'] = info['hypervisor_hostname']
|
||||
host_status['supported_instances'] = [(const.ARCHITECTURE,
|
||||
const.HYPERVISOR_TYPE,
|
||||
obj_fields.VMMode.HVM)]
|
||||
host_status['ipl_time'] = info['ipl_time']
|
||||
|
||||
return host_status
|
||||
|
||||
def get_available_resource(self, nodename=None):
|
||||
LOG.debug("Getting available resource for %s", CONF.host)
|
||||
|
||||
try:
|
||||
host_stats = self._reqh.call('host_get_info')
|
||||
except exception.NovaException:
|
||||
host_stats = {}
|
||||
|
||||
res = {
|
||||
'vcpus': host_stats.get('vcpus', 0),
|
||||
'memory_mb': host_stats.get('memory_mb', 0),
|
||||
'local_gb': host_stats.get('disk_total', 0),
|
||||
'vcpus_used': 0,
|
||||
'memory_mb_used': host_stats.get('memory_mb_used', 0),
|
||||
'local_gb_used': host_stats.get('disk_used', 0),
|
||||
'hypervisor_type': host_stats.get('hypervisor_type', 'zvm'),
|
||||
'hypervisor_version': host_stats.get('hypervisor_version', ''),
|
||||
'hypervisor_hostname': host_stats.get('hypervisor_hostname', ''),
|
||||
'cpu_info': jsonutils.dumps(host_stats.get('cpu_info', {})),
|
||||
'disk_available_least': host_stats.get('disk_available', 0),
|
||||
'supported_instances': [(const.ARCHITECTURE,
|
||||
const.HYPERVISOR_TYPE,
|
||||
obj_fields.VMMode.HVM)],
|
||||
'numa_topology': None,
|
||||
}
|
||||
|
||||
return res
|
||||
|
||||
def get_available_nodes(self, refresh=False):
|
||||
return [self._hypervisor_hostname]
|
||||
|
||||
def _mapping_power_stat(self, power_stat):
|
||||
"""Translate power state to OpenStack defined constants."""
|
||||
return const.ZVM_POWER_STAT.get(power_stat, power_state.NOSTATE)
|
||||
|
||||
def get_info(self, instance):
|
||||
"""Get the current status of an instance."""
|
||||
power_stat = ''
|
||||
try:
|
||||
power_stat = self._reqh.call('guest_get_power_state',
|
||||
instance['name'])
|
||||
except exception.NovaException as err:
|
||||
if err.kwargs['results']['overallRC'] == 404:
|
||||
# instance not exists
|
||||
LOG.warning("Get power state of non-exist instance: %s",
|
||||
instance['name'])
|
||||
raise exception.InstanceNotFound(instance_id=instance['name'])
|
||||
else:
|
||||
raise
|
||||
|
||||
power_stat = self._mapping_power_stat(power_stat)
|
||||
_instance_info = hardware.InstanceInfo(power_stat)
|
||||
|
||||
return _instance_info
|
||||
|
||||
def _instance_exists(self, instance_name):
|
||||
"""Overwrite this to using instance name as input parameter."""
|
||||
|
@ -134,7 +167,7 @@ class ZVMDriver(driver.ComputeDriver):
|
|||
def spawn(self, context, instance, image_meta, injected_files,
|
||||
admin_password, allocations, network_info=None,
|
||||
block_device_info=None, flavor=None):
|
||||
LOG.info(_("Spawning new instance %s on zVM hypervisor") %
|
||||
LOG.info(_("Spawning new instance %s on zVM hypervisor"),
|
||||
instance['name'], instance=instance)
|
||||
# For zVM instance, limit the maximum length of instance name to \ 8
|
||||
if len(instance['name']) > 8:
|
||||
|
@ -142,114 +175,141 @@ class ZVMDriver(driver.ComputeDriver):
|
|||
"name: %s, please change your instance_name_template to make "
|
||||
"sure the length of instance name is not longer than 8 "
|
||||
"characters") % instance['name'])
|
||||
raise nova_exception.InvalidInput(reason=msg)
|
||||
raise exception.InvalidInput(reason=msg)
|
||||
try:
|
||||
spawn_start = time.time()
|
||||
os_distro = image_meta.properties.os_distro
|
||||
|
||||
# TODO(YaLian) will remove network files from this
|
||||
transportfiles = self._vmutils.generate_configdrive(
|
||||
context, instance, os_distro, network_info,
|
||||
injected_files, admin_password)
|
||||
context, instance, injected_files, admin_password)
|
||||
|
||||
with self._imageop_semaphore:
|
||||
spawn_image_exist = self._sdk_api.image_query(
|
||||
image_meta.id)
|
||||
if not spawn_image_exist:
|
||||
self._imageutils.import_spawn_image(
|
||||
context, image_meta.id, os_distro)
|
||||
resp = self._get_image_info(context, image_meta.id, os_distro)
|
||||
spawn_image_name = resp[0][0]
|
||||
disk_list, eph_list = self._set_disk_list(instance,
|
||||
spawn_image_name,
|
||||
block_device_info)
|
||||
|
||||
spawn_image_name = self._sdk_api.image_query(
|
||||
image_meta.id)[0]
|
||||
if instance['root_gb'] == 0:
|
||||
root_disk_size = self._sdk_api.image_get_root_disk_size(
|
||||
spawn_image_name)
|
||||
else:
|
||||
root_disk_size = '%ig' % instance['root_gb']
|
||||
# Create the guest vm
|
||||
self._reqh.call('guest_create', instance['name'],
|
||||
instance['vcpus'], instance['memory_mb'],
|
||||
disk_list=disk_list)
|
||||
|
||||
disk_list = []
|
||||
root_disk = {'size': root_disk_size,
|
||||
'is_boot_disk': True
|
||||
}
|
||||
disk_list.append(root_disk)
|
||||
ephemeral_disks_info = block_device_info.get('ephemerals', [])
|
||||
eph_list = []
|
||||
for eph in ephemeral_disks_info:
|
||||
eph_dict = {'size': '%ig' % eph['size'],
|
||||
'format': (eph['guest_format'] or
|
||||
CONF.default_ephemeral_format or
|
||||
const.DEFAULT_EPH_DISK_FMT)}
|
||||
eph_list.append(eph_dict)
|
||||
|
||||
if eph_list:
|
||||
disk_list.extend(eph_list)
|
||||
self._sdk_api.guest_create(instance['name'], instance['vcpus'],
|
||||
instance['memory_mb'], disk_list)
|
||||
# Deploy image to the guest vm
|
||||
remotehost = self._get_host()
|
||||
self._reqh.call('guest_deploy', instance['name'],
|
||||
spawn_image_name, transportfiles=transportfiles,
|
||||
remotehost=remotehost)
|
||||
|
||||
# Setup network for z/VM instance
|
||||
self._setup_network(instance['name'], network_info)
|
||||
self._sdk_api.guest_deploy(instance['name'], spawn_image_name,
|
||||
transportfiles, zvmutils.get_host())
|
||||
self._setup_network(instance['name'], os_distro, network_info,
|
||||
instance)
|
||||
|
||||
# Handle ephemeral disks
|
||||
if eph_list:
|
||||
self._sdk_api.guest_config_minidisks(instance['name'],
|
||||
eph_list)
|
||||
self._reqh.call('guest_config_minidisks',
|
||||
instance['name'], eph_list)
|
||||
|
||||
self._wait_network_ready(instance['name'], instance)
|
||||
self._wait_network_ready(instance)
|
||||
|
||||
self._sdk_api.guest_start(instance['name'])
|
||||
self._reqh.call('guest_start', instance['name'])
|
||||
spawn_time = time.time() - spawn_start
|
||||
LOG.info(_("Instance spawned succeeded in %s seconds") %
|
||||
LOG.info(_("Instance spawned succeeded in %s seconds"),
|
||||
spawn_time, instance=instance)
|
||||
except Exception as err:
|
||||
with excutils.save_and_reraise_exception():
|
||||
LOG.error(_("Deploy image to instance %(instance)s "
|
||||
"failed with reason: %(err)s") %
|
||||
"failed with reason: %(err)s"),
|
||||
{'instance': instance['name'], 'err': err},
|
||||
instance=instance)
|
||||
self.destroy(context, instance, network_info,
|
||||
block_device_info)
|
||||
|
||||
def _setup_network(self, vm_name, network_info):
|
||||
LOG.debug("Creating NICs for vm %s", vm_name)
|
||||
manage_IP_set = False
|
||||
for vif in network_info:
|
||||
if not manage_IP_set:
|
||||
network = vif['network']
|
||||
ip_addr = network['subnets'][0]['ips'][0]['address']
|
||||
self._sdk_api.guest_create_nic(vm_name, nic_id=vif['id'],
|
||||
mac_addr=vif['address'],
|
||||
ip_addr=ip_addr)
|
||||
manage_IP_set = True
|
||||
def _get_image_info(self, context, image_meta_id, os_distro):
|
||||
spawn_image_exist = False
|
||||
try:
|
||||
spawn_image_exist = self._reqh.call('image_query',
|
||||
imagename=image_meta_id)
|
||||
except exception.NovaException as err:
|
||||
if err.kwargs['results']['overallRC'] == 404:
|
||||
# image not exist, nothing to do
|
||||
pass
|
||||
else:
|
||||
self._sdk_api.guest_create_nic(vm_name, nic_id=vif['id'],
|
||||
mac_addr=vif['address'])
|
||||
raise err
|
||||
|
||||
def _wait_network_ready(self, inst_name, instance):
|
||||
if not spawn_image_exist:
|
||||
with self._imageop_semaphore:
|
||||
self._import_spawn_image(context, image_meta_id, os_distro)
|
||||
return self._reqh.call('image_query', imagename=image_meta_id)
|
||||
else:
|
||||
return spawn_image_exist
|
||||
|
||||
def _set_disk_list(self, instance, image_name, block_device_info):
|
||||
if instance['root_gb'] == 0:
|
||||
root_disk_size = self._reqh.call('image_get_root_disk_size',
|
||||
image_name)
|
||||
else:
|
||||
root_disk_size = '%ig' % instance['root_gb']
|
||||
|
||||
disk_list = []
|
||||
root_disk = {'size': root_disk_size,
|
||||
'is_boot_disk': True
|
||||
}
|
||||
disk_list.append(root_disk)
|
||||
ephemeral_disks_info = block_device_info.get('ephemerals', [])
|
||||
eph_list = []
|
||||
for eph in ephemeral_disks_info:
|
||||
eph_dict = {'size': '%ig' % eph['size'],
|
||||
'format': (eph['guest_format'] or
|
||||
CONF.default_ephemeral_format or
|
||||
const.DEFAULT_EPH_DISK_FMT)}
|
||||
eph_list.append(eph_dict)
|
||||
|
||||
if eph_list:
|
||||
disk_list.extend(eph_list)
|
||||
return disk_list, eph_list
|
||||
|
||||
def _setup_network(self, vm_name, os_distro, network_info, instance):
|
||||
LOG.debug("Creating NICs for vm %s", vm_name)
|
||||
inst_nets = []
|
||||
for vif in network_info:
|
||||
subnet = vif['network']['subnets'][0]
|
||||
_net = {'ip_addr': subnet['ips'][0]['address'],
|
||||
'gateway_addr': subnet['gateway']['address'],
|
||||
'cidr': subnet['cidr'],
|
||||
'mac_addr': vif['address'],
|
||||
'nic_id': vif['id']}
|
||||
inst_nets.append(_net)
|
||||
|
||||
if inst_nets:
|
||||
self._reqh.call('guest_create_network_interface',
|
||||
vm_name, os_distro, inst_nets)
|
||||
|
||||
def _wait_network_ready(self, instance):
|
||||
"""Wait until neutron zvm-agent add all NICs to vm"""
|
||||
inst_name = instance['name']
|
||||
|
||||
def _wait_for_nics_add_in_vm(inst_name, expiration):
|
||||
if (CONF.zvm_reachable_timeout and
|
||||
timeutils.utcnow() > expiration):
|
||||
msg = _("NIC update check failed "
|
||||
"on instance:%s") % instance.uuid
|
||||
raise exception.ZVMNetworkError(msg=msg)
|
||||
raise exception.NovaException(message=msg)
|
||||
|
||||
try:
|
||||
switch_dict = self._sdk_api.guest_get_nic_vswitch_info(
|
||||
inst_name)
|
||||
if switch_dict and '' not in switch_dict.values():
|
||||
for key in switch_dict:
|
||||
result = self._sdk_api.guest_get_definition_info(
|
||||
inst_name, nic_coupled=key)
|
||||
if not result['nic_coupled']:
|
||||
switch_dict = self._reqh.call('guest_get_nic_vswitch_info',
|
||||
inst_name)
|
||||
if switch_dict and None not in switch_dict.values():
|
||||
for key, value in switch_dict.items():
|
||||
user_direct = self._reqh.call(
|
||||
'guest_get_definition_info',
|
||||
inst_name)
|
||||
if not self._nic_coupled(user_direct, key, value):
|
||||
return
|
||||
else:
|
||||
# In this case, the nic switch info is not ready yet
|
||||
# need another loop to check until time out or find it
|
||||
return
|
||||
|
||||
except exception.ZVMBaseException as e:
|
||||
except Exception as e:
|
||||
# Ignore any zvm driver exceptions
|
||||
LOG.info(_('encounter error %s during get vswitch info'),
|
||||
e.format_message(), instance=instance)
|
||||
|
@ -268,136 +328,44 @@ class ZVMDriver(driver.ComputeDriver):
|
|||
_wait_for_nics_add_in_vm, inst_name, expiration)
|
||||
timer.start(interval=10).wait()
|
||||
|
||||
@property
|
||||
def need_legacy_block_device_info(self):
|
||||
def _nic_coupled(self, user_direct, vdev, vswitch):
|
||||
if vswitch is None:
|
||||
return False
|
||||
direct_info = user_direct['user_direct']
|
||||
nic_str = ("NICDEF %s TYPE QDIO LAN SYSTEM %s" %
|
||||
(vdev.upper(), vswitch.upper()))
|
||||
for info in direct_info:
|
||||
if nic_str in info:
|
||||
return True
|
||||
return False
|
||||
|
||||
def _get_host(self):
|
||||
return ''.join([pwd.getpwuid(os.geteuid()).pw_name, '@', CONF.my_ip])
|
||||
|
||||
def _import_spawn_image(self, context, image_href, image_os_version):
|
||||
LOG.debug("Downloading the image %s from glance to nova compute "
|
||||
"server", image_href)
|
||||
image_path = os.path.join(os.path.normpath(CONF.zvm_image_tmp_path),
|
||||
image_href)
|
||||
if not os.path.exists(image_path):
|
||||
images.fetch(context, image_href, image_path)
|
||||
image_url = "file://" + image_path
|
||||
image_meta = {'os_version': image_os_version}
|
||||
remote_host = self._get_host()
|
||||
self._reqh.call('image_import', image_href, image_url,
|
||||
image_meta, remote_host=remote_host)
|
||||
|
||||
def destroy(self, context, instance, network_info=None,
|
||||
block_device_info=None, destroy_disks=False):
|
||||
|
||||
inst_name = instance['name']
|
||||
if self._instance_exists(inst_name):
|
||||
LOG.info(_("Destroying instance %s"), inst_name,
|
||||
instance=instance)
|
||||
self._sdk_api.guest_delete(inst_name)
|
||||
self._reqh.call('guest_delete', inst_name)
|
||||
else:
|
||||
LOG.warning(_('Instance %s does not exist'), inst_name,
|
||||
instance=instance)
|
||||
|
||||
def attach_volume(self, context, connection_info, instance, mountpoint,
|
||||
disk_bus=None, device_type=None, encryption=None):
|
||||
"""Attach the disk to the instance at mountpoint using info."""
|
||||
pass
|
||||
|
||||
def detach_volume(self, connection_info, instance, mountpoint=None,
|
||||
encryption=None):
|
||||
"""Detach the disk attached to the instance."""
|
||||
pass
|
||||
|
||||
def power_off(self, instance, timeout=0, retry_interval=0):
|
||||
"""Power off the specified instance."""
|
||||
inst_name = instance['name']
|
||||
if self._instance_exists(inst_name):
|
||||
LOG.info(_("Powering OFF instance %s"), inst_name,
|
||||
instance=instance)
|
||||
self._sdk_api.guest_stop(inst_name, timeout, retry_interval)
|
||||
else:
|
||||
LOG.warning(_('Instance %s does not exist'), inst_name,
|
||||
instance=instance)
|
||||
|
||||
def power_on(self, context, instance, network_info,
|
||||
block_device_info=None):
|
||||
"""Power on the specified instance."""
|
||||
inst_name = instance['name']
|
||||
if self._instance_exists(inst_name):
|
||||
LOG.info(_("Powering ON instance %s"), inst_name,
|
||||
instance=instance)
|
||||
self._sdk_api.guest_start(inst_name)
|
||||
else:
|
||||
LOG.warning(_('Instance %s does not exist'), inst_name,
|
||||
instance=instance)
|
||||
|
||||
def get_available_resource(self, nodename=None):
|
||||
"""Retrieve resource information.
|
||||
|
||||
This method is called when nova-compute launches, and
|
||||
as part of a periodic task
|
||||
|
||||
:param nodename:
|
||||
node which the caller want to get resources from
|
||||
a driver that manages only one node can safely ignore this
|
||||
:returns: Dictionary describing resources
|
||||
|
||||
"""
|
||||
LOG.debug("Getting available resource for %s" % CONF.host)
|
||||
stats = self.update_host_status()[0]
|
||||
|
||||
mem_used = stats['host_memory_total'] - stats['host_memory_free']
|
||||
supported_instances = stats['supported_instances']
|
||||
dic = {
|
||||
'vcpus': stats['vcpus'],
|
||||
'memory_mb': stats['host_memory_total'],
|
||||
'local_gb': stats['disk_total'],
|
||||
'vcpus_used': stats['vcpus_used'],
|
||||
'memory_mb_used': mem_used,
|
||||
'local_gb_used': stats['disk_used'],
|
||||
'hypervisor_type': stats['hypervisor_type'],
|
||||
'hypervisor_version': stats['hypervisor_version'],
|
||||
'hypervisor_hostname': stats['hypervisor_hostname'],
|
||||
'cpu_info': jsonutils.dumps(stats['cpu_info']),
|
||||
'disk_available_least': stats['disk_available'],
|
||||
'supported_instances': supported_instances,
|
||||
'numa_topology': None,
|
||||
}
|
||||
|
||||
return dic
|
||||
|
||||
def ensure_filtering_rules_for_instance(self, instance_ref, network_info):
|
||||
# It enforces security groups on host initialization and live
|
||||
# migration. In z/VM we do not assume instances running upon host
|
||||
# initialization
|
||||
return
|
||||
|
||||
def update_host_status(self):
|
||||
"""Refresh host stats. One compute service entry possibly
|
||||
manages several hypervisors, so will return a list of host
|
||||
status information.
|
||||
"""
|
||||
LOG.debug("Updating host status for %s" % CONF.host)
|
||||
|
||||
caps = []
|
||||
|
||||
info = self._sdk_api.host_get_info()
|
||||
|
||||
data = {'host': CONF.host,
|
||||
'allowed_vm_type': const.ALLOWED_VM_TYPE}
|
||||
data['vcpus'] = info['vcpus']
|
||||
data['vcpus_used'] = info['vcpus_used']
|
||||
data['cpu_info'] = info['cpu_info']
|
||||
data['disk_total'] = info['disk_total']
|
||||
data['disk_used'] = info['disk_used']
|
||||
data['disk_available'] = info['disk_available']
|
||||
data['host_memory_total'] = info['memory_mb']
|
||||
data['host_memory_free'] = (info['memory_mb'] -
|
||||
info['memory_mb_used'])
|
||||
data['hypervisor_type'] = info['hypervisor_type']
|
||||
data['hypervisor_version'] = info['hypervisor_version']
|
||||
data['hypervisor_hostname'] = info['hypervisor_hostname']
|
||||
data['supported_instances'] = [(const.ARCHITECTURE,
|
||||
const.HYPERVISOR_TYPE,
|
||||
obj_fields.VMMode.HVM)]
|
||||
data['ipl_time'] = info['ipl_time']
|
||||
|
||||
caps.append(data)
|
||||
|
||||
return caps
|
||||
|
||||
def get_console_output(self, context, instance):
|
||||
return self._sdk_api.guest_get_console_output(instance.name)
|
||||
|
||||
def get_host_uptime(self):
|
||||
return self._host_stats[0]['ipl_time']
|
||||
|
||||
def get_available_nodes(self, refresh=False):
|
||||
return [d['hypervisor_hostname'] for d in self._host_stats
|
||||
if (d.get('hypervisor_hostname') is not None)]
|
||||
res = self._reqh.call('host_get_info')
|
||||
return res['ipl_time']
|
||||
|
|
|
@ -1,46 +0,0 @@
|
|||
# Copyright 2013 IBM Corp.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
|
||||
from nova import exception
|
||||
from nova.i18n import _
|
||||
|
||||
|
||||
class ZVMBaseException(exception.NovaException):
|
||||
"""Base z/VM exception."""
|
||||
pass
|
||||
|
||||
|
||||
class ZVMDriverError(ZVMBaseException):
|
||||
msg_fmt = _('z/VM driver error: %(msg)s')
|
||||
|
||||
|
||||
class ZVMVolumeError(ZVMBaseException):
|
||||
msg_fmt = _('Volume error: %(msg)s')
|
||||
|
||||
|
||||
class ZVMImageError(ZVMBaseException):
|
||||
msg_fmt = _("Image error: %(msg)s")
|
||||
|
||||
|
||||
class ZVMNetworkError(ZVMBaseException):
|
||||
msg_fmt = _("z/VM network error: %(msg)s")
|
||||
|
||||
|
||||
class ZVMConfigDriveError(ZVMBaseException):
|
||||
msg_fmt = _('Create configure drive failed: %(msg)s')
|
||||
|
||||
|
||||
class ZVMRetryException(ZVMBaseException):
|
||||
pass
|
|
@ -14,31 +14,25 @@
|
|||
|
||||
|
||||
import os
|
||||
import pwd
|
||||
|
||||
from nova.api.metadata import base as instance_metadata
|
||||
from nova import block_device
|
||||
from nova.compute import power_state
|
||||
from nova import exception
|
||||
from nova.i18n import _
|
||||
from nova.virt import configdrive
|
||||
from nova.virt import driver
|
||||
from nova.virt import images
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
from zvmsdk import api as zvm_api
|
||||
from zvmsdk import dist
|
||||
import six.moves.urllib.parse as urlparse
|
||||
from zvmconnector import connector
|
||||
|
||||
from nova_zvm.virt.zvm import conf
|
||||
from nova_zvm.virt.zvm import configdrive as zvmconfigdrive
|
||||
from nova_zvm.virt.zvm import const
|
||||
from nova_zvm.virt.zvm import exception
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
CONF = cfg.CONF
|
||||
CONF = conf.CONF
|
||||
|
||||
CONF.import_opt('host', 'nova.conf')
|
||||
CONF.import_opt('instances_path', 'nova.compute.manager')
|
||||
CONF.import_opt('my_ip', 'nova.conf')
|
||||
|
||||
|
||||
def mapping_power_stat(power_stat):
|
||||
|
@ -46,30 +40,23 @@ def mapping_power_stat(power_stat):
|
|||
return const.ZVM_POWER_STAT.get(power_stat, power_state.NOSTATE)
|
||||
|
||||
|
||||
def _volume_in_mapping(mount_device, block_device_info):
|
||||
block_device_list = [block_device.strip_dev(vol['mount_device'])
|
||||
for vol in
|
||||
driver.block_device_info_get_mapping(
|
||||
block_device_info)]
|
||||
LOG.debug("block_device_list %s", block_device_list)
|
||||
return block_device.strip_dev(mount_device) in block_device_list
|
||||
class zVMConnectorRequestHandler(object):
|
||||
|
||||
def __init__(self):
|
||||
_url = urlparse.urlparse(CONF.zvm_cloud_connector_url)
|
||||
self._conn = connector.ZVMConnector(_url.hostname, _url.port)
|
||||
|
||||
def is_volume_root(root_device, mountpoint):
|
||||
"""This judges if the moutpoint equals the root_device."""
|
||||
return block_device.strip_dev(mountpoint) == block_device.strip_dev(
|
||||
root_device)
|
||||
|
||||
|
||||
def is_boot_from_volume(block_device_info):
|
||||
root_mount_device = driver.block_device_info_get_root(block_device_info)
|
||||
boot_from_volume = _volume_in_mapping(root_mount_device,
|
||||
block_device_info)
|
||||
return root_mount_device, boot_from_volume
|
||||
|
||||
|
||||
def get_host():
|
||||
return ''.join([pwd.getpwuid(os.geteuid()).pw_name, '@', CONF.my_ip])
|
||||
def call(self, func_name, *args, **kwargs):
|
||||
results = self._conn.send_request(func_name, *args, **kwargs)
|
||||
if results['overallRC'] == 0:
|
||||
return results['output']
|
||||
else:
|
||||
msg = ("SDK request %(api)s failed with parameters: %(args)s "
|
||||
"%(kwargs)s . Results: %(results)s" %
|
||||
{'api': func_name, 'args': str(args), 'kwargs': str(kwargs),
|
||||
'results': str(results)})
|
||||
LOG.debug(msg)
|
||||
raise exception.NovaException(message=msg, results=results)
|
||||
|
||||
|
||||
class PathUtils(object):
|
||||
|
@ -80,61 +67,40 @@ class PathUtils(object):
|
|||
instance_folder = os.path.join(self._get_instances_path(),
|
||||
instance_uuid)
|
||||
if not os.path.exists(instance_folder):
|
||||
LOG.debug("Creating the instance path %s" % instance_folder)
|
||||
LOG.debug("Creating the instance path %s", instance_folder)
|
||||
os.makedirs(instance_folder)
|
||||
return instance_folder
|
||||
|
||||
def get_console_log_path(self, os_node, instance_name):
|
||||
return os.path.join(self.get_instance_path(os_node, instance_name),
|
||||
"console.log")
|
||||
|
||||
|
||||
class NetworkUtils(object):
|
||||
"""Utilities for z/VM network operator."""
|
||||
pass
|
||||
|
||||
|
||||
class VMUtils(object):
|
||||
def __init__(self):
|
||||
self._sdk_api = zvm_api.SDKAPI()
|
||||
self._dist_manager = dist.LinuxDistManager()
|
||||
self._pathutils = PathUtils()
|
||||
self._imageutils = ImageUtils()
|
||||
|
||||
# Prepare and create configdrive for instance
|
||||
def generate_configdrive(self, context, instance, os_version,
|
||||
network_info, injected_files, admin_password):
|
||||
def generate_configdrive(self, context, instance, injected_files,
|
||||
admin_password):
|
||||
# Create network configuration files
|
||||
LOG.debug('Creating network configuration files '
|
||||
'for instance: %s' % instance['name'], instance=instance)
|
||||
'for instance: %s', instance['name'], instance=instance)
|
||||
|
||||
linuxdist = self._dist_manager.get_linux_dist(os_version)()
|
||||
instance_path = self._pathutils.get_instance_path(instance['uuid'])
|
||||
|
||||
files_and_cmds = linuxdist.create_network_configuration_files(
|
||||
instance_path, network_info)
|
||||
(net_conf_files, net_conf_cmds) = files_and_cmds
|
||||
# Add network configure files to inject_files
|
||||
if len(net_conf_files) > 0:
|
||||
injected_files.extend(net_conf_files)
|
||||
|
||||
transportfiles = None
|
||||
if configdrive.required_by(instance):
|
||||
transportfiles = self._create_config_drive(context, instance_path,
|
||||
instance,
|
||||
injected_files,
|
||||
admin_password,
|
||||
net_conf_cmds,
|
||||
linuxdist)
|
||||
admin_password)
|
||||
return transportfiles
|
||||
|
||||
def _create_config_drive(self, context, instance_path, instance,
|
||||
injected_files, admin_password, commands,
|
||||
linuxdist):
|
||||
injected_files, admin_password):
|
||||
if CONF.config_drive_format not in ['tgz', 'iso9660']:
|
||||
msg = (_("Invalid config drive format %s") %
|
||||
CONF.config_drive_format)
|
||||
raise exception.ZVMConfigDriveError(msg=msg)
|
||||
LOG.debug(msg)
|
||||
raise exception.ConfigDriveUnsupportedFormat(
|
||||
format=CONF.config_drive_format)
|
||||
|
||||
LOG.debug('Using config drive', instance=instance)
|
||||
|
||||
|
@ -142,19 +108,6 @@ class VMUtils(object):
|
|||
if admin_password:
|
||||
extra_md['admin_pass'] = admin_password
|
||||
|
||||
udev_settle = linuxdist.get_znetconfig_contents()
|
||||
if udev_settle:
|
||||
if len(commands) == 0:
|
||||
znetconfig = '\n'.join(('#!/bin/bash', udev_settle))
|
||||
else:
|
||||
znetconfig = '\n'.join(('#!/bin/bash', commands, udev_settle))
|
||||
znetconfig += '\nrm -rf /tmp/znetconfig.sh\n'
|
||||
# Create a temp file in instance to execute above commands
|
||||
net_cmd_file = []
|
||||
net_cmd_file.append(('/tmp/znetconfig.sh', znetconfig)) # nosec
|
||||
injected_files.extend(net_cmd_file)
|
||||
# injected_files.extend(('/tmp/znetconfig.sh', znetconfig))
|
||||
|
||||
inst_md = instance_metadata.InstanceMetadata(instance,
|
||||
content=injected_files,
|
||||
extra_md=extra_md,
|
||||
|
@ -165,30 +118,9 @@ class VMUtils(object):
|
|||
|
||||
configdrive_tgz = os.path.join(instance_path, 'cfgdrive.tgz')
|
||||
|
||||
LOG.debug('Creating config drive at %s' % configdrive_tgz,
|
||||
LOG.debug('Creating config drive at %s', configdrive_tgz,
|
||||
instance=instance)
|
||||
with zvmconfigdrive.ZVMConfigDriveBuilder(instance_md=inst_md) as cdb:
|
||||
cdb.make_drive(configdrive_tgz)
|
||||
|
||||
return configdrive_tgz
|
||||
|
||||
|
||||
class ImageUtils(object):
|
||||
|
||||
def __init__(self):
|
||||
self._pathutils = PathUtils()
|
||||
self._sdk_api = zvm_api.SDKAPI()
|
||||
|
||||
def import_spawn_image(self, context, image_href, image_os_version):
|
||||
LOG.debug("Downloading the image %s from glance to nova compute "
|
||||
"server" % image_href)
|
||||
|
||||
image_path = os.path.join(os.path.normpath(CONF.zvm_image_tmp_path),
|
||||
image_href)
|
||||
if not os.path.exists(image_path):
|
||||
images.fetch(context, image_href, image_path)
|
||||
image_url = "file://" + image_path
|
||||
image_meta = {'os_version': image_os_version}
|
||||
remote_host = get_host()
|
||||
self._sdk_api.image_import(image_url, image_meta=image_meta,
|
||||
remote_host=remote_host)
|
||||
|
|
|
@ -9,4 +9,4 @@ oslo.service>=1.10.0 # Apache-2.0
|
|||
oslo.utils>=3.20.0 # Apache-2.0
|
||||
six>=1.9.0
|
||||
|
||||
CloudLib4zvm>=0.2.2
|
||||
zVMCloudConnector>=0.3.2 # Apache 2.0 License
|
||||
|
|
|
@ -19,3 +19,4 @@ vine
|
|||
wsgi-intercept>=1.4.1 # MIT License
|
||||
eventlet!=0.18.3,!=0.20.1,<0.21.0,>=0.18.2 # MIT
|
||||
sphinxcontrib-actdiag # BSD
|
||||
python-memcached>=1.56
|
||||
|
|
Loading…
Reference in New Issue