Add enhanced KVM storage QoS quotas
This will add additonal KVM-based qoutas for Cinder front-end QoS The new quotas are: - read_bytes_sec_max - write_bytes_sec_max - total_bytes_sec_max - read_iops_sec_max - write_iops_sec_max - total_iops_sec_max - size_iops_sec Depends-On: https://review.openstack.org/574804 Change-Id: I5a8f34c7ed3dea940700dffd54bc7d44f7518ab4 Implements: blueprint enhanced-kvm-storage-qos
This commit is contained in:
parent
0a642e2eee
commit
37aea88845
@ -1016,12 +1016,22 @@ class LibvirtConfigGuestDiskTest(LibvirtConfigBaseTest):
|
|||||||
obj.source_path = "/tmp/hello"
|
obj.source_path = "/tmp/hello"
|
||||||
obj.target_dev = "/dev/hda"
|
obj.target_dev = "/dev/hda"
|
||||||
obj.target_bus = "ide"
|
obj.target_bus = "ide"
|
||||||
|
# Note that read/write iops/bytes values cannot be used with
|
||||||
|
# total values. These are only here for illustrative purposes.
|
||||||
obj.disk_read_bytes_sec = 1024000
|
obj.disk_read_bytes_sec = 1024000
|
||||||
obj.disk_read_iops_sec = 1000
|
obj.disk_read_iops_sec = 1000
|
||||||
obj.disk_total_bytes_sec = 2048000
|
obj.disk_total_bytes_sec = 2048000
|
||||||
obj.disk_write_bytes_sec = 1024000
|
obj.disk_write_bytes_sec = 1024000
|
||||||
obj.disk_write_iops_sec = 1000
|
obj.disk_write_iops_sec = 1000
|
||||||
obj.disk_total_iops_sec = 2000
|
obj.disk_total_iops_sec = 2000
|
||||||
|
obj.disk_write_bytes_sec_max = 1536000
|
||||||
|
obj.disk_write_iops_sec_max = 1500
|
||||||
|
obj.disk_total_iops_sec_max = 3072000
|
||||||
|
obj.disk_read_bytes_sec_max = 1536000
|
||||||
|
obj.disk_read_iops_sec_max = 1500
|
||||||
|
obj.disk_total_iops_sec_max = 2000
|
||||||
|
obj.disk_total_bytes_sec_max = 3072000
|
||||||
|
obj.disk_size_iops_sec = 16
|
||||||
|
|
||||||
xml = obj.to_xml()
|
xml = obj.to_xml()
|
||||||
self.assertXmlEqual(xml, """
|
self.assertXmlEqual(xml, """
|
||||||
@ -1035,6 +1045,13 @@ class LibvirtConfigGuestDiskTest(LibvirtConfigBaseTest):
|
|||||||
<write_iops_sec>1000</write_iops_sec>
|
<write_iops_sec>1000</write_iops_sec>
|
||||||
<total_bytes_sec>2048000</total_bytes_sec>
|
<total_bytes_sec>2048000</total_bytes_sec>
|
||||||
<total_iops_sec>2000</total_iops_sec>
|
<total_iops_sec>2000</total_iops_sec>
|
||||||
|
<read_bytes_sec_max>1536000</read_bytes_sec_max>
|
||||||
|
<write_bytes_sec_max>1536000</write_bytes_sec_max>
|
||||||
|
<total_bytes_sec_max>3072000</total_bytes_sec_max>
|
||||||
|
<read_iops_sec_max>1500</read_iops_sec_max>
|
||||||
|
<write_iops_sec_max>1500</write_iops_sec_max>
|
||||||
|
<total_iops_sec_max>2000</total_iops_sec_max>
|
||||||
|
<size_iops_sec>16</size_iops_sec>
|
||||||
</iotune>
|
</iotune>
|
||||||
</disk>""")
|
</disk>""")
|
||||||
|
|
||||||
|
@ -118,8 +118,18 @@ class LibvirtISCSIVolumeBaseTestCase(LibvirtVolumeBaseTestCase):
|
|||||||
'target_lun': 1,
|
'target_lun': 1,
|
||||||
'device_path': dev_path,
|
'device_path': dev_path,
|
||||||
'qos_specs': {
|
'qos_specs': {
|
||||||
|
# Note that read/write iops/bytes values cannot
|
||||||
|
# be used with total values.
|
||||||
|
# These are only here for illustrative purposes.
|
||||||
'total_bytes_sec': '102400',
|
'total_bytes_sec': '102400',
|
||||||
'read_iops_sec': '200',
|
'read_iops_sec': '200',
|
||||||
|
'read_bytes_sec_max': '150000',
|
||||||
|
'read_iops_sec_max': '2000',
|
||||||
|
'write_bytes_sec_max': '250000',
|
||||||
|
'write_iops_sec_max': '3000',
|
||||||
|
'total_bytes_sec_max': '400000',
|
||||||
|
'total_iops_sec_max': '4000',
|
||||||
|
'size_iops_sec': '16',
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -707,6 +707,13 @@ class LibvirtConfigGuestDisk(LibvirtConfigGuestDevice):
|
|||||||
self.disk_write_iops_sec = None
|
self.disk_write_iops_sec = None
|
||||||
self.disk_total_bytes_sec = None
|
self.disk_total_bytes_sec = None
|
||||||
self.disk_total_iops_sec = None
|
self.disk_total_iops_sec = None
|
||||||
|
self.disk_read_bytes_sec_max = None
|
||||||
|
self.disk_write_bytes_sec_max = None
|
||||||
|
self.disk_total_bytes_sec_max = None
|
||||||
|
self.disk_read_iops_sec_max = None
|
||||||
|
self.disk_write_iops_sec_max = None
|
||||||
|
self.disk_total_iops_sec_max = None
|
||||||
|
self.disk_size_iops_sec = None
|
||||||
self.logical_block_size = None
|
self.logical_block_size = None
|
||||||
self.physical_block_size = None
|
self.physical_block_size = None
|
||||||
self.readonly = False
|
self.readonly = False
|
||||||
@ -718,6 +725,64 @@ class LibvirtConfigGuestDisk(LibvirtConfigGuestDevice):
|
|||||||
self.mirror = None
|
self.mirror = None
|
||||||
self.encryption = None
|
self.encryption = None
|
||||||
|
|
||||||
|
def _format_iotune(self, dev):
|
||||||
|
iotune = etree.Element("iotune")
|
||||||
|
|
||||||
|
if self.disk_read_bytes_sec is not None:
|
||||||
|
iotune.append(self._text_node("read_bytes_sec",
|
||||||
|
self.disk_read_bytes_sec))
|
||||||
|
|
||||||
|
if self.disk_read_iops_sec is not None:
|
||||||
|
iotune.append(self._text_node("read_iops_sec",
|
||||||
|
self.disk_read_iops_sec))
|
||||||
|
|
||||||
|
if self.disk_write_bytes_sec is not None:
|
||||||
|
iotune.append(self._text_node("write_bytes_sec",
|
||||||
|
self.disk_write_bytes_sec))
|
||||||
|
|
||||||
|
if self.disk_write_iops_sec is not None:
|
||||||
|
iotune.append(self._text_node("write_iops_sec",
|
||||||
|
self.disk_write_iops_sec))
|
||||||
|
|
||||||
|
if self.disk_total_bytes_sec is not None:
|
||||||
|
iotune.append(self._text_node("total_bytes_sec",
|
||||||
|
self.disk_total_bytes_sec))
|
||||||
|
|
||||||
|
if self.disk_total_iops_sec is not None:
|
||||||
|
iotune.append(self._text_node("total_iops_sec",
|
||||||
|
self.disk_total_iops_sec))
|
||||||
|
|
||||||
|
if self.disk_read_bytes_sec_max is not None:
|
||||||
|
iotune.append(self._text_node("read_bytes_sec_max",
|
||||||
|
self.disk_read_bytes_sec_max))
|
||||||
|
|
||||||
|
if self.disk_write_bytes_sec_max is not None:
|
||||||
|
iotune.append(self._text_node("write_bytes_sec_max",
|
||||||
|
self.disk_write_bytes_sec_max))
|
||||||
|
|
||||||
|
if self.disk_total_bytes_sec_max is not None:
|
||||||
|
iotune.append(self._text_node("total_bytes_sec_max",
|
||||||
|
self.disk_total_bytes_sec_max))
|
||||||
|
|
||||||
|
if self.disk_read_iops_sec_max is not None:
|
||||||
|
iotune.append(self._text_node("read_iops_sec_max",
|
||||||
|
self.disk_read_iops_sec_max))
|
||||||
|
|
||||||
|
if self.disk_write_iops_sec_max is not None:
|
||||||
|
iotune.append(self._text_node("write_iops_sec_max",
|
||||||
|
self.disk_write_iops_sec_max))
|
||||||
|
|
||||||
|
if self.disk_total_iops_sec_max is not None:
|
||||||
|
iotune.append(self._text_node("total_iops_sec_max",
|
||||||
|
self.disk_total_iops_sec_max))
|
||||||
|
|
||||||
|
if self.disk_size_iops_sec is not None:
|
||||||
|
iotune.append(self._text_node("size_iops_sec",
|
||||||
|
self.disk_size_iops_sec))
|
||||||
|
|
||||||
|
if len(iotune) > 0:
|
||||||
|
dev.append(iotune)
|
||||||
|
|
||||||
def format_dom(self):
|
def format_dom(self):
|
||||||
dev = super(LibvirtConfigGuestDisk, self).format_dom()
|
dev = super(LibvirtConfigGuestDisk, self).format_dom()
|
||||||
|
|
||||||
@ -774,34 +839,7 @@ class LibvirtConfigGuestDisk(LibvirtConfigGuestDevice):
|
|||||||
if self.serial is not None:
|
if self.serial is not None:
|
||||||
dev.append(self._text_node("serial", self.serial))
|
dev.append(self._text_node("serial", self.serial))
|
||||||
|
|
||||||
iotune = etree.Element("iotune")
|
self._format_iotune(dev)
|
||||||
|
|
||||||
if self.disk_read_bytes_sec is not None:
|
|
||||||
iotune.append(self._text_node("read_bytes_sec",
|
|
||||||
self.disk_read_bytes_sec))
|
|
||||||
|
|
||||||
if self.disk_read_iops_sec is not None:
|
|
||||||
iotune.append(self._text_node("read_iops_sec",
|
|
||||||
self.disk_read_iops_sec))
|
|
||||||
|
|
||||||
if self.disk_write_bytes_sec is not None:
|
|
||||||
iotune.append(self._text_node("write_bytes_sec",
|
|
||||||
self.disk_write_bytes_sec))
|
|
||||||
|
|
||||||
if self.disk_write_iops_sec is not None:
|
|
||||||
iotune.append(self._text_node("write_iops_sec",
|
|
||||||
self.disk_write_iops_sec))
|
|
||||||
|
|
||||||
if self.disk_total_bytes_sec is not None:
|
|
||||||
iotune.append(self._text_node("total_bytes_sec",
|
|
||||||
self.disk_total_bytes_sec))
|
|
||||||
|
|
||||||
if self.disk_total_iops_sec is not None:
|
|
||||||
iotune.append(self._text_node("total_iops_sec",
|
|
||||||
self.disk_total_iops_sec))
|
|
||||||
|
|
||||||
if len(iotune) > 0:
|
|
||||||
dev.append(iotune)
|
|
||||||
|
|
||||||
# Block size tuning
|
# Block size tuning
|
||||||
if (self.logical_block_size is not None or
|
if (self.logical_block_size is not None or
|
||||||
|
@ -63,7 +63,11 @@ class LibvirtBaseVolumeDriver(object):
|
|||||||
if 'qos_specs' in data and data['qos_specs']:
|
if 'qos_specs' in data and data['qos_specs']:
|
||||||
tune_opts = ['total_bytes_sec', 'read_bytes_sec',
|
tune_opts = ['total_bytes_sec', 'read_bytes_sec',
|
||||||
'write_bytes_sec', 'total_iops_sec',
|
'write_bytes_sec', 'total_iops_sec',
|
||||||
'read_iops_sec', 'write_iops_sec']
|
'read_iops_sec', 'write_iops_sec',
|
||||||
|
'read_bytes_sec_max', 'read_iops_sec_max',
|
||||||
|
'write_bytes_sec_max', 'write_iops_sec_max',
|
||||||
|
'total_bytes_sec_max', 'total_iops_sec_max',
|
||||||
|
'size_iops_sec']
|
||||||
specs = data['qos_specs']
|
specs = data['qos_specs']
|
||||||
if isinstance(specs, dict):
|
if isinstance(specs, dict):
|
||||||
for k, v in specs.items():
|
for k, v in specs.items():
|
||||||
|
@ -0,0 +1,18 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- |
|
||||||
|
The libvirt driver now supports additional Cinder front-end
|
||||||
|
QoS specs, allowing the specification of additional IO
|
||||||
|
burst limits applied for each attached disk, individually.
|
||||||
|
|
||||||
|
- quota:read_bytes_sec_max
|
||||||
|
- quota:write_bytes_sec_max
|
||||||
|
- quota:total_bytes_sec_max
|
||||||
|
- quota:read_iops_sec_max
|
||||||
|
- quota:write_iops_sec_max
|
||||||
|
- quota:total_iops_sec_max
|
||||||
|
- quota:size_iops_sec
|
||||||
|
|
||||||
|
For more information, see the Cinder admin guide:
|
||||||
|
|
||||||
|
https://docs.openstack.org/cinder/latest/admin/blockstorage-basic-volume-qos.html
|
Loading…
Reference in New Issue
Block a user