[Core] Services as drivers

This patch move service definitions from classes to
drivers with default configurations.

* Driver are now loaded from all os_faults modules
  except tests folder.
* Registry now skips drivers without NAME.
* Registry now checks name collision.
* Added documentation for service drivers.

Change-Id: I58723bbb01a04e61836415392cf43be3e5fffff0
This commit is contained in:
Anton Studenov 2017-04-17 17:20:27 +03:00
parent 533654d951
commit a5945210c6
17 changed files with 1054 additions and 808 deletions

View File

@ -48,7 +48,7 @@ class CloudDriverDocDirective(rst.Directive):
subcat = utils.subcategory('{} [{}]'.format(drv_name, types))
subcat.extend(utils.parse_text(doc))
subcat.extend(utils.parse_text('**Supported services:**'))
subcat.extend(utils.parse_text('**Default services:**'))
subcat.extend(utils.rstlist(services))
return [subcat]

View File

@ -25,3 +25,18 @@ Node discover
.. driver_doc:: node_list
Services
--------
.. driver_doc:: process
.. driver_doc:: linux_service
.. driver_doc:: screen
.. driver_doc:: salt_service
.. driver_doc:: pcs_service
.. driver_doc:: pcs_or_linux_service

View File

@ -12,6 +12,7 @@
# limitations under the License.
import abc
import copy
import logging
import six
@ -20,20 +21,21 @@ from os_faults.api import base_driver
from os_faults.api import error
from os_faults.api import node_collection
from os_faults.api import power_management
from os_faults import registry
LOG = logging.getLogger(__name__)
@six.add_metaclass(abc.ABCMeta)
class CloudManagement(base_driver.BaseDriver):
SERVICE_NAME_TO_CLASS = {}
SUPPORTED_SERVICES = []
SERVICES = {}
SUPPORTED_NETWORKS = []
NODE_CLS = node_collection.NodeCollection
def __init__(self):
self.power_manager = power_management.PowerManager()
self.node_discover = None
self.services = copy.deepcopy(self.SERVICES)
def add_power_management(self, driver):
self.power_manager.add_driver(driver)
@ -75,12 +77,15 @@ class CloudManagement(base_driver.BaseDriver):
:param name: name of the serives
:return: Service
"""
if name in self.SERVICE_NAME_TO_CLASS:
klazz = self.SERVICE_NAME_TO_CLASS[name]
return klazz(node_cls=self.NODE_CLS, cloud_management=self)
raise error.ServiceError(
'{} driver does not support {!r} service'.format(
self.NAME.title(), name))
if name not in self.services:
raise error.ServiceError(
'{} driver does not support {!r} service'.format(
self.NAME.title(), name))
config = self.services[name]
klazz = registry.get_driver(config["driver"])
return klazz(node_cls=self.NODE_CLS, cloud_management=self,
service_name=name, config=config["args"])
@abc.abstractmethod
def execute_on_cloud(self, hosts, task, raise_on_error=True):
@ -98,7 +103,7 @@ class CloudManagement(base_driver.BaseDriver):
:return: [String] list of service names
"""
return cls.SUPPORTED_SERVICES
return cls.SERVICES.keys()
@classmethod
def list_supported_networks(cls):

View File

@ -38,3 +38,7 @@ class NodeCollectionError(OSFError):
class OSFDriverNotFound(OSFError):
"""Driver Not Found by os-faults registry"""
class OSFDriverWithSuchNameExists(OSFError):
"""Driver with such name already exists in os-faults registry"""

View File

@ -15,11 +15,18 @@ import abc
import six
from os_faults.api import base_driver
from os_faults.api.util import public
@six.add_metaclass(abc.ABCMeta)
class Service(object):
class Service(base_driver.BaseDriver):
def __init__(self, service_name, config, node_cls, cloud_management):
self.service_name = service_name
self.config = config
self.node_cls = node_cls
self.cloud_management = cloud_management
@abc.abstractmethod
def get_nodes(self):

View File

