SR-IOV cannot be enabled with non-KVM hypervisor

Change-Id: I619de0fbd6b9250ffda8dce9a766fba27c2fb4e2
Partial-bug: #1563254
This commit is contained in:
slava 2016-03-30 00:43:32 +03:00 committed by Valyavskiy Viacheslav
parent 9b89b6d191
commit 9ffc2baa54
4 changed files with 84 additions and 57 deletions

View File

@ -443,39 +443,48 @@ class NetAssignmentValidator(BasicValidator):
return interfaces_data
@classmethod
def _verify_sriov_properties(cls, iface, data, node_id):
def _verify_sriov_properties(cls, iface, data, db_node):
non_changeable = ['sriov_totalvfs', 'available', 'pci_id']
sriov_new = data['interface_properties']['sriov']
check_for_changes = [n for n in sriov_new if n in non_changeable]
if not check_for_changes:
return
sriov_db = iface.interface_properties['sriov']
if sriov_new['enabled']:
# check hypervisor type
h_type = objects.Cluster.get_editable_attributes(
db_node.cluster)['common']['libvirt_type']['value']
if h_type != consts.HYPERVISORS.kvm:
raise errors.InvalidData(
'Only KVM hypervisor works with SR-IOV.')
for param_name in check_for_changes:
if sriov_db[param_name] != sriov_new[param_name]:
raise errors.InvalidData(
"Node '{0}' interface '{1}': SR-IOV parameter '{2}' cannot"
" be changed through API".format(
node_id, iface.name, param_name),
db_node.id, iface.name, param_name),
log_message=True
)
if not sriov_db['available'] and sriov_new['enabled']:
raise errors.InvalidData(
"Node '{0}' interface '{1}': SR-IOV cannot be enabled as it is"
" not available".format(node_id, iface.name),
" not available".format(db_node.id, iface.name),
log_message=True
)
if not sriov_new['sriov_numvfs'] and sriov_new['enabled']:
raise errors.InvalidData(
"Node '{0}' interface '{1}': virtual functions can not be"
" enabled for interface when 'sriov_numfs' option is not"
" specified!".format(node_id, iface.name),
" specified!".format(db_node.id, iface.name),
log_message=True
)
if sriov_db['sriov_totalvfs'] < sriov_new['sriov_numvfs']:
raise errors.InvalidData(
"Node '{0}' interface '{1}': '{2}' virtual functions was"
"requested but just '{3}' are available".format(
node_id, iface.name, sriov_new['sriov_numvfs'],
db_node.id, iface.name, sriov_new['sriov_numvfs'],
sriov_db['sriov_totalvfs']),
log_message=True
)
@ -577,7 +586,7 @@ class NetAssignmentValidator(BasicValidator):
h_type = objects.Cluster.get_editable_attributes(
db_node.cluster)['common']['libvirt_type']['value']
if h_type != 'kvm':
if h_type != consts.HYPERVISORS.kvm:
raise errors.InvalidData('Only KVM hypervisor works with DPDK.')
@classmethod
@ -639,7 +648,7 @@ class NetAssignmentValidator(BasicValidator):
log_message=True
)
if iface.get('interface_properties', {}).get('sriov'):
cls._verify_sriov_properties(db_iface, iface, node['id'])
cls._verify_sriov_properties(db_iface, iface, db_node)
elif iface['type'] == consts.NETWORK_INTERFACE_TYPES.bond:
pxe_iface_present = False

View File

@ -514,3 +514,8 @@ DEFAULT_HUGEPAGE_SIZE = '2048'
HUGE_PAGES_SIZE_MAP = [('2048', '2M'), ('1048576', '1G')]
MEMORY_RESERVED_FOR_OPERATING_SYSTEM = 1024 ** 3 # one GiB in bytes
HYPERVISORS = Enum(
"kvm",
"qemu"
)

View File

