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:
Huang Rui 2017-12-14 13:59:08 +08:00
parent 9704803789
commit 369b0b1674
9 changed files with 577 additions and 645 deletions

View File

@ -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)

View File

@ -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'])

View File

@ -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="""

View File

@ -25,8 +25,6 @@ from oslo_log import log as logging
LOG = logging.getLogger(__name__)
CONF = cfg.CONF

View File

@ -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']

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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