Coverage for manila/manager.py: 87%
60 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 2010 United States Government as represented by the
2# Administrator of the National Aeronautics and Space Administration.
3# All Rights Reserved.
4#
5# Licensed under the Apache License, Version 2.0 (the "License"); you may
6# not use this file except in compliance with the License. You may obtain
7# a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14# License for the specific language governing permissions and limitations
15# under the License.
17"""Base Manager class.
19Managers are responsible for a certain aspect of the system. It is a logical
20grouping of code relating to a portion of the system. In general other
21components should be using the manager to make changes to the components that
22it is responsible for.
24For example, other components that need to deal with volumes in some way,
25should do so by calling methods on the VolumeManager instead of directly
26changing fields in the database. This allows us to keep all of the code
27relating to volumes in the same place.
29We have adopted a basic strategy of Smart managers and dumb data, which means
30rather than attaching methods to data objects, components should call manager
31methods that act on the data.
33Methods on managers that can be executed locally should be called directly. If
34a particular method must execute on a remote host, this should be done via rpc
35to the service that wraps the manager
37Managers should be responsible for most of the db access, and
38non-implementation specific data. Anything implementation specific that can't
39be generalized should be done by the Driver.
41In general, we prefer to have one manager with multiple drivers for different
42implementations, but sometimes it makes sense to have multiple managers. You
43can think of it this way: Abstract different overall strategies at the manager
44level(FlatNetwork vs VlanNetwork), and different implementations at the driver
45level(LinuxNetDriver vs CiscoNetDriver).
47Managers will often provide methods for initial setup of a host or periodic
48tasks to a wrapping service.
50This module provides Manager, a base class for managers.
52"""
55from eventlet import greenpool
56from oslo_config import cfg
57from oslo_log import log
58from oslo_service import periodic_task
60from manila.db import base
61from manila.scheduler import rpcapi as scheduler_rpcapi
62from manila import version
64CONF = cfg.CONF
65LOG = log.getLogger(__name__)
68class PeriodicTasks(periodic_task.PeriodicTasks):
69 def __init__(self):
70 super(PeriodicTasks, self).__init__(CONF)
73class Manager(base.Base, PeriodicTasks):
75 @property
76 def RPC_API_VERSION(self):
77 """Redefine this in child classes."""
78 raise NotImplementedError
80 @property
81 def target(self):
82 """This property is used by oslo_messaging.
84 https://wiki.openstack.org/wiki/Oslo/Messaging#API_Version_Negotiation
85 """
86 if not hasattr(self, '_target'):
87 import oslo_messaging as messaging
88 self._target = messaging.Target(version=self.RPC_API_VERSION)
89 return self._target
91 def __init__(self, host=None, db_driver=None):
92 if not host:
93 host = CONF.host
94 self.host = host
95 self.additional_endpoints = []
96 self.availability_zone = CONF.storage_availability_zone
97 super(Manager, self).__init__(db_driver)
99 def periodic_tasks(self, context, raise_on_error=False):
100 """Tasks to be run at a periodic interval."""
101 return self.run_periodic_tasks(context, raise_on_error=raise_on_error)
103 def init_host(self, service_id=None):
104 """Handle initialization if this is a standalone service.
106 A hook point for services to execute tasks before the services are made
107 available (i.e. showing up on RPC and starting to accept RPC calls) to
108 other components. Child classes should override this method.
110 :param service_id: ID of the service where the manager is running.
111 """
112 pass
114 def init_host_with_rpc(self, service_id=None):
115 """A hook for service to do jobs after RPC is ready.
117 Like init_host(), this method is a hook where services get a chance
118 to execute tasks that *need* RPC. Child classes should override
119 this method.
121 :param service_id: ID of the service where the manager is running.
122 """
123 pass
125 def service_version(self, context):
126 return version.version_string()
128 def service_config(self, context):
129 config = {}
130 for key in CONF:
131 config[key] = CONF.get(key, None)
132 return config
134 def is_service_ready(self):
135 """Method indicating if service is ready.
137 This method should be overridden by subclasses which will return False
138 when the back end is not ready yet.
140 """
141 return True
144class SchedulerDependentManager(Manager):
145 """Periodically send capability updates to the Scheduler services.
147 Services that need to update the Scheduler of their capabilities
148 should derive from this class. Otherwise they can derive from
149 manager.Manager directly. Updates are only sent after
150 update_service_capabilities is called with non-None values.
152 """
154 def __init__(self, host=None, db_driver=None, service_name='undefined'):
155 self.last_capabilities = None
156 self.service_name = service_name
157 self.scheduler_rpcapi = scheduler_rpcapi.SchedulerAPI()
158 self._tp = greenpool.GreenPool()
159 super(SchedulerDependentManager, self).__init__(host, db_driver)
161 def _add_to_threadpool(self, func, *args, **kwargs):
162 self._tp.spawn_n(func, *args, **kwargs)
164 def update_service_capabilities(self, capabilities):
165 """Remember these capabilities to send on next periodic update."""
166 self.last_capabilities = capabilities
168 @periodic_task.periodic_task
169 def _publish_service_capabilities(self, context):
170 """Pass data back to the scheduler at a periodic interval."""
171 if self.last_capabilities:
172 LOG.debug('Notifying Schedulers of capabilities ...')
173 self.scheduler_rpcapi.update_service_capabilities(
174 context,
175 self.service_name,
176 self.host,
177 self.last_capabilities)