SR-IOV cannot be enabled with non-KVM hypervisor
Change-Id: I619de0fbd6b9250ffda8dce9a766fba27c2fb4e2 Partial-bug: #1563254
This commit is contained in:
parent
9b89b6d191
commit
9ffc2baa54
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
)
|
||||
|
|
|
@ -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']
|
||||
)
|
||||
|
|
|
@ -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})
|
||||
|
||||
|
|
Loading…
Reference in New Issue