Coverage for manila/scheduler/scheduler_options.py: 88%
48 statements
« prev ^ index » next coverage.py v7.11.0, created at 2026-02-18 22:19 +0000
« prev ^ index » next coverage.py v7.11.0, created at 2026-02-18 22:19 +0000
1# Copyright (c) 2011 OpenStack, LLC.
2# All Rights Reserved.
3#
4# Licensed under the Apache License, Version 2.0 (the "License"); you may
5# not use this file except in compliance with the License. You may obtain
6# a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13# License for the specific language governing permissions and limitations
14# under the License.
16"""
17SchedulerOptions monitors a local .json file for changes and loads
18it if needed. This file is converted to a data structure and passed
19into the filtering and weighing functions which can use it for
20dynamic configuration.
21"""
23import datetime
24import os
26from oslo_config import cfg
27from oslo_log import log
28from oslo_serialization import jsonutils
29from oslo_utils import timeutils
31scheduler_json_config_location_opt = cfg.StrOpt(
32 'scheduler_json_config_location',
33 default='',
34 help='Absolute path to scheduler configuration JSON file.')
36CONF = cfg.CONF
37CONF.register_opt(scheduler_json_config_location_opt)
39LOG = log.getLogger(__name__)
42class SchedulerOptions(object):
43 """Monitor and load local .json file for filtering and weighing.
45 SchedulerOptions monitors a local .json file for changes and loads it
46 if needed. This file is converted to a data structure and passed into
47 the filtering and weighing functions which can use it for dynamic
48 configuration.
49 """
51 def __init__(self):
52 super(SchedulerOptions, self).__init__()
53 self.data = {}
54 self.last_modified = None
55 self.last_checked = None
57 def _get_file_handle(self, filename):
58 """Get file handle. Broken out for testing."""
59 return open(filename)
61 def _get_file_timestamp(self, filename):
62 """Get the last modified datetime. Broken out for testing."""
63 try:
64 return os.path.getmtime(filename)
65 except os.error:
66 LOG.exception("Could not stat scheduler options file "
67 "%(filename)s.",
68 {"filename": filename})
69 raise
71 def _load_file(self, handle):
72 """Decode the JSON file. Broken out for testing."""
73 try:
74 return jsonutils.load(handle)
75 except ValueError:
76 LOG.exception("Could not decode scheduler options.")
77 return {}
79 def _get_time_now(self):
80 """Get current UTC. Broken out for testing."""
81 return timeutils.utcnow()
83 def get_configuration(self, filename=None):
84 """Check the json file for changes and load it if needed."""
85 if not filename:
86 filename = CONF.scheduler_json_config_location
87 if not filename:
88 return self.data
89 if self.last_checked:
90 now = self._get_time_now()
91 if now - self.last_checked < datetime.timedelta(minutes=5):
92 return self.data
94 last_modified = self._get_file_timestamp(filename)
95 if (not last_modified or not self.last_modified or
96 last_modified > self.last_modified):
97 self.data = self._load_file(self._get_file_handle(filename))
98 self.last_modified = last_modified
99 if not self.data:
100 self.data = {}
102 return self.data