@ -796,11 +796,25 @@ class TestHandlers(BaseIntegrationTest):
)
self.assertEqual(resp.status_code, 200)
def test_get_update_sriov_properties(self):
class TestSriovHandlers(BaseIntegrationTest):
def setUp(self):
super(TestSriovHandlers, self).setUp()
self.env.create(
nodes_kwargs=[{"api": True}]
cluster_kwargs={
'editable_attributes': {
'common': {
'libvirt_type': {
'value': consts.HYPERVISORS.kvm
}
}
}
},
nodes_kwargs=[{"api": False}]
)
def test_get_update_sriov_properties(self):
resp = self.app.get(
reverse('NodeNICsHandler',
kwargs={'node_id': self.env.nodes[0].id}),
@ -839,10 +853,6 @@ class TestHandlers(BaseIntegrationTest):
self.assertEqual(sriov['physnet'], 'new_physnet')
def test_update_readonly_sriov_properties_failed(self):
self.env.create(
nodes_kwargs=[{"api": True}]
)
resp = self.app.get(
reverse('NodeNICsHandler',
kwargs={'node_id': self.env.nodes[0].id}),
@ -867,10 +877,6 @@ class TestHandlers(BaseIntegrationTest):
self.env.nodes[0].id, nics[0]['name']))
def test_enable_sriov_failed(self):
self.env.create(
nodes_kwargs=[{"api": True}]
)
resp = self.app.get(
reverse('NodeNICsHandler',
kwargs={'node_id': self.env.nodes[0].id}),
@ -894,10 +900,6 @@ class TestHandlers(BaseIntegrationTest):
" not available".format(self.env.nodes[0].id, nics[0]['name']))
def test_set_sriov_numvfs_failed(self):
self.env.create(
nodes_kwargs=[{"api": True}]
)
resp = self.app.get(
reverse('NodeNICsHandler',
kwargs={'node_id': self.env.nodes[0].id}),
@ -922,10 +924,6 @@ class TestHandlers(BaseIntegrationTest):
self.env.nodes[0].id, nics[0]['name']))
def test_set_sriov_numvfs_failed_negative_value(self):
self.env.create(
nodes_kwargs=[{"api": True}]
)
resp = self.app.get(
reverse('NodeNICsHandler',
kwargs={'node_id': self.env.nodes[0].id}),
@ -949,10 +947,6 @@ class TestHandlers(BaseIntegrationTest):
)
def test_set_sriov_numvfs_failed_float_value(self):
self.env.create(
nodes_kwargs=[{"api": True}]
)
resp = self.app.get(
reverse('NodeNICsHandler',
kwargs={'node_id': self.env.nodes[0].id}),
@ -976,10 +970,6 @@ class TestHandlers(BaseIntegrationTest):
)
def test_set_sriov_numvfs_zero_value(self):
self.env.create(
nodes_kwargs=[{"api": True}]
)
resp = self.app.get(
reverse('NodeNICsHandler',
kwargs={'node_id': self.env.nodes[0].id}),
@ -1003,27 +993,51 @@ class TestHandlers(BaseIntegrationTest):
)
def test_enable_sriov_without_number_of_functions(self):
meta = self.env.default_metadata()
self.env.set_interfaces_in_meta(meta, [
{'name': 'new_nic',
'mac': '00:00:00:00:00:00',
'current_speed': 10,
'max_speed': 10,
'state': 'down',
'interface_properties': {
'sriov': {
'sriov_totalvfs': 8,
'available': True,
'pci_id': '1234:5678'
},
'pci_id': '8765:4321',
'numa_node': 1
}}]
# change NIC properties in DB as SR-IOV parameters can be set up only
# for NICs that have hardware SR-IOV support
nic = objects.NIC.get_by_uid(self.env.nodes[0].nic_interfaces[0].id)
nic.interface_properties['sriov']['available'] = True
nic.interface_properties['sriov']['sriov_totalvfs'] = 8
nic.interface_properties.changed()
resp = self.app.get(
reverse('NodeNICsHandler',
kwargs={'node_id': self.env.nodes[0].id}),
headers=self.default_headers)
self.assertEqual(resp.status_code, 200)
nics = resp.json_body
nics[0]['interface_properties']['sriov']['enabled'] = True
resp = self.app.put(
reverse("NodeNICsHandler",
kwargs={"node_id": self.env.nodes[0].id}),
jsonutils.dumps(nics),
expect_errors=True,
headers=self.default_headers)
self.assertEqual(resp.status_code, 400)
self.assertIn(
"Node '{0}' interface '{1}': virtual functions can not be"
" enabled for interface when 'sriov_numfs' option is not"
" specified!".format(self.env.nodes[0].id,
self.env.nodes[0].nic_interfaces[0].name),
resp.json_body['message']
)
node = self.env.create_node(api=True, roles=['compute'], meta=meta)
self.env.create_cluster(api=True, nodes=[node['id']])
def test_enable_sriov_failed_with_non_kvm_hypervisor(self):
node = self.env.create_node(api=True, roles=['compute'])
self.env.create_cluster(
api=True,
nodes=[node['id']],
editable_attributes={
'common': {
'libvirt_type': {
'value': consts.HYPERVISORS.qemu
}
}
}
)
resp = self.app.get(
reverse('NodeNICsHandler',
kwargs={'node_id': node['id']}),
@ -1041,9 +1055,7 @@ class TestHandlers(BaseIntegrationTest):
expect_errors=True,
headers=self.default_headers)
self.assertEqual(resp.status_code, 400)
self.assertIn(
"Node '{0}' interface 'new_nic': virtual functions can not be"
" enabled for interface when 'sriov_numfs' option is not"
" specified!".format(node['id']),
self.assertEqual(
"Only KVM hypervisor works with SR-IOV.",
resp.json_body['message']
)

View File

@ -128,7 +128,8 @@ class TestDeploymentAttributesSerialization90(
'nova': {'type': 'custom_hugepages', 'value': {'2048': 1}}
}
cluster_attrs = objects.Cluster.get_editable_attributes(node.cluster)
cluster_attrs['common']['libvirt_type']['value'] = 'kvm'
cluster_attrs['common']['libvirt_type'].update(
{'value': consts.HYPERVISORS.kvm})
objects.Cluster.update_attributes(
node.cluster, {'editable': cluster_attrs})