Add disk filter
Part of blueprint limit-container-diskspace Change-Id: I8b5a792181d4f4f603869ba6db76ff63561ed9f2
This commit is contained in:
parent
e47a48c649
commit
a3f78f4d61
@ -66,7 +66,8 @@ Related options:
|
|||||||
"AvailabilityZoneFilter",
|
"AvailabilityZoneFilter",
|
||||||
"CPUFilter",
|
"CPUFilter",
|
||||||
"RamFilter",
|
"RamFilter",
|
||||||
"ComputeFilter"
|
"ComputeFilter",
|
||||||
|
"DiskFilter",
|
||||||
],
|
],
|
||||||
help="""
|
help="""
|
||||||
Filters that the scheduler will use.
|
Filters that the scheduler will use.
|
||||||
|
42
zun/scheduler/filters/disk_filter.py
Normal file
42
zun/scheduler/filters/disk_filter.py
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
# Copyright (c) 2017 OpenStack Foundation
|
||||||
|
# All Rights Reserved.
|
||||||
|
#
|
||||||
|
# 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 oslo_log import log as logging
|
||||||
|
|
||||||
|
from zun.scheduler import filters
|
||||||
|
|
||||||
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class DiskFilter(filters.BaseHostFilter):
|
||||||
|
"""Filter the containers by disk request"""
|
||||||
|
|
||||||
|
run_filter_once_per_request = True
|
||||||
|
|
||||||
|
def host_passes(self, host_state, container, extra_spec):
|
||||||
|
if not container.disk:
|
||||||
|
return True
|
||||||
|
|
||||||
|
usable_disk = host_state.disk_total - host_state.disk_used
|
||||||
|
if usable_disk < container.disk:
|
||||||
|
LOG.debug("%(host_state)s does not have %(container_disk)d "
|
||||||
|
"usable disk, it only has %(usable_disk)d usable "
|
||||||
|
"disk.",
|
||||||
|
{'host_state': host_state,
|
||||||
|
'container_disk': container.disk,
|
||||||
|
'usable_disk': usable_disk})
|
||||||
|
return False
|
||||||
|
host_state.limits['disk'] = host_state.disk_total
|
||||||
|
return True
|
@ -34,6 +34,8 @@ class HostState(object):
|
|||||||
self.mem_used = 0
|
self.mem_used = 0
|
||||||
self.cpus = 0
|
self.cpus = 0
|
||||||
self.cpu_used = 0
|
self.cpu_used = 0
|
||||||
|
self.disk_total = 0
|
||||||
|
self.disk_used = 0
|
||||||
self.numa_topology = None
|
self.numa_topology = None
|
||||||
self.labels = None
|
self.labels = None
|
||||||
self.pci_stats = None
|
self.pci_stats = None
|
||||||
@ -62,6 +64,8 @@ class HostState(object):
|
|||||||
self.mem_used = compute_node.mem_used
|
self.mem_used = compute_node.mem_used
|
||||||
self.cpus = compute_node.cpus
|
self.cpus = compute_node.cpus
|
||||||
self.cpu_used = compute_node.cpu_used
|
self.cpu_used = compute_node.cpu_used
|
||||||
|
self.disk_total = compute_node.disk_total
|
||||||
|
self.disk_used = compute_node.disk_used
|
||||||
self.numa_topology = compute_node.numa_topology
|
self.numa_topology = compute_node.numa_topology
|
||||||
self.labels = compute_node.labels
|
self.labels = compute_node.labels
|
||||||
self.pci_stats = pci_stats.PciDeviceStats(
|
self.pci_stats = pci_stats.PciDeviceStats(
|
||||||
|
45
zun/tests/unit/scheduler/filters/test_disk_filter.py
Normal file
45
zun/tests/unit/scheduler/filters/test_disk_filter.py
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
# 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 zun.common import context
|
||||||
|
from zun import objects
|
||||||
|
from zun.scheduler.filters import disk_filter
|
||||||
|
from zun.tests import base
|
||||||
|
from zun.tests.unit.scheduler import fakes
|
||||||
|
|
||||||
|
|
||||||
|
class TestDiskFilter(base.TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(TestDiskFilter, self).setUp()
|
||||||
|
self.context = context.RequestContext('fake_user', 'fake_project')
|
||||||
|
|
||||||
|
def test_disk_filter_pass(self):
|
||||||
|
self.filt_cls = disk_filter.DiskFilter()
|
||||||
|
container = objects.Container(self.context)
|
||||||
|
container.disk = 20
|
||||||
|
host = fakes.FakeHostState('testhost')
|
||||||
|
host.disk_total = 80
|
||||||
|
host.disk_used = 40
|
||||||
|
extra_spec = {}
|
||||||
|
self.assertTrue(self.filt_cls.host_passes(host, container, extra_spec))
|
||||||
|
|
||||||
|
def test_disk_filter_fail(self):
|
||||||
|
self.filt_cls = disk_filter.DiskFilter()
|
||||||
|
container = objects.Container(self.context)
|
||||||
|
container.disk = 20
|
||||||
|
host = fakes.FakeHostState('testhost')
|
||||||
|
host.disk_total = 80
|
||||||
|
host.disk_used = 70
|
||||||
|
extra_spec = {}
|
||||||
|
self.assertFalse(self.filt_cls.host_passes(host, container,
|
||||||
|
extra_spec))
|
@ -58,6 +58,8 @@ class FilterSchedulerTestCase(base.TestCase):
|
|||||||
node1.mem_total = 1024 * 128
|
node1.mem_total = 1024 * 128
|
||||||
node1.mem_used = 1024 * 4
|
node1.mem_used = 1024 * 4
|
||||||
node1.mem_free = 1024 * 124
|
node1.mem_free = 1024 * 124
|
||||||
|
node1.disk_total = 80
|
||||||
|
node1.disk_used = 20
|
||||||
node1.hostname = 'host1'
|
node1.hostname = 'host1'
|
||||||
node1.numa_topology = None
|
node1.numa_topology = None
|
||||||
node1.labels = {}
|
node1.labels = {}
|
||||||
@ -68,6 +70,8 @@ class FilterSchedulerTestCase(base.TestCase):
|
|||||||
node2.mem_total = 1024 * 128
|
node2.mem_total = 1024 * 128
|
||||||
node2.mem_used = 1024 * 4
|
node2.mem_used = 1024 * 4
|
||||||
node2.mem_free = 1024 * 124
|
node2.mem_free = 1024 * 124
|
||||||
|
node2.disk_total = 80
|
||||||
|
node2.disk_used = 20
|
||||||
node2.hostname = 'host2'
|
node2.hostname = 'host2'
|
||||||
node2.numa_topology = None
|
node2.numa_topology = None
|
||||||
node2.labels = {}
|
node2.labels = {}
|
||||||
@ -78,6 +82,8 @@ class FilterSchedulerTestCase(base.TestCase):
|
|||||||
node3.mem_total = 1024 * 128
|
node3.mem_total = 1024 * 128
|
||||||
node3.mem_used = 1024 * 4
|
node3.mem_used = 1024 * 4
|
||||||
node3.mem_free = 1024 * 124
|
node3.mem_free = 1024 * 124
|
||||||
|
node3.disk_total = 80
|
||||||
|
node3.disk_used = 20
|
||||||
node3.hostname = 'host3'
|
node3.hostname = 'host3'
|
||||||
node3.numa_topology = None
|
node3.numa_topology = None
|
||||||
node3.labels = {}
|
node3.labels = {}
|
||||||
@ -88,6 +94,8 @@ class FilterSchedulerTestCase(base.TestCase):
|
|||||||
node4.mem_total = 1024 * 128
|
node4.mem_total = 1024 * 128
|
||||||
node4.mem_used = 1024 * 4
|
node4.mem_used = 1024 * 4
|
||||||
node4.mem_free = 1024 * 124
|
node4.mem_free = 1024 * 124
|
||||||
|
node4.disk_total = 80
|
||||||
|
node4.disk_used = 20
|
||||||
node4.hostname = 'host4'
|
node4.hostname = 'host4'
|
||||||
node4.numa_topology = None
|
node4.numa_topology = None
|
||||||
node4.labels = {}
|
node4.labels = {}
|
||||||
|
Loading…
Reference in New Issue
Block a user