@ -21,12 +21,71 @@ from os_faults import utils
LOG = logging.getLogger(__name__)
PORT_SCHEMA = {
'type': 'array',
'items': [
{'enum': ['tcp', 'udp']},
{'type': 'integer', 'minimum': 0, 'maximum': 65535},
],
'minItems': 2,
'maxItems': 2,
}
class ServiceAsProcess(service.Service):
"""Service as process
def __init__(self, node_cls, cloud_management=None):
self.node_cls = node_cls
self.cloud_management = cloud_management
"process" is a basic service driver that uses `ps` and `kill` in
actions like kill / freeze / unfreeze. Commands for start / restart
/ terminate should be specified in configuration, otherwise
the commands will fail at runtime.
**Example configuration:**
.. code-block:: yaml
services:
app:
driver: process
args:
grep: my_app
restart_cmd: /bin/my_app --restart
terminate_cmd: /bin/stop_my_app
start_cmd: /bin/my_app
port: ['tcp', 4242]
parameters:
- **grep** - regexp for grep to find process PID
- **restart_cmd** - command to restart service (optional)
- **terminate_cmd** - command to terminate service (optional)
- **start_cmd** - command to start service (optional)
- **port** - tuple with two values - potocol, port number (optional)
"""
NAME = 'process'
DESCRIPTION = 'Service as process'
CONFIG_SCHEMA = {
'type': 'object',
'properties': {
'grep': {'type': 'string'},
'start_cmd': {'type': 'string'},
'terminate_cmd': {'type': 'string'},
'restart_cmd': {'type': 'string'},
'port': PORT_SCHEMA,
},
'required': ['grep'],
'additionalProperties': False,
}
def __init__(self, *args, **kwargs):
super(ServiceAsProcess, self).__init__(*args, **kwargs)
self.grep = self.config['grep']
self.start_cmd = self.config.get('start_cmd')
self.terminate_cmd = self.config.get('terminate_cmd')
self.restart_cmd = self.config.get('restart_cmd')
self.port = self.config.get('port')
def _run_task(self, task, nodes):
ips = nodes.get_ips()
@ -47,7 +106,7 @@ class ServiceAsProcess(service.Service):
def get_nodes(self):
nodes = self.cloud_management.get_nodes()
ips = nodes.get_ips()
cmd = 'bash -c "ps ax | grep -v grep | grep \'{}\'"'.format(self.GREP)
cmd = 'bash -c "ps ax | grep -v grep | grep \'{}\'"'.format(self.grep)
results = self.cloud_management.execute_on_cloud(
ips, {'command': cmd}, False)
success_ips = [r.host for r in results
@ -56,81 +115,114 @@ class ServiceAsProcess(service.Service):
return self.node_cls(cloud_management=self.cloud_management,
hosts=hosts)
@utils.require_variables('RESTART_CMD', 'SERVICE_NAME')
@utils.require_variables('restart_cmd')
def restart(self, nodes=None):
nodes = nodes if nodes is not None else self.get_nodes()
LOG.info("Restart '%s' service on nodes: %s", self.SERVICE_NAME,
LOG.info("Restart '%s' service on nodes: %s", self.service_name,
nodes.get_ips())
self._run_task({'shell': self.RESTART_CMD}, nodes)
self._run_task({'shell': self.restart_cmd}, nodes)
@utils.require_variables('TERMINATE_CMD', 'SERVICE_NAME')
@utils.require_variables('terminate_cmd')
def terminate(self, nodes=None):
nodes = nodes if nodes is not None else self.get_nodes()
LOG.info("Terminate '%s' service on nodes: %s", self.SERVICE_NAME,
LOG.info("Terminate '%s' service on nodes: %s", self.service_name,
nodes.get_ips())
self._run_task({'shell': self.TERMINATE_CMD}, nodes)
self._run_task({'shell': self.terminate_cmd}, nodes)
@utils.require_variables('START_CMD', 'SERVICE_NAME')
@utils.require_variables('start_cmd')
def start(self, nodes=None):
nodes = nodes if nodes is not None else self.get_nodes()
LOG.info("Start '%s' service on nodes: %s", self.SERVICE_NAME,
LOG.info("Start '%s' service on nodes: %s", self.service_name,
nodes.get_ips())
self._run_task({'shell': self.START_CMD}, nodes)
self._run_task({'shell': self.start_cmd}, nodes)
@utils.require_variables('GREP', 'SERVICE_NAME')
def kill(self, nodes=None):
nodes = nodes if nodes is not None else self.get_nodes()
LOG.info("Kill '%s' service on nodes: %s", self.SERVICE_NAME,
LOG.info("Kill '%s' service on nodes: %s", self.service_name,
nodes.get_ips())
cmd = {'kill': {'grep': self.GREP, 'sig': signal.SIGKILL}}
cmd = {'kill': {'grep': self.grep, 'sig': signal.SIGKILL}}
self._run_task(cmd, nodes)
@utils.require_variables('GREP', 'SERVICE_NAME')
def freeze(self, nodes=None, sec=None):
nodes = nodes if nodes is not None else self.get_nodes()
if sec:
cmd = {'freeze': {'grep': self.GREP, 'sec': sec}}
cmd = {'freeze': {'grep': self.grep, 'sec': sec}}
else:
cmd = {'kill': {'grep': self.GREP, 'sig': signal.SIGSTOP}}
LOG.info("Freeze '%s' service %son nodes: %s", self.SERVICE_NAME,
cmd = {'kill': {'grep': self.grep, 'sig': signal.SIGSTOP}}
LOG.info("Freeze '%s' service %son nodes: %s", self.service_name,
('for %s sec ' % sec) if sec else '', nodes.get_ips())
self._run_task(cmd, nodes)
@utils.require_variables('GREP', 'SERVICE_NAME')
def unfreeze(self, nodes=None):
nodes = nodes if nodes is not None else self.get_nodes()
LOG.info("Unfreeze '%s' service on nodes: %s", self.SERVICE_NAME,
LOG.info("Unfreeze '%s' service on nodes: %s", self.service_name,
nodes.get_ips())
cmd = {'kill': {'grep': self.GREP, 'sig': signal.SIGCONT}}
cmd = {'kill': {'grep': self.grep, 'sig': signal.SIGCONT}}
self._run_task(cmd, nodes)
@utils.require_variables('PORT', 'SERVICE_NAME')
@utils.require_variables('port')
def plug(self, nodes=None):
nodes = nodes if nodes is not None else self.get_nodes()
LOG.info("Open port %d for '%s' service on nodes: %s",
self.PORT[1], self.SERVICE_NAME, nodes.get_ips())
self._run_task({'iptables': {'protocol': self.PORT[0],
'port': self.PORT[1],
self.port[1], self.service_name, nodes.get_ips())
self._run_task({'iptables': {'protocol': self.port[0],
'port': self.port[1],
'action': 'unblock',
'service': self.SERVICE_NAME}}, nodes)
'service': self.service_name}}, nodes)
@utils.require_variables('PORT', 'SERVICE_NAME')
@utils.require_variables('port')
def unplug(self, nodes=None):
nodes = nodes if nodes is not None else self.get_nodes()
LOG.info("Close port %d for '%s' service on nodes: %s",
self.PORT[1], self.SERVICE_NAME, nodes.get_ips())
self._run_task({'iptables': {'protocol': self.PORT[0],
'port': self.PORT[1],
self.port[1], self.service_name, nodes.get_ips())
self._run_task({'iptables': {'protocol': self.port[0],
'port': self.port[1],
'action': 'block',
'service': self.SERVICE_NAME}}, nodes)
'service': self.service_name}}, nodes)
class LinuxService(ServiceAsProcess):
"""Linux service
Service that is defined in init.d and can be controled by `service`
CLI tool.
**Example configuration:**
.. code-block:: yaml
services:
app:
driver: linux_service
args:
linux_service: app
grep: my_app
port: ['tcp', 4242]
parameters:
- **linux_service** - name of a service
- **grep** - regexp for grep to find process PID
- **port** - tuple with two values - potocol, port number (optional)
"""
NAME = 'linux_service'
DESCRIPTION = 'Service in init.d'
CONFIG_SCHEMA = {
'type': 'object',
'properties': {
'linux_service': {'type': 'string'},
'grep': {'type': 'string'},
'port': PORT_SCHEMA,
},
'required': ['grep', 'linux_service'],
'additionalProperties': False,
}
@utils.require_variables('LINUX_SERVICE')
def __init__(self, *args, **kwargs):
super(LinuxService, self).__init__(*args, **kwargs)
self.linux_service = self.config['linux_service']
self.RESTART_CMD = 'service {} restart'.format(self.LINUX_SERVICE)
self.TERMINATE_CMD = 'service {} stop'.format(self.LINUX_SERVICE)
self.START_CMD = 'service {} start'.format(self.LINUX_SERVICE)
self.restart_cmd = 'service {} restart'.format(self.linux_service)
self.terminate_cmd = 'service {} stop'.format(self.linux_service)
self.start_cmd = 'service {} start'.format(self.linux_service)

View File

@ -18,7 +18,6 @@ from os_faults.api import cloud_management
from os_faults.api import node_collection
from os_faults.api import node_discover
from os_faults.common import service
from os_faults import utils
LOG = logging.getLogger(__name__)
@ -33,89 +32,64 @@ class DevStackNode(node_collection.NodeCollection):
class ServiceInScreen(service.ServiceAsProcess):
"""Service in Screen
This driver controls service that is started in a window of
`screen` tool.
**Example configuration:**
.. code-block:: yaml
services:
app:
driver: screen
args:
window_name: app
grep: my_app
port: ['tcp', 4242]
parameters:
- **window_name** - name of a service
- **grep** - regexp for grep to find process PID
- **port** - tuple with two values - potocol, port number (optional)
"""
NAME = 'screen'
DESCRIPTION = 'Service in screen'
CONFIG_SCHEMA = {
'type': 'object',
'properties': {
'window_name': {'type': 'string'},
'grep': {'type': 'string'},
'port': service.PORT_SCHEMA,
},
'required': ['grep', 'window_name'],
'additionalProperties': False,
}
@utils.require_variables('WINDOW_NAME')
def __init__(self, *args, **kwargs):
super(ServiceInScreen, self).__init__(*args, **kwargs)
self.window_name = self.config['window_name']
# sends ctr+c, arrow up key, enter key
self.RESTART_CMD = (
self.restart_cmd = (
"screen -S stack -p {window_name} -X "
"stuff $'\\003'$'\\033[A'$(printf \\\\r)").format(
window_name=self.WINDOW_NAME)
window_name=self.window_name)
# sends ctr+c
self.TERMINATE_CMD = (
self.terminate_cmd = (
"screen -S stack -p {window_name} -X "
"stuff $'\\003'").format(
window_name=self.WINDOW_NAME)
window_name=self.window_name)
# sends arrow up key, enter key
self.START_CMD = (
self.start_cmd = (
"screen -S stack -p {window_name} -X "
"stuff $'\\033[A'$(printf \\\\r)").format(
window_name=self.WINDOW_NAME)
class KeystoneService(service.ServiceAsProcess):
SERVICE_NAME = 'keystone'
GREP = 'keystone-'
RESTART_CMD = 'sudo service apache2 restart'
TERMINATE_CMD = 'sudo service apache2 stop'
START_CMD = 'sudo service apache2 start'
class MySQLService(service.ServiceAsProcess):
SERVICE_NAME = 'mysql'
GREP = 'mysqld'
RESTART_CMD = 'sudo service mysql restart'
TERMINATE_CMD = 'sudo service mysql stop'
START_CMD = 'sudo service mysql start'
PORT = ('tcp', 3307)
class RabbitMQService(service.ServiceAsProcess):
SERVICE_NAME = 'rabbitmq'
GREP = 'rabbitmq-server'
RESTART_CMD = 'sudo service rabbitmq-server restart'
TERMINATE_CMD = 'sudo service rabbitmq-server stop'
START_CMD = 'sudo service rabbitmq-server start'
class NovaAPIService(ServiceInScreen):
SERVICE_NAME = 'nova-api'
GREP = 'nova-api'
WINDOW_NAME = 'n-api'
class GlanceAPIService(ServiceInScreen):
SERVICE_NAME = 'glance-api'
GREP = 'glance-api'
WINDOW_NAME = 'g-api'
class NovaComputeService(ServiceInScreen):
SERVICE_NAME = 'nova-compute'
GREP = 'nova-compute'
WINDOW_NAME = 'n-cpu'
class NovaSchedulerService(ServiceInScreen):
SERVICE_NAME = 'nova-scheduler'
GREP = 'nova-scheduler'
WINDOW_NAME = 'n-sch'
class IronicApiService(ServiceInScreen):
SERVICE_NAME = 'ironic-api'
GREP = 'ironic-api'
WINDOW_NAME = 'ir-api'
class IronicConductorService(ServiceInScreen):
SERVICE_NAME = 'ironic-conductor'
GREP = 'ironic-conductor'
WINDOW_NAME = 'ir-cond'
window_name=self.window_name)
class DevStackManagement(cloud_management.CloudManagement,
@ -154,18 +128,78 @@ class DevStackManagement(cloud_management.CloudManagement,
NAME = 'devstack'
DESCRIPTION = 'DevStack management driver'
NODE_CLS = DevStackNode
SERVICE_NAME_TO_CLASS = {
'keystone': KeystoneService,
'mysql': MySQLService,
'rabbitmq': RabbitMQService,
'nova-api': NovaAPIService,
'glance-api': GlanceAPIService,
'nova-compute': NovaComputeService,
'nova-scheduler': NovaSchedulerService,
'ironic-api': IronicApiService,
'ironic-conductor': IronicConductorService,
SERVICES = {
'keystone': {
'driver': 'process',
'args': {
'grep': 'keystone-',
'restart_cmd': 'sudo service apache2 restart',
'terminate_cmd': 'sudo service apache2 stop',
'start_cmd': 'sudo service apache2 start',
}
},
'mysql': {
'driver': 'process',
'args': {
'grep': 'mysqld',
'restart_cmd': 'sudo service mysql restart',
'terminate_cmd': 'sudo service mysql stop',
'start_cmd': 'sudo service mysql start',
'port': ['tcp', 3307],
}
},
'rabbitmq': {
'driver': 'process',
'args': {
'grep': 'rabbitmq-server',
'restart_cmd': 'sudo service rabbitmq-server restart',
'terminate_cmd': 'sudo service rabbitmq-server stop',
'start_cmd': 'sudo service rabbitmq-server start',
}
},
'nova-api': {
'driver': 'screen',
'args': {
'grep': 'nova-api',
'window_name': 'n-api',
}
},
'glance-api': {
'driver': 'screen',
'args': {
'grep': 'glance-api',
'window_name': 'g-api',
}
},
'nova-compute': {
'driver': 'screen',
'args': {
'grep': 'nova-compute',
'window_name': 'n-cpu',
}
},
'nova-scheduler': {
'driver': 'screen',
'args': {
'grep': 'nova-scheduler',
'window_name': 'n-sch',
}
},
'ironic-api': {
'driver': 'screen',
'args': {
'grep': 'ironic-api',
'window_name': 'ir-api',
}
},
'ironic-conductor': {
'driver': 'screen',
'args': {
'grep': 'ironic-conductor',
'window_name': 'ir-cond',
}
},
}
SUPPORTED_SERVICES = list(SERVICE_NAME_TO_CLASS.keys())
SUPPORTED_NETWORKS = ['all-in-one']
CONFIG_SCHEMA = {
'type': 'object',

View File

@ -19,7 +19,6 @@ from os_faults.api import cloud_management
from os_faults.api import node_collection
from os_faults.api import node_discover
from os_faults.common import service
from os_faults import utils
LOG = logging.getLogger(__name__)
@ -45,299 +44,122 @@ class FuelNodeCollection(node_collection.NodeCollection):
class PcsService(service.ServiceAsProcess):
"""Service as a resource in Pacemaker
Service that can be controled by `pcs resource` CLI tool.
**Example configuration:**
.. code-block:: yaml
services:
app:
driver: pcs_service
args:
pcs_service: app
grep: my_app
port: ['tcp', 4242]
parameters:
- **pcs_service** - name of a service
- **grep** - regexp for grep to find process PID
- **port** - tuple with two values - potocol, port number (optional)
"""
NAME = 'pcs_service'
DESCRIPTION = 'Service in pacemaker'
CONFIG_SCHEMA = {
'type': 'object',
'properties': {
'pcs_service': {'type': 'string'},
'grep': {'type': 'string'},
'port': service.PORT_SCHEMA,
},
'required': ['grep', 'pcs_service'],
'additionalProperties': False,
}
@utils.require_variables('PCS_SERVICE')
def __init__(self, *args, **kwargs):
super(PcsService, self).__init__(*args, **kwargs)
self.pcs_service = self.config['pcs_service']
self.RESTART_CMD = 'pcs resource restart {} $(hostname)'.format(
self.PCS_SERVICE)
self.TERMINATE_CMD = 'pcs resource ban {} $(hostname)'.format(
self.PCS_SERVICE)
self.START_CMD = 'pcs resource clear {} $(hostname)'.format(
self.PCS_SERVICE)
self.restart_cmd = 'pcs resource restart {} $(hostname)'.format(
self.pcs_service)
self.terminate_cmd = 'pcs resource ban {} $(hostname)'.format(
self.pcs_service)
self.start_cmd = 'pcs resource clear {} $(hostname)'.format(
self.pcs_service)
class PcsOrLinuxService(service.ServiceAsProcess):
"""Service as a resource in Pacemaker or Linux service
Service that can be controled by `pcs resource` CLI tool or
linux `service` tool. This is a hybrid driver that tries to find
service in Pacemaker and uses linux `service` if it is not found
there.
**Example configuration:**
.. code-block:: yaml
services:
app:
driver: pcs_or_linux_service
args:
pcs_service: p_app
linux_service: app
grep: my_app
port: ['tcp', 4242]
parameters:
- **pcs_service** - name of a service in Pacemaker
- **linux_service** - name of a service in init.d
- **grep** - regexp for grep to find process PID
- **port** - tuple with two values - potocol, port number (optional)
"""
NAME = 'pcs_or_linux_service'
DESCRIPTION = 'Service in pacemaker or init.d'
CONFIG_SCHEMA = {
'type': 'object',
'properties': {
'pcs_service': {'type': 'string'},
'linux_service': {'type': 'string'},
'grep': {'type': 'string'},
'port': service.PORT_SCHEMA,
},
'required': ['grep', 'pcs_service', 'linux_service'],
'additionalProperties': False,
}
@utils.require_variables('PCS_SERVICE', 'LINUX_SERVICE')
def __init__(self, *args, **kwargs):
super(PcsOrLinuxService, self).__init__(*args, **kwargs)
self.pcs_service = self.config.get('pcs_service')
self.linux_service = self.config.get('linux_service')
self.RESTART_CMD = (
self.restart_cmd = (
'if pcs resource show {pcs_service}; '
'then pcs resource restart {pcs_service} $(hostname); '
'else service {linux_service} restart; fi').format(
linux_service=self.LINUX_SERVICE,
pcs_service=self.PCS_SERVICE)
self.TERMINATE_CMD = (
linux_service=self.linux_service,
pcs_service=self.pcs_service)
self.terminate_cmd = (
'if pcs resource show {pcs_service}; '
'then pcs resource ban {pcs_service} $(hostname); '
'else service {linux_service} stop; fi').format(
linux_service=self.LINUX_SERVICE,
pcs_service=self.PCS_SERVICE)
self.START_CMD = (
linux_service=self.linux_service,
pcs_service=self.pcs_service)
self.start_cmd = (
'if pcs resource show {pcs_service}; '
'then pcs resource clear {pcs_service} $(hostname); '
'else service {linux_service} start; fi').format(
linux_service=self.LINUX_SERVICE,
pcs_service=self.PCS_SERVICE)
class KeystoneService(service.LinuxService):
SERVICE_NAME = 'keystone'
GREP = 'keystone'
LINUX_SERVICE = 'apache2'
class HorizonService(service.LinuxService):
SERVICE_NAME = 'horizon'
GREP = 'apache2'
LINUX_SERVICE = 'apache2'
class MemcachedService(service.LinuxService):
SERVICE_NAME = 'memcached'
GREP = 'memcached'
LINUX_SERVICE = 'memcached'
class MySQLService(PcsService):
SERVICE_NAME = 'mysql'
GREP = 'mysqld'
PCS_SERVICE = 'p_mysqld'
PORT = ('tcp', 3307)
class RabbitMQService(PcsService):
SERVICE_NAME = 'rabbitmq'
GREP = 'rabbit tcp_listeners'
PCS_SERVICE = 'p_rabbitmq-server'
class GlanceAPIService(service.LinuxService):
SERVICE_NAME = 'glance-api'
GREP = 'glance-api'
LINUX_SERVICE = 'glance-api'
class GlanceGlareService(service.LinuxService):
SERVICE_NAME = 'glance-glare'
GREP = 'glance-glare'
LINUX_SERVICE = 'glance-glare'
class GlanceRegistryService(service.LinuxService):
SERVICE_NAME = 'glance-registry'
GREP = 'glance-registry'
LINUX_SERVICE = 'glance-registry'
class NovaAPIService(service.LinuxService):
SERVICE_NAME = 'nova-api'
GREP = 'nova-api'
LINUX_SERVICE = 'nova-api'
class NovaComputeService(service.LinuxService):
SERVICE_NAME = 'nova-compute'
GREP = 'nova-compute'
LINUX_SERVICE = 'nova-compute'
class NovaSchedulerService(service.LinuxService):
SERVICE_NAME = 'nova-scheduler'
GREP = 'nova-scheduler'
LINUX_SERVICE = 'nova-scheduler'
class NovaCertService(service.LinuxService):
SERVICE_NAME = 'nova-cert'
GREP = 'nova-cert'
LINUX_SERVICE = 'nova-cert'
class NovaConductorService(service.LinuxService):
SERVICE_NAME = 'nova-conductor'
GREP = 'nova-conductor'
LINUX_SERVICE = 'nova-conductor'
class NovaConsoleAuthService(service.LinuxService):
SERVICE_NAME = 'nova-consoleauth'
GREP = 'nova-consoleauth'
LINUX_SERVICE = 'nova-consoleauth'
class NovaNoVNCProxyService(service.LinuxService):
SERVICE_NAME = 'nova-novncproxy'
GREP = 'nova-novncproxy'
LINUX_SERVICE = 'nova-novncproxy'
class NeutronServerService(service.LinuxService):
SERVICE_NAME = 'neutron-server'
GREP = 'neutron-server'
LINUX_SERVICE = 'neutron-server'
class NeutronDhcpAgentService(PcsService):
SERVICE_NAME = 'neutron-dhcp-agent'
GREP = 'neutron-dhcp-agent'
PCS_SERVICE = 'neutron-dhcp-agent'
class NeutronMetadataAgentService(PcsOrLinuxService):
SERVICE_NAME = 'neutron-metadata-agent'
GREP = 'neutron-metadata-agent'
PCS_SERVICE = 'neutron-metadata-agent'
LINUX_SERVICE = 'neutron-metadata-agent'
class NeutronOpenvswitchAgentService(PcsOrLinuxService):
SERVICE_NAME = 'neutron-openvswitch-agent'
GREP = 'neutron-openvswitch-agent'
PCS_SERVICE = 'neutron-openvswitch-agent'
LINUX_SERVICE = 'neutron-openvswitch-agent'
class NeutronL3AgentService(PcsOrLinuxService):
SERVICE_NAME = 'neutron-l3-agent'
GREP = 'neutron-l3-agent'
PCS_SERVICE = 'neutron-l3-agent'
LINUX_SERVICE = 'neutron-l3-agent'
class HeatAPIService(service.LinuxService):
SERVICE_NAME = 'heat-api'
GREP = 'heat-api'
LINUX_SERVICE = 'heat-api'
class HeatEngineService(PcsService):
SERVICE_NAME = 'heat-engine'
GREP = 'heat-engine'
PCS_SERVICE = 'p_heat-engine'
class CinderAPIService(service.LinuxService):
SERVICE_NAME = 'cinder-api'
GREP = 'cinder-api'
LINUX_SERVICE = 'cinder-api'
class CinderSchedulerService(service.LinuxService):
SERVICE_NAME = 'cinder-scheduler'
GREP = 'cinder-scheduler'
LINUX_SERVICE = 'cinder-scheduler'
class CinderVolumeService(service.LinuxService):
SERVICE_NAME = 'cinder-volume'
GREP = 'cinder-volume'
LINUX_SERVICE = 'cinder-volume'
class CinderBackupService(service.LinuxService):
SERVICE_NAME = 'cinder-backup'
GREP = 'cinder-backup'
LINUX_SERVICE = 'cinder-backup'
class IronicApiService(service.LinuxService):
SERVICE_NAME = 'ironic-api'
GREP = 'ironic-api'
LINUX_SERVICE = 'ironic-api'
class IronicConductorService(service.LinuxService):
SERVICE_NAME = 'ironic-conductor'
GREP = 'ironic-conductor'
LINUX_SERVICE = 'ironic-conductor'
class SwiftAccountService(service.LinuxService):
SERVICE_NAME = 'swift-account'
GREP = 'swift-account'
LINUX_SERVICE = 'swift-account'
class SwiftAccountAuditorService(service.LinuxService):
SERVICE_NAME = 'swift-account-auditor'
GREP = 'swift-account-auditor'
LINUX_SERVICE = 'swift-account-auditor'
class SwiftAccountReaperService(service.LinuxService):
SERVICE_NAME = 'swift-account-reaper'
GREP = 'swift-account-reaper'
LINUX_SERVICE = 'swift-account-reaper'
class SwiftAccountReplicatorService(service.LinuxService):
SERVICE_NAME = 'swift-account-replicator'
GREP = 'swift-account-replicator'
LINUX_SERVICE = 'swift-account-replicator'
class SwiftContainerService(service.LinuxService):
SERVICE_NAME = 'swift-container'
GREP = 'swift-container'
LINUX_SERVICE = 'swift-container'
class SwiftContainerAuditorService(service.LinuxService):
SERVICE_NAME = 'swift-container-auditor'
GREP = 'swift-container-auditor'
LINUX_SERVICE = 'swift-container-auditor'
class SwiftContainerReplicatorService(service.LinuxService):
SERVICE_NAME = 'swift-container-replicator'
GREP = 'swift-container-replicator'
LINUX_SERVICE = 'swift-container-replicator'
class SwiftContainerSyncService(service.LinuxService):
SERVICE_NAME = 'swift-container-sync'
GREP = 'swift-container-sync'
LINUX_SERVICE = 'swift-container-sync'
class SwiftContainerUpdaterService(service.LinuxService):
SERVICE_NAME = 'swift-container-updater'
GREP = 'swift-container-updater'
LINUX_SERVICE = 'swift-container-updater'
class SwiftObjectService(service.LinuxService):
SERVICE_NAME = 'swift-object'
GREP = 'swift-object'
LINUX_SERVICE = 'swift-object'
class SwiftObjectAuditorService(service.LinuxService):
SERVICE_NAME = 'swift-object-auditor'
GREP = 'swift-object-auditor'
LINUX_SERVICE = 'swift-object-auditor'
class SwiftObjectReplicatorService(service.LinuxService):
SERVICE_NAME = 'swift-object-replicator'
GREP = 'swift-object-replicator'
LINUX_SERVICE = 'swift-object-replicator'
class SwiftObjectUpdaterService(service.LinuxService):
SERVICE_NAME = 'swift-object-updater'
GREP = 'swift-object-updater'
LINUX_SERVICE = 'swift-object-updater'
class SwiftProxyService(service.LinuxService):
SERVICE_NAME = 'swift-proxy'
GREP = 'swift-proxy'
LINUX_SERVICE = 'swift-proxy'
linux_service=self.linux_service,
pcs_service=self.pcs_service)
class FuelManagement(cloud_management.CloudManagement,
@ -370,51 +192,306 @@ class FuelManagement(cloud_management.CloudManagement,
NAME = 'fuel'
DESCRIPTION = 'Fuel 9.x cloud management driver'
NODE_CLS = FuelNodeCollection
SERVICE_NAME_TO_CLASS = {
'keystone': KeystoneService,
'horizon': HorizonService,
'memcached': MemcachedService,
'mysql': MySQLService,
'rabbitmq': RabbitMQService,
'glance-api': GlanceAPIService,
'glance-glare': GlanceGlareService,
'glance-registry': GlanceRegistryService,
'nova-api': NovaAPIService,
'nova-compute': NovaComputeService,
'nova-scheduler': NovaSchedulerService,
'nova-cert': NovaCertService,
'nova-conductor': NovaConductorService,
'nova-consoleauth': NovaConsoleAuthService,
'nova-novncproxy': NovaNoVNCProxyService,
'neutron-server': NeutronServerService,
'neutron-dhcp-agent': NeutronDhcpAgentService,
'neutron-metadata-agent': NeutronMetadataAgentService,
'neutron-openvswitch-agent': NeutronOpenvswitchAgentService,
'neutron-l3-agent': NeutronL3AgentService,
'heat-api': HeatAPIService,
'heat-engine': HeatEngineService,
'cinder-api': CinderAPIService,
'cinder-scheduler': CinderSchedulerService,
'cinder-volume': CinderVolumeService,
'cinder-backup': CinderBackupService,
'ironic-api': IronicApiService,
'ironic-conductor': IronicConductorService,
'swift-account': SwiftAccountService,
'swift-account-auditor': SwiftAccountAuditorService,
'swift-account-reaper': SwiftAccountReaperService,
'swift-account-replicator': SwiftAccountReplicatorService,
'swift-container': SwiftContainerService,
'swift-container-auditor': SwiftContainerAuditorService,
'swift-container-replicator': SwiftContainerReplicatorService,
'swift-container-sync': SwiftContainerSyncService,
'swift-container-updater': SwiftContainerUpdaterService,
'swift-object': SwiftObjectService,
'swift-object-auditor': SwiftObjectAuditorService,
'swift-object-replicator': SwiftObjectReplicatorService,
'swift-object-updater': SwiftObjectUpdaterService,
'swift-proxy': SwiftProxyService,
SERVICES = {
'keystone': {
'driver': 'linux_service',
'args': {
'grep': 'keystone',
'linux_service': 'apache2',
}
},
'horizon': {
'driver': 'linux_service',
'args': {
'grep': 'apache2',
'linux_service': 'apache2',
}
},
'memcached': {
'driver': 'linux_service',
'args': {
'grep': 'memcached',
'linux_service': 'memcached',
}
},
'mysql': {
'driver': 'pcs_service',
'args': {
'grep': 'mysqld',
'pcs_service': 'p_mysqld',
'port': ['tcp', 3307],
}
},
'rabbitmq': {
'driver': 'pcs_service',
'args': {
'grep': 'rabbit tcp_listeners',
'pcs_service': 'p_rabbitmq-server',
}
},
'glance-api': {
'driver': 'linux_service',
'args': {
'grep': 'glance-api',
'linux_service': 'glance-api',
}
},
'glance-glare': {
'driver': 'linux_service',
'args': {
'grep': 'glance-glare',
'linux_service': 'glance-glare',
}
},
'glance-registry': {
'driver': 'linux_service',
'args': {
'grep': 'glance-registry',
'linux_service': 'glance-registry',
}
},
'nova-api': {
'driver': 'linux_service',
'args': {
'grep': 'nova-api',
'linux_service': 'nova-api',
}
},
'nova-compute': {
'driver': 'linux_service',
'args': {
'grep': 'nova-compute',
'linux_service': 'nova-compute',
}
},
'nova-scheduler': {
'driver': 'linux_service',
'args': {
'grep': 'nova-scheduler',
'linux_service': 'nova-scheduler',
}
},
'nova-cert': {
'driver': 'linux_service',
'args': {
'grep': 'nova-cert',
'linux_service': 'nova-cert',
}
},
'nova-conductor': {
'driver': 'linux_service',
'args': {
'grep': 'nova-conductor',
'linux_service': 'nova-conductor',
}
},
'nova-consoleauth': {
'driver': 'linux_service',
'args': {
'grep': 'nova-consoleauth',
'linux_service': 'nova-consoleauth',
}
},
'nova-novncproxy': {
'driver': 'linux_service',
'args': {
'grep': 'nova-novncproxy',
'linux_service': 'nova-novncproxy',
}
},
'neutron-server': {
'driver': 'linux_service',
'args': {
'grep': 'neutron-server',
'linux_service': 'neutron-server',
}
},
'neutron-dhcp-agent': {
'driver': 'pcs_service',
'args': {
'grep': 'neutron-dhcp-agent',
'pcs_service': 'neutron-dhcp-agent',
}
},
'neutron-metadata-agent': {
'driver': 'pcs_or_linux_service',
'args': {
'grep': 'neutron-metadata-agent',
'pcs_service': 'neutron-metadata-agent',
'linux_service': 'neutron-metadata-agent',
}
},
'neutron-openvswitch-agent': {
'driver': 'pcs_or_linux_service',
'args': {
'grep': 'neutron-openvswitch-agent',
'pcs_service': 'neutron-openvswitch-agent',
'linux_service': 'neutron-openvswitch-agent',
}
},
'neutron-l3-agent': {
'driver': 'pcs_or_linux_service',
'args': {
'grep': 'neutron-l3-agent',
'pcs_service': 'neutron-l3-agent',
'linux_service': 'neutron-l3-agent',
}
},
'heat-api': {
'driver': 'linux_service',
'args': {
'grep': 'heat-api',
'linux_service': 'heat-api',
}
},
'heat-engine': {
'driver': 'pcs_service',
'args': {
'grep': 'heat-engine',
'pcs_service': 'p_heat-engine',
}
},
'cinder-api': {
'driver': 'linux_service',
'args': {
'grep': 'cinder-api',
'linux_service': 'cinder-api',
}
},
'cinder-scheduler': {
'driver': 'linux_service',
'args': {
'grep': 'cinder-scheduler',
'linux_service': 'cinder-scheduler',
}
},
'cinder-volume': {
'driver': 'linux_service',
'args': {
'grep': 'cinder-volume',
'linux_service': 'cinder-volume',
}
},
'cinder-backup': {
'driver': 'linux_service',
'args': {
'grep': 'cinder-backup',
'linux_service': 'cinder-backup',
}
},
'ironic-api': {
'driver': 'linux_service',
'args': {
'grep': 'ironic-api',
'linux_service': 'ironic-api',
}
},
'ironic-conductor': {
'driver': 'linux_service',
'args': {
'grep': 'ironic-conductor',
'linux_service': 'ironic-conductor',
}
},
'swift-account': {
'driver': 'linux_service',
'args': {
'grep': 'swift-account',
'linux_service': 'swift-account',
}
},
'swift-account-auditor': {
'driver': 'linux_service',
'args': {
'grep': 'swift-account-auditor',
'linux_service': 'swift-account-auditor',
}
},
'swift-account-reaper': {
'driver': 'linux_service',
'args': {
'grep': 'swift-account-reaper',
'linux_service': 'swift-account-reaper',
}
},
'swift-account-replicator': {
'driver': 'linux_service',
'args': {
'grep': 'swift-account-replicator',
'linux_service': 'swift-account-replicator',
}
},
'swift-container': {
'driver': 'linux_service',
'args': {
'grep': 'swift-container',
'linux_service': 'swift-container',
}
},
'swift-container-auditor': {
'driver': 'linux_service',
'args': {
'grep': 'swift-container-auditor',
'linux_service': 'swift-container-auditor',
}
},
'swift-container-replicator': {
'driver': 'linux_service',
'args': {
'grep': 'swift-container-replicator',
'linux_service': 'swift-container-replicator',
}
},
'swift-container-sync': {
'driver': 'linux_service',
'args': {
'grep': 'swift-container-sync',
'linux_service': 'swift-container-sync',
}
},
'swift-container-updater': {
'driver': 'linux_service',
'args': {
'grep': 'swift-container-updater',
'linux_service': 'swift-container-updater',
}
},
'swift-object': {
'driver': 'linux_service',
'args': {
'grep': 'swift-object',
'linux_service': 'swift-object',
}
},
'swift-object-auditor': {
'driver': 'linux_service',
'args': {
'grep': 'swift-object-auditor',
'linux_service': 'swift-object-auditor',
}
},
'swift-object-replicator': {
'driver': 'linux_service',
'args': {
'grep': 'swift-object-replicator',
'linux_service': 'swift-object-replicator',
}
},
'swift-object-updater': {
'driver': 'linux_service',
'args': {
'grep': 'swift-object-updater',
'linux_service': 'swift-object-updater',
}
},
'swift-proxy': {
'driver': 'linux_service',
'args': {
'grep': 'swift-proxy',
'linux_service': 'swift-proxy',
}
},
}
SUPPORTED_SERVICES = list(SERVICE_NAME_TO_CLASS.keys())
SUPPORTED_NETWORKS = ['management', 'private', 'public', 'storage']
CONFIG_SCHEMA = {
'type': 'object',
@ -424,7 +501,6 @@ class FuelManagement(cloud_management.CloudManagement,
'username': {'type': 'string'},
'private_key_file': {'type': 'string'},
'slave_direct_ssh': {'type': 'boolean'},
},
'required': ['address', 'username'],
'additionalProperties': False,

View File

@ -21,7 +21,6 @@ from os_faults.api import node_collection
from os_faults.api import node_discover
from os_faults.common import service
from os_faults import error
from os_faults import utils
LOG = logging.getLogger(__name__)
@ -42,195 +41,50 @@ SALT_START = SALT_CALL + 'service.start {service}'
class SaltService(service.ServiceAsProcess):
"""Salt service
Service that can be controled by `salt service.*` commands.
**Example configuration:**
.. code-block:: yaml
services:
app:
driver: salt_service
args:
salt_service: app
grep: my_app
port: ['tcp', 4242]
parameters:
- **salt_service** - name of a service
- **grep** - regexp for grep to find process PID
- **port** - tuple with two values - potocol, port number (optional)
"""
NAME = 'salt_service'
DESCRIPTION = 'Service in salt'
CONFIG_SCHEMA = {
'type': 'object',
'properties': {
'salt_service': {'type': 'string'},
'grep': {'type': 'string'},
'port': service.PORT_SCHEMA,
},
'required': ['grep', 'salt_service'],
'additionalProperties': False,
}
@utils.require_variables('SALT_SERVICE')
def __init__(self, *args, **kwargs):
super(SaltService, self).__init__(*args, **kwargs)
self.salt_service = self.config['salt_service']
self.RESTART_CMD = SALT_RESTART.format(service=self.SALT_SERVICE)
self.TERMINATE_CMD = SALT_TERMINATE.format(service=self.SALT_SERVICE)
self.START_CMD = SALT_START.format(service=self.SALT_SERVICE)
class KeystoneService(SaltService):
SERVICE_NAME = 'keystone'
GREP = 'keystone-all'
SALT_SERVICE = 'keystone'
class HorizonService(SaltService):
SERVICE_NAME = 'horizon'
GREP = 'apache2'
SALT_SERVICE = 'apache2'
class MemcachedService(SaltService):
SERVICE_NAME = 'memcached'
GREP = 'memcached'
SALT_SERVICE = 'memcached'
class MySQLService(SaltService):
SERVICE_NAME = 'mysql'
GREP = 'mysqld'
SALT_SERVICE = 'mysql'
PORT = ('tcp', 3307)
class RabbitMQService(SaltService):
SERVICE_NAME = 'rabbitmq'
GREP = 'beam\.smp .*rabbitmq_server'
SALT_SERVICE = 'rabbitmq-server'
class GlanceAPIService(SaltService):
SERVICE_NAME = 'glance-api'
GREP = 'glance-api'
SALT_SERVICE = 'glance-api'
class GlanceRegistryService(SaltService):
SERVICE_NAME = 'glance-registry'
GREP = 'glance-registry'
SALT_SERVICE = 'glance-registry'
class NovaAPIService(SaltService):
SERVICE_NAME = 'nova-api'
GREP = 'nova-api'
SALT_SERVICE = 'nova-api'
class NovaComputeService(SaltService):
SERVICE_NAME = 'nova-compute'
GREP = 'nova-compute'
SALT_SERVICE = 'nova-compute'
class NovaSchedulerService(SaltService):
SERVICE_NAME = 'nova-scheduler'
GREP = 'nova-scheduler'
SALT_SERVICE = 'nova-scheduler'
class NovaCertService(SaltService):
SERVICE_NAME = 'nova-cert'
GREP = 'nova-cert'
SALT_SERVICE = 'nova-cert'
class NovaConductorService(SaltService):
SERVICE_NAME = 'nova-conductor'
GREP = 'nova-conductor'
SALT_SERVICE = 'nova-conductor'
class NovaConsoleAuthService(SaltService):
SERVICE_NAME = 'nova-consoleauth'
GREP = 'nova-consoleauth'
SALT_SERVICE = 'nova-consoleauth'
class NovaNoVNCProxyService(SaltService):
SERVICE_NAME = 'nova-novncproxy'
GREP = 'nova-novncproxy'
SALT_SERVICE = 'nova-novncproxy'
class NeutronServerService(SaltService):
SERVICE_NAME = 'neutron-server'
GREP = 'neutron-server'
SALT_SERVICE = 'neutron-server'
class NeutronDhcpAgentService(SaltService):
SERVICE_NAME = 'neutron-dhcp-agent'
GREP = 'neutron-dhcp-agent'
SALT_SERVICE = 'neutron-dhcp-agent'
class NeutronMetadataAgentService(SaltService):
SERVICE_NAME = 'neutron-metadata-agent'
GREP = 'neutron-metadata-agent'
SALT_SERVICE = 'neutron-metadata-agent'
class NeutronOpenvswitchAgentService(SaltService):
SERVICE_NAME = 'neutron-openvswitch-agent'
GREP = 'neutron-openvswitch-agent'
SALT_SERVICE = 'neutron-openvswitch-agent'
class NeutronL3AgentService(SaltService):
SERVICE_NAME = 'neutron-l3-agent'
GREP = 'neutron-l3-agent'
SALT_SERVICE = 'neutron-l3-agent'
class HeatAPIService(SaltService):
SERVICE_NAME = 'heat-api'
GREP = 'heat-api ' # space at the end filters heat-api-* services
SALT_SERVICE = 'heat-api'
class HeatEngineService(SaltService):
SERVICE_NAME = 'heat-engine'
GREP = 'heat-engine'
SALT_SERVICE = 'heat-engine'
class CinderAPIService(SaltService):
SERVICE_NAME = 'cinder-api'
GREP = 'cinder-api'
SALT_SERVICE = 'cinder-api'
class CinderSchedulerService(SaltService):
SERVICE_NAME = 'cinder-scheduler'
GREP = 'cinder-scheduler'
SALT_SERVICE = 'cinder-scheduler'
class CinderVolumeService(SaltService):
SERVICE_NAME = 'cinder-volume'
GREP = 'cinder-volume'
SALT_SERVICE = 'cinder-volume'
class CinderBackupService(SaltService):
SERVICE_NAME = 'cinder-backup'
GREP = 'cinder-backup'
SALT_SERVICE = 'cinder-backup'
class ElasticSearchService(SaltService):
SERVICE_NAME = 'elasticsearch'
GREP = 'java .*elasticsearch'
SALT_SERVICE = 'elasticsearch'
class GrafanaServerService(SaltService):
SERVICE_NAME = 'grafana-server'
GREP = 'grafana-server'
SALT_SERVICE = 'grafana-server'
class InfluxDBService(SaltService):
SERVICE_NAME = 'influxdb'
GREP = 'influxd'
SALT_SERVICE = 'influxdb'
class KibanaService(SaltService):
SERVICE_NAME = 'kibana'
GREP = 'kibana'
SALT_SERVICE = 'kibana'
class Nagios3Service(SaltService):
SERVICE_NAME = 'nagios3'
GREP = 'nagios3'
SALT_SERVICE = 'nagios3'
self.restart_cmd = SALT_RESTART.format(service=self.salt_service)
self.terminate_cmd = SALT_TERMINATE.format(service=self.salt_service)
self.start_cmd = SALT_START.format(service=self.salt_service)
class TCPCloudManagement(cloud_management.CloudManagement,
@ -279,39 +133,220 @@ class TCPCloudManagement(cloud_management.CloudManagement,
NAME = 'tcpcloud'
DESCRIPTION = 'TCPCloud management driver'
NODE_CLS = TCPCloudNodeCollection
SERVICE_NAME_TO_CLASS = {
'keystone': KeystoneService,
'horizon': HorizonService,
'memcached': MemcachedService,
'mysql': MySQLService,
'rabbitmq': RabbitMQService,
'glance-api': GlanceAPIService,
'glance-registry': GlanceRegistryService,
'nova-api': NovaAPIService,
'nova-compute': NovaComputeService,
'nova-scheduler': NovaSchedulerService,
'nova-cert': NovaCertService,
'nova-conductor': NovaConductorService,
'nova-consoleauth': NovaConsoleAuthService,
'nova-novncproxy': NovaNoVNCProxyService,
'neutron-server': NeutronServerService,
'neutron-dhcp-agent': NeutronDhcpAgentService,
'neutron-metadata-agent': NeutronMetadataAgentService,
'neutron-openvswitch-agent': NeutronOpenvswitchAgentService,
'neutron-l3-agent': NeutronL3AgentService,
'heat-api': HeatAPIService,
'heat-engine': HeatEngineService,
'cinder-api': CinderAPIService,
'cinder-scheduler': CinderSchedulerService,
'cinder-volume': CinderVolumeService,
'cinder-backup': CinderBackupService,
'elasticsearch': ElasticSearchService,
'grafana-server': GrafanaServerService,
'influxdb': InfluxDBService,
'kibana': KibanaService,
'nagios3': Nagios3Service,
SERVICES = {
'keystone': {
'driver': 'salt_service',
'args': {
'grep': 'keystone-all',
'salt_service': 'keystone',
}
},
'horizon': {
'driver': 'salt_service',
'args': {
'grep': 'apache2',
'salt_service': 'apache2',
}
},
'memcached': {
'driver': 'salt_service',
'args': {
'grep': 'memcached',
'salt_service': 'memcached',
}
},
'mysql': {
'driver': 'salt_service',
'args': {
'grep': 'mysqld',
'salt_service': 'mysql',
'port': ['tcp', 3307],
}
},
'rabbitmq': {
'driver': 'salt_service',
'args': {
'grep': 'beam\.smp .*rabbitmq_server',
'salt_service': 'rabbitmq-server',
}
},
'glance-api': {
'driver': 'salt_service',
'args': {
'grep': 'glance-api',
'salt_service': 'glance-api',
}
},
'glance-registry': {
'driver': 'salt_service',
'args': {
'grep': 'glance-registry',
'salt_service': 'glance-registry',
}
},
'nova-api': {
'driver': 'salt_service',
'args': {
'grep': 'nova-api',
'salt_service': 'nova-api',
}
},
'nova-compute': {
'driver': 'salt_service',
'args': {
'grep': 'nova-compute',
'salt_service': 'nova-compute',
}
},
'nova-scheduler': {
'driver': 'salt_service',
'args': {
'grep': 'nova-scheduler',
'salt_service': 'nova-scheduler',
}
},
'nova-cert': {
'driver': 'salt_service',
'args': {
'grep': 'nova-cert',
'salt_service': 'nova-cert',
}
},
'nova-conductor': {
'driver': 'salt_service',
'args': {
'grep': 'nova-conductor',
'salt_service': 'nova-conductor',
}
},
'nova-consoleauth': {
'driver': 'salt_service',
'args': {
'grep': 'nova-consoleauth',
'salt_service': 'nova-consoleauth',
}
},
'nova-novncproxy': {
'driver': 'salt_service',
'args': {
'grep': 'nova-novncproxy',
'salt_service': 'nova-novncproxy',
}
},
'neutron-server': {
'driver': 'salt_service',
'args': {
'grep': 'neutron-server',
'salt_service': 'neutron-server',
}
},
'neutron-dhcp-agent': {
'driver': 'salt_service',
'args': {
'grep': 'neutron-dhcp-agent',
'salt_service': 'neutron-dhcp-agent',
}
},
'neutron-metadata-agent': {
'driver': 'salt_service',
'args': {
'grep': 'neutron-metadata-agent',
'salt_service': 'neutron-metadata-agent',
}
},
'neutron-openvswitch-agent': {
'driver': 'salt_service',
'args': {
'grep': 'neutron-openvswitch-agent',
'salt_service': 'neutron-openvswitch-agent',
}
},
'neutron-l3-agent': {
'driver': 'salt_service',
'args': {
'grep': 'neutron-l3-agent',
'salt_service': 'neutron-l3-agent',
}
},
'heat-api': {
'driver': 'salt_service',
'args': {
# space at the end filters heat-api-* services
'grep': 'heat-api ',
'salt_service': 'heat-api',
}
},
'heat-engine': {
'driver': 'salt_service',
'args': {
'grep': 'heat-engine',
'salt_service': 'heat-engine',
}
},
'cinder-api': {
'driver': 'salt_service',
'args': {
'grep': 'cinder-api',
'salt_service': 'cinder-api',
}
},
'cinder-scheduler': {
'driver': 'salt_service',
'args': {
'grep': 'cinder-scheduler',
'salt_service': 'cinder-scheduler',
}
},
'cinder-volume': {
'driver': 'salt_service',
'args': {
'grep': 'cinder-volume',
'salt_service': 'cinder-volume',
}
},
'cinder-backup': {
'driver': 'salt_service',
'args': {
'grep': 'cinder-backup',
'salt_service': 'cinder-backup',
}
},
'elasticsearch': {
'driver': 'salt_service',
'args': {
'grep': 'java .*elasticsearch',
'salt_service': 'elasticsearch',
}
},
'grafana-server': {
'driver': 'salt_service',
'args': {
'grep': 'grafana-server',
'salt_service': 'grafana-server',
}
},
'influxdb': {
'driver': 'salt_service',
'args': {
'grep': 'influxd',
'salt_service': 'influxdb',
}
},
'kibana': {
'driver': 'salt_service',
'args': {
'grep': 'kibana',
'salt_service': 'kibana',
}
},
'nagios3': {
'driver': 'salt_service',
'args': {
'grep': 'nagios3',
'salt_service': 'nagios3',
}
},
}
SUPPORTED_SERVICES = list(SERVICE_NAME_TO_CLASS.keys())
SUPPORTED_NETWORKS = []
CONFIG_SCHEMA = {
'type': 'object',

View File

@ -17,21 +17,22 @@ import sys
from oslo_utils import importutils
import os_faults
from os_faults.api import base_driver
from os_faults.api import error
from os_faults import drivers
DRIVERS = {}
def _import_modules_from_package():
drivers_folder = os.path.dirname(drivers.__file__)
library_root = os.path.normpath(os.path.join(
os.path.join(drivers_folder, os.pardir), os.pardir))
folder = os.path.dirname(os_faults.__file__)
library_root = os.path.normpath(os.path.join(folder, os.pardir))
for root, dirs, files in os.walk(drivers_folder):
for root, dirs, files in os.walk(folder):
for filename in files:
if filename.startswith('__') or not filename.endswith('.py'):
if (filename.startswith('__') or
filename.startswith('test') or
not filename.endswith('.py')):
continue
relative_path = os.path.relpath(os.path.join(root, filename),
@ -56,16 +57,33 @@ def _list_drivers():
for class_info in class_info_list:
klazz = class_info[1]
if not issubclass(klazz, base_driver.BaseDriver):
continue
if 'NAME' not in vars(klazz): # driver must have a name
continue
if klazz.NAME == 'base': # skip base class
continue
if issubclass(klazz, base_driver.BaseDriver):
yield klazz
yield klazz
def get_drivers():
global DRIVERS
if not DRIVERS:
DRIVERS = dict((k.get_driver_name(), k) for k in _list_drivers())
DRIVERS = {}
for k in _list_drivers():
driver_name = k.get_driver_name()
if driver_name in DRIVERS:
orig_k = DRIVERS[driver_name]
orig_path = orig_k.__module__ + '.' + orig_k.__name__
dup_path = k.__module__ + '.' + k.__name__
raise error.OSFDriverWithSuchNameExists(
'Driver "%s" already defined in %s. '
'Found a duplicate in %s ' % (
driver_name, orig_path, dup_path))
DRIVERS[driver_name] = k
return DRIVERS

View File

@ -163,10 +163,8 @@ class DevStackManagementTestCase(test.TestCase):
nodes.hosts)
@mock.patch('os_faults.ansible.executor.AnsibleRunner', autospec=True)
@ddt.data(*devstack.DevStackManagement.SERVICE_NAME_TO_CLASS.items())
@ddt.unpack
def test_get_service_nodes(self, service_name, service_cls,
mock_ansible_runner):
@ddt.data(*devstack.DevStackManagement.SERVICES.keys())
def test_get_service_nodes(self, service_name, mock_ansible_runner):
ansible_runner_inst = mock_ansible_runner.return_value
ansible_runner_inst.execute.side_effect = [
[fakes.FakeAnsibleResult(payload={'stdout': '09:7b:74:90:63:c1'},
@ -177,12 +175,10 @@ class DevStackManagementTestCase(test.TestCase):
devstack_management = devstack.DevStackManagement(self.conf)
service = devstack_management.get_service(service_name)
self.assertIsInstance(service, service_cls)
nodes = service.get_nodes()
cmd = 'bash -c "ps ax | grep -v grep | grep \'{}\'"'.format(
service_cls.GREP)
service.grep)
ansible_runner_inst.execute.assert_has_calls([
mock.call(
['10.0.0.2'], {'command': 'cat /sys/class/net/eth0/address'}),
@ -202,9 +198,8 @@ class DevStackServiceTestCase(test.TestCase):
self.conf = {'address': '10.0.0.2', 'username': 'root'}
@mock.patch('os_faults.ansible.executor.AnsibleRunner', autospec=True)
@ddt.data(*devstack.DevStackManagement.SERVICE_NAME_TO_CLASS.items())
@ddt.unpack
def test_restart(self, service_name, service_cls, mock_ansible_runner):
@ddt.data(*devstack.DevStackManagement.SERVICES.keys())
def test_restart(self, service_name, mock_ansible_runner):
ansible_runner_inst = mock_ansible_runner.return_value
ansible_runner_inst.execute.side_effect = [
[fakes.FakeAnsibleResult(payload={'stdout': '09:7b:74:90:63:c1'},
@ -216,23 +211,20 @@ class DevStackServiceTestCase(test.TestCase):
devstack_management = devstack.DevStackManagement(self.conf)
service = devstack_management.get_service(service_name)
self.assertIsInstance(service, service_cls)
service.restart()
cmd = 'bash -c "ps ax | grep -v grep | grep \'{}\'"'.format(
service_cls.GREP)
service.grep)
ansible_runner_inst.execute.assert_has_calls([
mock.call(
['10.0.0.2'], {'command': 'cat /sys/class/net/eth0/address'}),
mock.call(['10.0.0.2'], {'command': cmd}, []),
mock.call(['10.0.0.2'], {'shell': service.RESTART_CMD})
mock.call(['10.0.0.2'], {'shell': service.restart_cmd})
])
@mock.patch('os_faults.ansible.executor.AnsibleRunner', autospec=True)
@ddt.data(*devstack.DevStackManagement.SERVICE_NAME_TO_CLASS.items())
@ddt.unpack
def test_terminate(self, service_name, service_cls, mock_ansible_runner):
@ddt.data(*devstack.DevStackManagement.SERVICES.keys())
def test_terminate(self, service_name, mock_ansible_runner):
ansible_runner_inst = mock_ansible_runner.return_value
ansible_runner_inst.execute.side_effect = [
[fakes.FakeAnsibleResult(payload={'stdout': '09:7b:74:90:63:c1'},
@ -244,23 +236,20 @@ class DevStackServiceTestCase(test.TestCase):
devstack_management = devstack.DevStackManagement(self.conf)
service = devstack_management.get_service(service_name)
self.assertIsInstance(service, service_cls)
service.terminate()
cmd = 'bash -c "ps ax | grep -v grep | grep \'{}\'"'.format(
service_cls.GREP)
service.grep)
ansible_runner_inst.execute.assert_has_calls([
mock.call(
['10.0.0.2'], {'command': 'cat /sys/class/net/eth0/address'}),
mock.call(['10.0.0.2'], {'command': cmd}, []),
mock.call(['10.0.0.2'], {'shell': service.TERMINATE_CMD})
mock.call(['10.0.0.2'], {'shell': service.terminate_cmd})
])
@mock.patch('os_faults.ansible.executor.AnsibleRunner', autospec=True)
@ddt.data(*devstack.DevStackManagement.SERVICE_NAME_TO_CLASS.items())
@ddt.unpack
def test_start(self, service_name, service_cls, mock_ansible_runner):
@ddt.data(*devstack.DevStackManagement.SERVICES.keys())
def test_start(self, service_name, mock_ansible_runner):
ansible_runner_inst = mock_ansible_runner.return_value
ansible_runner_inst.execute.side_effect = [
[fakes.FakeAnsibleResult(payload={'stdout': '09:7b:74:90:63:c1'},
@ -272,15 +261,13 @@ class DevStackServiceTestCase(test.TestCase):
devstack_management = devstack.DevStackManagement(self.conf)
service = devstack_management.get_service(service_name)
self.assertIsInstance(service, service_cls)
service.start()
cmd = 'bash -c "ps ax | grep -v grep | grep \'{}\'"'.format(
service_cls.GREP)
service.grep)
ansible_runner_inst.execute.assert_has_calls([
mock.call(
['10.0.0.2'], {'command': 'cat /sys/class/net/eth0/address'}),
mock.call(['10.0.0.2'], {'command': cmd}, []),
mock.call(['10.0.0.2'], {'shell': service.START_CMD})
mock.call(['10.0.0.2'], {'shell': service.start_cmd})
])

View File

@ -157,10 +157,8 @@ class FuelManagementTestCase(test.TestCase):
self.assertEqual(nodes.hosts, hosts)
@mock.patch('os_faults.ansible.executor.AnsibleRunner', autospec=True)
@ddt.data(*fuel.FuelManagement.SERVICE_NAME_TO_CLASS.items())
@ddt.unpack
def test_get_service_nodes(self, service_name, service_cls,
mock_ansible_runner):
@ddt.data(*fuel.FuelManagement.SERVICES.keys())
def test_get_service_nodes(self, service_name, mock_ansible_runner):
ansible_runner_inst = mock_ansible_runner.return_value
ansible_runner_inst.execute.side_effect = [
[self.fake_ansible_result],
@ -177,11 +175,10 @@ class FuelManagementTestCase(test.TestCase):
})
service = fuel_managment.get_service(service_name)
self.assertIsInstance(service, service_cls)
nodes = service.get_nodes()
cmd = 'bash -c "ps ax | grep -v grep | grep \'{}\'"'.format(
service_cls.GREP)
service.grep)
ansible_runner_inst.execute.assert_has_calls([
mock.call(['fuel.local'], {'command': 'fuel node --json'}),
mock.call(['10.0.0.2', '10.0.0.3'],

View File

@ -34,9 +34,8 @@ class FuelServiceTestCase(test.TestCase):
})
@mock.patch('os_faults.ansible.executor.AnsibleRunner', autospec=True)
@ddt.data(*fuel.FuelManagement.SERVICE_NAME_TO_CLASS.items())
@ddt.unpack
def test_kill(self, service_name, service_cls, mock_ansible_runner):
@ddt.data(*fuel.FuelManagement.SERVICES.keys())
def test_kill(self, service_name, mock_ansible_runner):
ansible_runner_inst = mock_ansible_runner.return_value
ansible_runner_inst.execute.side_effect = [
[self.fake_ansible_result],
@ -53,24 +52,21 @@ class FuelServiceTestCase(test.TestCase):
fuel_managment = fuel.FuelManagement(self.conf)
service = fuel_managment.get_service(service_name)
self.assertIsInstance(service, service_cls)
service.kill()
get_nodes_cmd = 'bash -c "ps ax | grep -v grep | grep \'{}\'"'.format(
service_cls.GREP)
service.grep)
ansible_runner_inst.execute.assert_has_calls([
mock.call(['fuel.local'], {'command': 'fuel node --json'}),
mock.call(['10.0.0.2', '10.0.0.3'],
{'command': get_nodes_cmd}, []),
mock.call(['10.0.0.2', '10.0.0.3'],
{'kill': {'grep': service_cls.GREP, 'sig': 9}}),
{'kill': {'grep': service.grep, 'sig': 9}}),
])
@mock.patch('os_faults.ansible.executor.AnsibleRunner', autospec=True)
@ddt.data(*fuel.FuelManagement.SERVICE_NAME_TO_CLASS.items())
@ddt.unpack
def test_freeze(self, service_name, service_cls, mock_ansible_runner):
@ddt.data(*fuel.FuelManagement.SERVICES.keys())
def test_freeze(self, service_name, mock_ansible_runner):
ansible_runner_inst = mock_ansible_runner.return_value
ansible_runner_inst.execute.side_effect = [
[self.fake_ansible_result],
@ -87,24 +83,21 @@ class FuelServiceTestCase(test.TestCase):
fuel_managment = fuel.FuelManagement(self.conf)
service = fuel_managment.get_service(service_name)
self.assertIsInstance(service, service_cls)
service.freeze()
get_nodes_cmd = 'bash -c "ps ax | grep -v grep | grep \'{}\'"'.format(
service_cls.GREP)
service.grep)
ansible_runner_inst.execute.assert_has_calls([
mock.call(['fuel.local'], {'command': 'fuel node --json'}),
mock.call(['10.0.0.2', '10.0.0.3'],
{'command': get_nodes_cmd}, []),
mock.call(['10.0.0.2', '10.0.0.3'],
{'kill': {'grep': service_cls.GREP, 'sig': 19}}),
{'kill': {'grep': service.grep, 'sig': 19}}),
])
@mock.patch('os_faults.ansible.executor.AnsibleRunner', autospec=True)
@ddt.data(*fuel.FuelManagement.SERVICE_NAME_TO_CLASS.items())
@ddt.unpack
def test_freeze_sec(self, service_name, service_cls, mock_ansible_runner):
@ddt.data(*fuel.FuelManagement.SERVICES.keys())
def test_freeze_sec(self, service_name, mock_ansible_runner):
ansible_runner_inst = mock_ansible_runner.return_value
ansible_runner_inst.execute.side_effect = [
[self.fake_ansible_result],
@ -121,26 +114,23 @@ class FuelServiceTestCase(test.TestCase):
fuel_managment = fuel.FuelManagement(self.conf)
service = fuel_managment.get_service(service_name)
self.assertIsInstance(service, service_cls)
delay_sec = 10
service.freeze(nodes=None, sec=delay_sec)
get_nodes_cmd = 'bash -c "ps ax | grep -v grep | grep \'{}\'"'.format(
service_cls.GREP)
service.grep)
ansible_runner_inst.execute.assert_has_calls([
mock.call(['fuel.local'], {'command': 'fuel node --json'}),
mock.call(['10.0.0.2', '10.0.0.3'],
{'command': get_nodes_cmd}, []),
mock.call(['10.0.0.2', '10.0.0.3'],
{'freeze': {'grep': service_cls.GREP,
{'freeze': {'grep': service.grep,
'sec': delay_sec}}),
])
@mock.patch('os_faults.ansible.executor.AnsibleRunner', autospec=True)
@ddt.data(*fuel.FuelManagement.SERVICE_NAME_TO_CLASS.items())
@ddt.unpack
def test_unfreeze(self, service_name, service_cls, mock_ansible_runner):
@ddt.data(*fuel.FuelManagement.SERVICES.keys())
def test_unfreeze(self, service_name, mock_ansible_runner):
ansible_runner_inst = mock_ansible_runner.return_value
ansible_runner_inst.execute.side_effect = [
[self.fake_ansible_result],
@ -157,24 +147,21 @@ class FuelServiceTestCase(test.TestCase):
fuel_managment = fuel.FuelManagement(self.conf)
service = fuel_managment.get_service(service_name)
self.assertIsInstance(service, service_cls)
service.unfreeze()
get_nodes_cmd = 'bash -c "ps ax | grep -v grep | grep \'{}\'"'.format(
service_cls.GREP)
service.grep)
ansible_runner_inst.execute.assert_has_calls([
mock.call(['fuel.local'], {'command': 'fuel node --json'}),
mock.call(['10.0.0.2', '10.0.0.3'],
{'command': get_nodes_cmd}, []),
mock.call(['10.0.0.2', '10.0.0.3'],
{'kill': {'grep': service_cls.GREP, 'sig': 18}}),
{'kill': {'grep': service.grep, 'sig': 18}}),
])
@mock.patch('os_faults.ansible.executor.AnsibleRunner', autospec=True)
@ddt.data(('mysql', fuel.MySQLService))
@ddt.unpack
def test_unplug(self, service_name, service_cls, mock_ansible_runner):
@ddt.data('mysql')
def test_unplug(self, service_name, mock_ansible_runner):
ansible_runner_inst = mock_ansible_runner.return_value
ansible_runner_inst.execute.side_effect = [
[self.fake_ansible_result],
@ -191,27 +178,24 @@ class FuelServiceTestCase(test.TestCase):
fuel_managment = fuel.FuelManagement(self.conf)
service = fuel_managment.get_service(service_name)
self.assertIsInstance(service, service_cls)
service.unplug()
get_nodes_cmd = 'bash -c "ps ax | grep -v grep | grep \'{}\'"'.format(
service_cls.GREP)
service.grep)
ansible_runner_inst.execute.assert_has_calls([
mock.call(['fuel.local'], {'command': 'fuel node --json'}),
mock.call(['10.0.0.2', '10.0.0.3'],
{'command': get_nodes_cmd}, []),
mock.call(['10.0.0.2', '10.0.0.3'],
{'iptables': {'protocol': service_cls.PORT[0],
'port': service_cls.PORT[1],
{'iptables': {'protocol': service.port[0],
'port': service.port[1],
'action': 'block',
'service': service_cls.SERVICE_NAME}}),
'service': service.service_name}}),
])
@mock.patch('os_faults.ansible.executor.AnsibleRunner', autospec=True)
@ddt.data(('mysql', fuel.MySQLService))
@ddt.unpack
def test_plug(self, service_name, service_cls, mock_ansible_runner):
@ddt.data('mysql')
def test_plug(self, service_name, mock_ansible_runner):
ansible_runner_inst = mock_ansible_runner.return_value
ansible_runner_inst.execute.side_effect = [
[self.fake_ansible_result],
@ -228,27 +212,24 @@ class FuelServiceTestCase(test.TestCase):
fuel_managment = fuel.FuelManagement(self.conf)
service = fuel_managment.get_service(service_name)
self.assertIsInstance(service, service_cls)
service.plug()
get_nodes_cmd = 'bash -c "ps ax | grep -v grep | grep \'{}\'"'.format(
service_cls.GREP)
service.grep)
ansible_runner_inst.execute.assert_has_calls([
mock.call(['fuel.local'], {'command': 'fuel node --json'}),
mock.call(['10.0.0.2', '10.0.0.3'],
{'command': get_nodes_cmd}, []),
mock.call(['10.0.0.2', '10.0.0.3'],
{'iptables': {'protocol': service_cls.PORT[0],
'port': service_cls.PORT[1],
{'iptables': {'protocol': service.port[0],
'port': service.port[1],
'action': 'unblock',
'service': service_cls.SERVICE_NAME}}),
'service': service.service_name}}),
])
@mock.patch('os_faults.ansible.executor.AnsibleRunner', autospec=True)
@ddt.data(*fuel.FuelManagement.SERVICE_NAME_TO_CLASS.items())
@ddt.unpack
def test_restart(self, service_name, service_cls, mock_ansible_runner):
@ddt.data(*fuel.FuelManagement.SERVICES.keys())
def test_restart(self, service_name, mock_ansible_runner):
ansible_runner_inst = mock_ansible_runner.return_value
ansible_runner_inst.execute.side_effect = [
[self.fake_ansible_result],
@ -265,24 +246,21 @@ class FuelServiceTestCase(test.TestCase):
fuel_managment = fuel.FuelManagement(self.conf)
service = fuel_managment.get_service(service_name)
self.assertIsInstance(service, service_cls)
service.restart()
get_nodes_cmd = 'bash -c "ps ax | grep -v grep | grep \'{}\'"'.format(
service_cls.GREP)
service.grep)
ansible_runner_inst.execute.assert_has_calls([
mock.call(['fuel.local'], {'command': 'fuel node --json'}),
mock.call(['10.0.0.2', '10.0.0.3'],
{'command': get_nodes_cmd}, []),
mock.call(['10.0.0.2', '10.0.0.3'],
{'shell': service.RESTART_CMD}),
{'shell': service.restart_cmd}),
])
@mock.patch('os_faults.ansible.executor.AnsibleRunner', autospec=True)
@ddt.data(*fuel.FuelManagement.SERVICE_NAME_TO_CLASS.items())
@ddt.unpack
def test_terminate(self, service_name, service_cls, mock_ansible_runner):
@ddt.data(*fuel.FuelManagement.SERVICES.keys())
def test_terminate(self, service_name, mock_ansible_runner):
ansible_runner_inst = mock_ansible_runner.return_value
ansible_runner_inst.execute.side_effect = [
[self.fake_ansible_result],
@ -299,24 +277,21 @@ class FuelServiceTestCase(test.TestCase):
fuel_managment = fuel.FuelManagement(self.conf)
service = fuel_managment.get_service(service_name)
self.assertIsInstance(service, service_cls)
service.terminate()
get_nodes_cmd = 'bash -c "ps ax | grep -v grep | grep \'{}\'"'.format(
service_cls.GREP)
service.grep)
ansible_runner_inst.execute.assert_has_calls([
mock.call(['fuel.local'], {'command': 'fuel node --json'}),
mock.call(['10.0.0.2', '10.0.0.3'],
{'command': get_nodes_cmd}, []),
mock.call(['10.0.0.2', '10.0.0.3'],
{'shell': service.TERMINATE_CMD}),
{'shell': service.terminate_cmd}),
])
@mock.patch('os_faults.ansible.executor.AnsibleRunner', autospec=True)
@ddt.data(*fuel.FuelManagement.SERVICE_NAME_TO_CLASS.items())
@ddt.unpack
def test_start(self, service_name, service_cls, mock_ansible_runner):
@ddt.data(*fuel.FuelManagement.SERVICES.keys())
def test_start(self, service_name, mock_ansible_runner):
ansible_runner_inst = mock_ansible_runner.return_value
ansible_runner_inst.execute.side_effect = [
[self.fake_ansible_result],
@ -333,18 +308,16 @@ class FuelServiceTestCase(test.TestCase):
fuel_managment = fuel.FuelManagement(self.conf)
service = fuel_managment.get_service(service_name)
self.assertIsInstance(service, service_cls)
service.start()
get_nodes_cmd = 'bash -c "ps ax | grep -v grep | grep \'{}\'"'.format(
service_cls.GREP)
service.grep)
ansible_runner_inst.execute.assert_has_calls([
mock.call(['fuel.local'], {'command': 'fuel node --json'}),
mock.call(['10.0.0.2', '10.0.0.3'],
{'command': get_nodes_cmd}, []),
mock.call(['10.0.0.2', '10.0.0.3'],
{'shell': service.START_CMD}),
{'shell': service.start_cmd}),
])
@mock.patch('os_faults.ansible.executor.AnsibleRunner', autospec=True)
@ -370,13 +343,13 @@ class FuelServiceTestCase(test.TestCase):
self.assertEqual('Task failed on some nodes', str(exception))
get_nodes_cmd = 'bash -c "ps ax | grep -v grep | grep \'{}\'"'.format(
service.GREP)
service.grep)
ansible_runner_inst.execute.assert_has_calls([
mock.call(['fuel.local'], {'command': 'fuel node --json'}),
mock.call(['10.0.0.2', '10.0.0.3'],
{'command': get_nodes_cmd}, []),
mock.call(['10.0.0.2', '10.0.0.3'],
{'shell': service.RESTART_CMD}),
{'shell': service.restart_cmd}),
])
@mock.patch('os_faults.ansible.executor.AnsibleRunner', autospec=True)
@ -399,7 +372,7 @@ class FuelServiceTestCase(test.TestCase):
self.assertEqual('Node collection is empty', str(exception))
get_nodes_cmd = 'bash -c "ps ax | grep -v grep | grep \'{}\'"'.format(
service.GREP)
service.grep)
ansible_runner_inst.execute.assert_has_calls([
mock.call(['fuel.local'], {'command': 'fuel node --json'}),
mock.call(['10.0.0.2', '10.0.0.3'],

View File

@ -230,10 +230,8 @@ class TCPCloudManagementTestCase(test.TestCase):
self.assertEqual(nodes.hosts, hosts)
@mock.patch('os_faults.ansible.executor.AnsibleRunner', autospec=True)
@ddt.data(*tcpcloud.TCPCloudManagement.SERVICE_NAME_TO_CLASS.items())
@ddt.unpack
def test_get_service_nodes(self, service_name, service_cls,
mock_ansible_runner):
@ddt.data(*tcpcloud.TCPCloudManagement.SERVICES.keys())
def test_get_service_nodes(self, service_name, mock_ansible_runner):
ansible_runner_inst = mock_ansible_runner.return_value
ansible_runner_inst.execute.side_effect = [
[self.fake_ansible_result],
@ -248,11 +246,9 @@ class TCPCloudManagementTestCase(test.TestCase):
tcp_managment = tcpcloud.TCPCloudManagement(self.tcp_conf)
service = tcp_managment.get_service(service_name)
self.assertIsInstance(service, service_cls)
nodes = service.get_nodes()
cmd = 'bash -c "ps ax | grep -v grep | grep \'{}\'"'.format(
service_cls.GREP)
service.grep)
ansible_runner_inst.execute.assert_has_calls([
mock.call(['tcp.local'], {'command': self.get_nodes_cmd}),
mock.call(['tcp.local'], {'command': self.get_ips_cmd}),
@ -303,9 +299,8 @@ class TcpServiceTestCase(test.TestCase):
"pillar.get _param:single_address --out=yaml")
@mock.patch('os_faults.ansible.executor.AnsibleRunner', autospec=True)
@ddt.data(*tcpcloud.TCPCloudManagement.SERVICE_NAME_TO_CLASS.items())
@ddt.unpack
def test_restart(self, service_name, service_cls, mock_ansible_runner):
@ddt.data(*tcpcloud.TCPCloudManagement.SERVICES.keys())
def test_restart(self, service_name, mock_ansible_runner):
ansible_runner_inst = mock_ansible_runner.return_value
ansible_runner_inst.execute.side_effect = [
[self.fake_ansible_result],
@ -324,24 +319,21 @@ class TcpServiceTestCase(test.TestCase):
tcp_managment = tcpcloud.TCPCloudManagement(self.tcp_conf)
service = tcp_managment.get_service(service_name)
self.assertIsInstance(service, service_cls)
service.restart()
cmd = 'bash -c "ps ax | grep -v grep | grep \'{}\'"'.format(
service_cls.GREP)
service.grep)
ansible_runner_inst.execute.assert_has_calls([
mock.call(['tcp.local'], {'command': self.get_nodes_cmd}),
mock.call(['tcp.local'], {'command': self.get_ips_cmd}),
mock.call(['10.0.0.2', '10.0.0.3'],
{'command': cmd}, []),
mock.call(['10.0.0.3'], {'shell': service.RESTART_CMD}),
mock.call(['10.0.0.3'], {'shell': service.restart_cmd}),
])
@mock.patch('os_faults.ansible.executor.AnsibleRunner', autospec=True)
@ddt.data(*tcpcloud.TCPCloudManagement.SERVICE_NAME_TO_CLASS.items())
@ddt.unpack
def test_terminate(self, service_name, service_cls, mock_ansible_runner):
@ddt.data(*tcpcloud.TCPCloudManagement.SERVICES.keys())
def test_terminate(self, service_name, mock_ansible_runner):
ansible_runner_inst = mock_ansible_runner.return_value
ansible_runner_inst.execute.side_effect = [
[self.fake_ansible_result],
@ -360,24 +352,21 @@ class TcpServiceTestCase(test.TestCase):
tcp_managment = tcpcloud.TCPCloudManagement(self.tcp_conf)
service = tcp_managment.get_service(service_name)
self.assertIsInstance(service, service_cls)
service.terminate()
cmd = 'bash -c "ps ax | grep -v grep | grep \'{}\'"'.format(
service_cls.GREP)
service.grep)
ansible_runner_inst.execute.assert_has_calls([
mock.call(['tcp.local'], {'command': self.get_nodes_cmd}),
mock.call(['tcp.local'], {'command': self.get_ips_cmd}),
mock.call(['10.0.0.2', '10.0.0.3'],
{'command': cmd}, []),
mock.call(['10.0.0.3'], {'shell': service.TERMINATE_CMD}),
mock.call(['10.0.0.3'], {'shell': service.terminate_cmd}),
])
@mock.patch('os_faults.ansible.executor.AnsibleRunner', autospec=True)
@ddt.data(*tcpcloud.TCPCloudManagement.SERVICE_NAME_TO_CLASS.items())
@ddt.unpack
def test_start(self, service_name, service_cls, mock_ansible_runner):
@ddt.data(*tcpcloud.TCPCloudManagement.SERVICES.keys())
def test_start(self, service_name, mock_ansible_runner):
ansible_runner_inst = mock_ansible_runner.return_value
ansible_runner_inst.execute.side_effect = [
[self.fake_ansible_result],
@ -396,16 +385,14 @@ class TcpServiceTestCase(test.TestCase):
tcp_managment = tcpcloud.TCPCloudManagement(self.tcp_conf)
service = tcp_managment.get_service(service_name)
self.assertIsInstance(service, service_cls)
service.start()
cmd = 'bash -c "ps ax | grep -v grep | grep \'{}\'"'.format(
service_cls.GREP)
service.grep)
ansible_runner_inst.execute.assert_has_calls([
mock.call(['tcp.local'], {'command': self.get_nodes_cmd}),
mock.call(['tcp.local'], {'command': self.get_ips_cmd}),
mock.call(['10.0.0.2', '10.0.0.3'],
{'command': cmd}, []),
mock.call(['10.0.0.3'], {'shell': service.START_CMD}),
mock.call(['10.0.0.3'], {'shell': service.start_cmd}),
])

View File

@ -16,6 +16,7 @@ import sys
import mock
from os_faults.api import base_driver
from os_faults.api import error
from os_faults import drivers
from os_faults import registry
from os_faults.tests.unit import test
@ -39,7 +40,19 @@ class RegistryTestCase(test.TestCase):
@mock.patch('os.walk')
def test_get_drivers(self, mock_os_walk, mock_import_module):
drivers_folder = os.path.dirname(drivers.__file__)
mock_os_walk.return_value = [(drivers_folder, [], ['test_driver.py'])]
mock_os_walk.return_value = [(drivers_folder, [], ['driver.py'])]
mock_import_module.return_value = sys.modules[__name__]
self.assertEqual({'test': TestDriver}, registry.get_drivers())
@mock.patch('os_faults.registry._list_drivers')
def test_name_collision(self, mock_list_drivers):
class TestDriver1(base_driver.BaseDriver):
NAME = 'test'
class TestDriver2(base_driver.BaseDriver):
NAME = 'test'
mock_list_drivers.return_value = [TestDriver1, TestDriver2]
self.assertRaises(error.OSFDriverWithSuchNameExists,
registry.get_drivers)

View File

@ -61,6 +61,9 @@ class UtilsTestCase(test.TestCase):
class MyClass(object):
FOO = 10
def __init__(self):
self.BAR = None
@utils.require_variables('FOO')
def method(self, a, b):
return self.FOO + a + b

View File

@ -51,7 +51,7 @@ def require_variables(*variables):
def wrapper(self, *args, **kawrgs):
missing_vars = []
for var in variables:
if not hasattr(self, var):
if not getattr(self, var, None):
missing_vars.append(var)
if missing_vars:
missing_vars = ', '.join(missing_vars)