Configure and use driver filter and weighing for
scheduler
OpenStack Block Storage enables you to choose a volume back end based
on back-end specific properties by using the DriverFilter and
GoodnessWeigher for the scheduler. The driver filter and weigher
scheduling can help ensure that the scheduler chooses the best back end
based on requested volume properties as well as various back-end
specific properties.
What is
driver filter and weigher and when to use it
The driver filter and weigher gives you the ability to more finely
control how the OpenStack Block Storage scheduler chooses the best back
end to use when handling a volume request. One example scenario where
using the driver filter and weigher can be if a back end that utilizes
thin-provisioning is used. The default filters use the
free capacity
property to determine the best back end, but
that is not always perfect. If a back end has the ability to provide a
more accurate back-end specific value you can use that as part of the
weighing. Another example of when the driver filter and weigher can
prove useful is if a back end exists where there is a hard limit of 1000
volumes. The maximum volume size is 500 GB. Once 75% of the total space
is occupied the performance of the back end degrades. The driver filter
and weigher can provide a way for these limits to be checked for.
Enable driver filter and
weighing
To enable the driver filter, set the
scheduler_default_filters
option in the
cinder.conf
file to DriverFilter
. The
DriverFilter can also be used along with other filters by adding it to
the list if other filters are already present.
To enable the goodness filter as a weigher, set the
scheduler_default_weighers
option in the
cinder.conf
file to GoodnessWeigher
or add it
to the list if other weighers are already present.
You can choose to use the DriverFilter
without the
GoodnessWeigher
or vice-versa. The filter and weigher
working together, however, create the most benefits when helping the
scheduler choose an ideal back end.
Important
The GoodnessWeigher can be used along with CapacityWeigher and
others, but must be used with caution as it might obfuscate the
CapacityWeigher.
Example cinder.conf
configuration file:
Note
It is useful to use the other filters and weighers available in
OpenStack in combination with these custom ones. For example, the
CapacityFilter
and CapacityWeigher
can be
combined with these. Using them together should be done with caution as
depending on the defined logic, one might obfuscate the other.
Defining your
own filter and goodness functions
You can define your own filter and goodness functions through the use
of various properties that OpenStack Block Storage has exposed.
Properties exposed include information about the volume request being
made, volume_type
settings, and back-end specific
information about drivers. All of these allow for a lot of control over
how the ideal back end for a volume request will be decided.
The filter_function
option is a string defining an
equation that will determine whether a back end should be considered as
a potential candidate in the scheduler.
The goodness_function
option is a string defining an
equation that will rate the quality of the potential host (0 to 100, 0
lowest, 100 highest).
Important
The drive filter and weigher will use default values for filter and
goodness functions for each back end if you do not define them yourself.
If complete control is desired then a filter and goodness function
should be defined for each of the back ends in the
cinder.conf
file.
Supported
operations in filter and goodness functions
Below is a table of all the operations currently usable in custom
filter and goodness functions created by you:
Operations | Type |
---|---|
+, -, *, /, ^ | standard math |
not, and, or, &, |, ! | logic |
>, >=, <, <=, ==, <>, != | equality |
+, – | sign |
x ? a : b | ternary |
abs(x), max(x, y), min(x, y) | math helper functions |
Caution
Syntax errors you define in filter or goodness strings are thrown at
a volume request time.
Available
properties when creating custom functions
There are various properties that can be used in either the
filter_function
or the goodness_function
strings. The properties allow access to volume info, qos settings, extra
specs, and so on.
The following properties and their sub-properties are currently
available for use:
Host stats for a back end
In order to access these properties, use the following format:
stats.<property>
- host
-
The host’s name
- volume_backend_name
-
The volume back end name
- vendor_name
-
The vendor name
- driver_version
-
The driver version
- storage_protocol
-
The storage protocol
- QoS_support
-
Boolean signifying whether QoS is supported
- total_capacity_gb
-
The total capacity in GB
- allocated_capacity_gb
-
The allocated capacity in GB
- free_capacity_gb
-
The free capacity in GB
- reserved_percentage
-
The reserved storage percentage
Capabilities specific to a
back end
These properties are determined by the specific back end you are
creating filter and goodness functions for. Some back ends may not have
any properties available here. Once the capabilities vary too much
according to the backend, it is better to check its properties reported
on the scheduler log. The scheduler reports these capabilities
constantly. In order to access these properties, use the following
format: capabilities.<property>
Requested volume properties
In order to access the volume properties, use the following format:
volume.<property>
- status
-
Status for the requested volume
- volume_type_id
-
The volume type ID
- display_name
-
The display name of the volume
- volume_metadata
-
Any metadata the volume has
- reservations
-
Any reservations the volume has
- user_id
-
The volume’s user ID
- attach_status
-
The attach status for the volume
- display_description
-
The volume’s display description
- id
-
The volume’s ID
- replication_status
-
The volume’s replication status
- snapshot_id
-
The volume’s snapshot ID
- encryption_key_id
-
The volume’s encryption key ID
- source_volid
-
The source volume ID
- volume_admin_metadata
-
Any admin metadata for this volume
- source_replicaid
-
The source replication ID
- consistencygroup_id
-
The consistency group ID
- size
-
The size of the volume in GB
- metadata
-
General metadata
The property most used from here will most likely be the
size
sub-property.
Extra specs for the
requested volume type
View the available properties for volume types by running:
$ cinder extra-specs-list
Current QoS
specs for the requested volume type
View the available properties for volume types by running:
$ openstack volume qos list
In order to access these properties in a custom string use the
following format:
<property>.<sub_property>
Driver filter and
weigher usage examples
Below are examples for using the filter and weigher separately,
together, and using driver-specific properties.
Example cinder.conf
file configuration for customizing
the filter function:
[default]
scheduler_default_filters = DriverFilter
enabled_backends = lvm-1, lvm-2
[lvm-1]
volume_driver = cinder.volume.drivers.lvm.LVMVolumeDriver
volume_backend_name = sample_LVM01
filter_function = "volume.size < 10"
[lvm-2]
volume_driver = cinder.volume.drivers.lvm.LVMVolumeDriver
volume_backend_name = sample_LVM02
filter_function = "volume.size >= 10"
The above example will filter volumes to different back ends
depending on the size of the requested volume. Default OpenStack Block
Storage scheduler weighing is done. Volumes with a size less than 10 GB
are sent to lvm-1 and volumes with a size greater than or equal to 10 GB
are sent to lvm-2.
Example cinder.conf
file configuration for customizing
the goodness function:
[default]
scheduler_default_weighers = GoodnessWeigher
enabled_backends = lvm-1, lvm-2
[lvm-1]
volume_driver = cinder.volume.drivers.lvm.LVMVolumeDriver
volume_backend_name = sample_LVM01
goodness_function = "(volume.size < 5) ? 100 : 50"
[lvm-2]
volume_driver = cinder.volume.drivers.lvm.LVMVolumeDriver
volume_backend_name = sample_LVM02
goodness_function = "(volume.size >= 5) ? 100 : 25"
The above example will determine the goodness rating of a back end
based off of the requested volume’s size. Default OpenStack Block
Storage scheduler filtering is done. The example shows how the ternary
if statement can be used in a filter or goodness function. If a
requested volume is of size 10 GB then lvm-1 is rated as 50 and lvm-2 is
rated as 100. In this case lvm-2 wins. If a requested volume is of size
3 GB then lvm-1 is rated 100 and lvm-2 is rated 25. In this case lvm-1
would win.
Example cinder.conf
file configuration for customizing
both the filter and goodness functions:
[default]
scheduler_default_filters = DriverFilter
scheduler_default_weighers = GoodnessWeigher
enabled_backends = lvm-1, lvm-2
[lvm-1]
volume_driver = cinder.volume.drivers.lvm.LVMVolumeDriver
volume_backend_name = sample_LVM01
filter_function = "stats.total_capacity_gb < 500"
goodness_function = "(volume.size < 25) ? 100 : 50"
[lvm-2]
volume_driver = cinder.volume.drivers.lvm.LVMVolumeDriver
volume_backend_name = sample_LVM02
filter_function = "stats.total_capacity_gb >= 500"
goodness_function = "(volume.size >= 25) ? 100 : 75"
The above example combines the techniques from the first two
examples. The best back end is now decided based off of the total
capacity of the back end and the requested volume’s size.
Example cinder.conf
file configuration for accessing
driver specific properties:
[default]
scheduler_default_filters = DriverFilter
scheduler_default_weighers = GoodnessWeigher
enabled_backends = lvm-1,lvm-2,lvm-3
[lvm-1]
volume_group = stack-volumes-lvmdriver-1
volume_driver = cinder.volume.drivers.lvm.LVMVolumeDriver
volume_backend_name = lvmdriver-1
filter_function = "volume.size < 5"
goodness_function = "(capabilities.total_volumes < 3) ? 100 : 50"
[lvm-2]
volume_group = stack-volumes-lvmdriver-2
volume_driver = cinder.volume.drivers.lvm.LVMVolumeDriver
volume_backend_name = lvmdriver-2
filter_function = "volume.size < 5"
goodness_function = "(capabilities.total_volumes < 8) ? 100 : 50"
[lvm-3]
volume_group = stack-volumes-lvmdriver-3
volume_driver = cinder.volume.drivers.LVMVolumeDriver
volume_backend_name = lvmdriver-3
goodness_function = "55"
The above is an example of how back-end specific properties can be
used in the filter and goodness functions. In this example the LVM
driver’s total_volumes
capability is being used to
determine which host gets used during a volume request. In the above
example, lvm-1 and lvm-2 will handle volume requests for all volumes
with a size less than 5 GB. Both lvm-1 and lvm-2 will have the same
priority while lvm-1 contains 3 or less volumes. After that lvm-2 will
have priority while it contains 8 or less volumes. The lvm-3 will
collect all volumes greater or equal to 5 GB as well as all volumes once
lvm-1 and lvm-2 lose priority.