magnum/magnum/drivers/common/driver.py

205 lines
6.8 KiB
Python

# Copyright 2014 NEC Corporation. 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.
import abc
import six
from oslo_config import cfg
from pkg_resources import iter_entry_points
from stevedore import driver
from magnum.common import exception
from magnum.objects import cluster_template
CONF = cfg.CONF
@six.add_metaclass(abc.ABCMeta)
class Driver(object):
definitions = None
@classmethod
def load_entry_points(cls):
for entry_point in iter_entry_points('magnum.drivers'):
if entry_point.name not in CONF.drivers.disabled_drivers:
yield entry_point, entry_point.load(require=False)
@classmethod
def get_drivers(cls):
"""Retrieves cluster drivers from python entry_points.
Example:
With the following classes:
class Driver1(Driver):
provides = [
('server_type1', 'os1', 'coe1')
]
class Driver2(Driver):
provides = [
('server_type2', 'os2', 'coe2')
]
And the following entry_points:
magnum.drivers =
driver_name_1 = some.python.path:Driver1
driver_name_2 = some.python.path:Driver2
get_drivers will return:
{
(server_type1, os1, coe1):
{'driver_name_1': Driver1},
(server_type2, os2, coe2):
{'driver_name_2': Driver2}
}
:return: dict
"""
if not cls.definitions:
cls.definitions = dict()
for entry_point, def_class in cls.load_entry_points():
for cluster_type in def_class().provides:
cluster_type_tuple = (cluster_type['server_type'],
cluster_type['os'],
cluster_type['coe'])
providers = cls.definitions.setdefault(cluster_type_tuple,
dict())
providers['entry_point_name'] = entry_point.name
providers['class'] = def_class
return cls.definitions
@classmethod
def get_driver(cls, server_type, os, coe):
"""Get Driver.
Returns the Driver class for the provided cluster_type.
With the following classes:
class Driver1(Driver):
provides = [
('server_type1', 'os1', 'coe1')
]
class Driver2(Driver):
provides = [
('server_type2', 'os2', 'coe2')
]
And the following entry_points:
magnum.drivers =
driver_name_1 = some.python.path:Driver1
driver_name_2 = some.python.path:Driver2
get_driver('server_type2', 'os2', 'coe2')
will return: Driver2
:param server_type: The server_type the cluster definition will build
on
:param os: The operating system the cluster definition will build on
:param coe: The Container Orchestration Environment the cluster will
produce
:return: class
"""
definition_map = cls.get_drivers()
cluster_type = (server_type, os, coe)
if cluster_type not in definition_map:
raise exception.ClusterTypeNotSupported(
server_type=server_type,
os=os,
coe=coe)
driver_info = definition_map[cluster_type]
# TODO(muralia): once --drivername is supported as an input during
# cluster create, change the following line to use driver name for
# loading.
return driver.DriverManager("magnum.drivers",
driver_info['entry_point_name']).driver()
@classmethod
def get_driver_for_cluster(cls, context, cluster):
ct = cluster_template.ClusterTemplate.get_by_uuid(
context, cluster.cluster_template_id)
return cls.get_driver(ct.server_type, ct.cluster_distro, ct.coe)
def update_cluster_status(self, context, cluster):
"""Update the cluster status based on underlying orchestration
This is an optional method if your implementation does not need
to poll the orchestration for status updates (for example, your
driver uses some notification-based mechanism instead).
"""
return
@abc.abstractproperty
def provides(self):
"""return a list of (server_type, os, coe) tuples
Returns a list of cluster configurations supported by this driver
"""
raise NotImplementedError("Subclasses must implement 'provides'.")
@abc.abstractmethod
def create_cluster(self, context, cluster, cluster_create_timeout):
raise NotImplementedError("Subclasses must implement "
"'create_cluster'.")
@abc.abstractmethod
def update_cluster(self, context, cluster, scale_manager=None,
rollback=False):
raise NotImplementedError("Subclasses must implement "
"'update_cluster'.")
@abc.abstractmethod
def delete_cluster(self, context, cluster):
raise NotImplementedError("Subclasses must implement "
"'delete_cluster'.")
@abc.abstractmethod
def create_federation(self, context, federation):
raise NotImplementedError("Subclasses must implement "
"'create_federation'.")
@abc.abstractmethod
def update_federation(self, context, federation):
raise NotImplementedError("Subclasses must implement "
"'update_federation'.")
@abc.abstractmethod
def delete_federation(self, context, federation):
raise NotImplementedError("Subclasses must implement "
"'delete_federation'.")
def get_monitor(self, context, cluster):
"""return the monitor with container data for this driver."""
return None
def get_scale_manager(self, context, osclient, cluster):
"""return the scale manager for this driver."""
return None
def rotate_ca_certificate(self, context, cluster):
raise exception.NotSupported(
"'rotate_ca_certificate' is not supported by this driver.")