add a new service list api
Story: 2004897 Task: 29204 Task: 29207 Depends-On: I2996afcd4f05c87847db1f9be64a362a2593f5b6 Change-Id: I494e5749adc1d3845f793a941f970a944457d992
This commit is contained in:
parent
f87cdcd111
commit
12f70b9ada
@ -216,6 +216,12 @@ function configure_vitrage {
|
|||||||
else
|
else
|
||||||
write_uwsgi_config "$VITRAGE_UWSGI_FILE" "$VITRAGE_PUBLIC_UWSGI" "/rca"
|
write_uwsgi_config "$VITRAGE_UWSGI_FILE" "$VITRAGE_PUBLIC_UWSGI" "/rca"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [[ ! -z "$VITRAGE_COORDINATION_URL" ]]; then
|
||||||
|
iniset $VITRAGE_CONF coordination backend_url "$VITRAGE_COORDINATION_URL"
|
||||||
|
elif is_service_enabled etcd3; then
|
||||||
|
iniset $VITRAGE_CONF coordination backend_url "etcd3://${SERVICE_HOST}:$ETCD_PORT"
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# init_vitrage() - Initialize etc.
|
# init_vitrage() - Initialize etc.
|
||||||
|
@ -1783,7 +1783,7 @@ Request Examples
|
|||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
DELETE /v1/resources/`<id>`
|
DELETE /v1/webhook/`<id>`
|
||||||
Host: 127.0.0.1:8999
|
Host: 127.0.0.1:8999
|
||||||
User-Agent: keystoneauth1/2.3.0 python-requests/2.9.1 CPython/2.7.6
|
User-Agent: keystoneauth1/2.3.0 python-requests/2.9.1 CPython/2.7.6
|
||||||
Accept: application/json
|
Accept: application/json
|
||||||
@ -1800,3 +1800,132 @@ Response Body
|
|||||||
|
|
||||||
Returns a success message if the webhook is deleted, otherwise an error
|
Returns a success message if the webhook is deleted, otherwise an error
|
||||||
message is returned.
|
message is returned.
|
||||||
|
|
||||||
|
|
||||||
|
Service list
|
||||||
|
^^^^^^^^^^^^
|
||||||
|
|
||||||
|
Lists the vitrage services present in the system
|
||||||
|
|
||||||
|
GET /v1/services/
|
||||||
|
~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Headers
|
||||||
|
=======
|
||||||
|
|
||||||
|
- X-Auth-Token (string, required) - Keystone auth token
|
||||||
|
- Accept (string) - application/json
|
||||||
|
|
||||||
|
Path Parameters
|
||||||
|
===============
|
||||||
|
|
||||||
|
None.
|
||||||
|
|
||||||
|
Query Parameters
|
||||||
|
================
|
||||||
|
|
||||||
|
None.
|
||||||
|
|
||||||
|
Request Body
|
||||||
|
============
|
||||||
|
|
||||||
|
None.
|
||||||
|
|
||||||
|
Request Examples
|
||||||
|
================
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
GET //v1/services/ HTTP/1.1
|
||||||
|
Host: 135.248.19.18:8999
|
||||||
|
X-Auth-Token: 2b8882ba2ec44295bf300aecb2caa4f7
|
||||||
|
Accept: application/json
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
ResponseStatus code
|
||||||
|
===================
|
||||||
|
|
||||||
|
- 200 - OK
|
||||||
|
- 404 - Not Found
|
||||||
|
- 500 - Service API not supported
|
||||||
|
- 500 - Failed to connect to coordination backend
|
||||||
|
|
||||||
|
Response Body
|
||||||
|
=============
|
||||||
|
|
||||||
|
Returns a JSON object with a list of all services.
|
||||||
|
|
||||||
|
Response Examples
|
||||||
|
=================
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"Created At": "2019-02-10T11:07:15+00:00",
|
||||||
|
"Hostname": "controller-1",
|
||||||
|
"Process Id": 23161,
|
||||||
|
"Name": "ApiWorker worker(0)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Created At": "2019-02-10T11:07:15+00:00",
|
||||||
|
"Hostname": "controller-1",
|
||||||
|
"Process Id": 23153,
|
||||||
|
"Name": "EvaluatorWorker worker(0)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Created At": "2019-02-10T11:07:15+00:00",
|
||||||
|
"Hostname": "controller-1",
|
||||||
|
"Process Id": 23155,
|
||||||
|
"Name": "EvaluatorWorker worker(1)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Created At": "2019-02-10T11:07:15+00:00",
|
||||||
|
"Hostname": "controller-1",
|
||||||
|
"Process Id": 23157,
|
||||||
|
"Name": "EvaluatorWorker worker(2)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Created At": "2019-02-10T11:07:15+00:00",
|
||||||
|
"Hostname": "controller-1",
|
||||||
|
"Process Id": 23158,
|
||||||
|
"Name": "EvaluatorWorker worker(3)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Created At": "2019-02-10T11:07:33+00:00",
|
||||||
|
"Hostname": "controller-1",
|
||||||
|
"Process Id": 23366,
|
||||||
|
"Name": "MachineLearningService worker(0)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Created At": "2019-02-10T11:07:35+00:00",
|
||||||
|
"Hostname": "controller-1",
|
||||||
|
"Process Id": 23475,
|
||||||
|
"Name": "PersistorService worker(0)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Created At": "2019-02-10T11:07:15+00:00",
|
||||||
|
"Hostname": "controller-1",
|
||||||
|
"Process Id": 23164,
|
||||||
|
"Name": "SnmpParsingService worker(0)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Created At": "2019-02-10T11:14:30+00:00",
|
||||||
|
"Hostname": "controller-1",
|
||||||
|
"Process Id": 25698,
|
||||||
|
"Name": "VitrageApi"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Created At": "2019-02-10T11:14:30+00:00",
|
||||||
|
"Hostname": "controller-1",
|
||||||
|
"Process Id": 25699,
|
||||||
|
"Name": "VitrageApi"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Created At": "2019-02-10T11:07:32+00:00",
|
||||||
|
"Hostname": "controller-1",
|
||||||
|
"Process Id": 23352,
|
||||||
|
"Name": "VitrageNotifierService worker(0)"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
@ -142,3 +142,6 @@ wrapt==1.10.11
|
|||||||
futures==3.0.0
|
futures==3.0.0
|
||||||
docutils==0.11
|
docutils==0.11
|
||||||
python-zaqarclient==1.2.0
|
python-zaqarclient==1.2.0
|
||||||
|
tooz==1.58.0
|
||||||
|
zake==0.1.6
|
||||||
|
psutil==5.4.3
|
||||||
|
@ -1,6 +0,0 @@
|
|||||||
[DEFAULT]
|
|
||||||
|
|
||||||
# The list of modules to copy from oslo-incubator.git
|
|
||||||
|
|
||||||
# The base module to hold the copy of openstack.common
|
|
||||||
base=vitrage
|
|
@ -0,0 +1,3 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- Added a new API to list all vitrage services present in the system.
|
@ -52,3 +52,5 @@ cotyledon>=1.6.8 # Apache-2.0
|
|||||||
futures>=3.0.0;python_version=='2.7' or python_version=='2.6' # BSD
|
futures>=3.0.0;python_version=='2.7' or python_version=='2.6' # BSD
|
||||||
pytz>=2013.6 # MIT
|
pytz>=2013.6 # MIT
|
||||||
tenacity>=4.9.0
|
tenacity>=4.9.0
|
||||||
|
tooz>=1.58.0 # Apache-2.0
|
||||||
|
psutil>=5.4.3 # BSD
|
@ -12,3 +12,4 @@ testtools>=2.3.0 # MIT
|
|||||||
stestr>=2.0.0 # Apache-2.0
|
stestr>=2.0.0 # Apache-2.0
|
||||||
reno>=2.7.0 # Apache-2.0
|
reno>=2.7.0 # Apache-2.0
|
||||||
mock>=2.0.0 # BSD
|
mock>=2.0.0 # BSD
|
||||||
|
zake>=0.1.6 # Apache-2.0
|
||||||
|
@ -41,7 +41,8 @@ def setup_app(root, conf=None):
|
|||||||
hooks.GCHook(),
|
hooks.GCHook(),
|
||||||
hooks.RPCHook(conf),
|
hooks.RPCHook(conf),
|
||||||
hooks.ContextHook(),
|
hooks.ContextHook(),
|
||||||
hooks.DBHook(conf)]
|
hooks.DBHook(conf),
|
||||||
|
hooks.CoordinatorHook(conf)]
|
||||||
|
|
||||||
app = pecan.make_app(
|
app = pecan.make_app(
|
||||||
root,
|
root,
|
||||||
|
@ -15,6 +15,7 @@ from vitrage.api.controllers.v1 import alarm
|
|||||||
from vitrage.api.controllers.v1 import event
|
from vitrage.api.controllers.v1 import event
|
||||||
from vitrage.api.controllers.v1 import rca
|
from vitrage.api.controllers.v1 import rca
|
||||||
from vitrage.api.controllers.v1 import resource
|
from vitrage.api.controllers.v1 import resource
|
||||||
|
from vitrage.api.controllers.v1 import service
|
||||||
from vitrage.api.controllers.v1 import template
|
from vitrage.api.controllers.v1 import template
|
||||||
from vitrage.api.controllers.v1 import topology
|
from vitrage.api.controllers.v1 import topology
|
||||||
from vitrage.api.controllers.v1 import webhook
|
from vitrage.api.controllers.v1 import webhook
|
||||||
@ -31,3 +32,4 @@ class V1Controller(object):
|
|||||||
webhook = webhook.WebhookController()
|
webhook = webhook.WebhookController()
|
||||||
template = template.TemplateController()
|
template = template.TemplateController()
|
||||||
event = event.EventController()
|
event = event.EventController()
|
||||||
|
service = service.ServiceController()
|
||||||
|
49
vitrage/api/controllers/v1/service.py
Normal file
49
vitrage/api/controllers/v1/service.py
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
# Copyright 2019 - Nokia Corporation
|
||||||
|
#
|
||||||
|
# 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 operator import itemgetter
|
||||||
|
|
||||||
|
from oslo_log import log
|
||||||
|
import pecan
|
||||||
|
|
||||||
|
from pecan.core import abort
|
||||||
|
from vitrage.api.policy import enforce
|
||||||
|
|
||||||
|
LOG = log.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
# noinspection PyBroadException
|
||||||
|
class ServiceController(object):
|
||||||
|
@pecan.expose('json')
|
||||||
|
def index(self):
|
||||||
|
return self.get()
|
||||||
|
|
||||||
|
@pecan.expose('json')
|
||||||
|
def get(self):
|
||||||
|
enforce("get service list", pecan.request.headers,
|
||||||
|
pecan.request.enforcer, {})
|
||||||
|
|
||||||
|
LOG.info('received get service list')
|
||||||
|
|
||||||
|
coordinator = pecan.request.coordinator
|
||||||
|
if not coordinator.backend_url:
|
||||||
|
abort(500, 'Service API not supported')
|
||||||
|
if not coordinator.is_active():
|
||||||
|
abort(500, 'Failed to connect to coordination backend')
|
||||||
|
|
||||||
|
try:
|
||||||
|
return sorted(coordinator.get_services(), key=itemgetter('name'))
|
||||||
|
except Exception:
|
||||||
|
LOG.exception('failed to get service list.')
|
||||||
|
abort(404, 'Failed to get service list.')
|
@ -17,6 +17,7 @@ from oslo_policy import policy
|
|||||||
from pecan import hooks
|
from pecan import hooks
|
||||||
|
|
||||||
from vitrage.common import policies
|
from vitrage.common import policies
|
||||||
|
from vitrage.coordination import coordination
|
||||||
from vitrage import messaging
|
from vitrage import messaging
|
||||||
from vitrage import rpc as vitrage_rpc
|
from vitrage import rpc as vitrage_rpc
|
||||||
from vitrage import storage
|
from vitrage import storage
|
||||||
@ -95,3 +96,14 @@ class GCHook(hooks.PecanHook):
|
|||||||
|
|
||||||
def after(self, state):
|
def after(self, state):
|
||||||
gc.collect()
|
gc.collect()
|
||||||
|
|
||||||
|
|
||||||
|
class CoordinatorHook(hooks.PecanHook):
|
||||||
|
|
||||||
|
def __init__(self, conf):
|
||||||
|
self.coordinator = coordination.Coordinator(conf)
|
||||||
|
self.coordinator.start()
|
||||||
|
self.coordinator.join_group()
|
||||||
|
|
||||||
|
def before(self, state):
|
||||||
|
state.request.coordinator = self.coordinator
|
||||||
|
@ -16,6 +16,7 @@ from vitrage.common.policies import alarms
|
|||||||
from vitrage.common.policies import event
|
from vitrage.common.policies import event
|
||||||
from vitrage.common.policies import rca
|
from vitrage.common.policies import rca
|
||||||
from vitrage.common.policies import resource
|
from vitrage.common.policies import resource
|
||||||
|
from vitrage.common.policies import service
|
||||||
from vitrage.common.policies import template
|
from vitrage.common.policies import template
|
||||||
from vitrage.common.policies import topology
|
from vitrage.common.policies import topology
|
||||||
from vitrage.common.policies import webhook
|
from vitrage.common.policies import webhook
|
||||||
@ -29,5 +30,6 @@ def list_rules():
|
|||||||
template.list_rules(),
|
template.list_rules(),
|
||||||
topology.list_rules(),
|
topology.list_rules(),
|
||||||
resource.list_rules(),
|
resource.list_rules(),
|
||||||
webhook.list_rules()
|
webhook.list_rules(),
|
||||||
|
service.list_rules(),
|
||||||
)
|
)
|
||||||
|
37
vitrage/common/policies/service.py
Normal file
37
vitrage/common/policies/service.py
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
# Copyright 2019 - Nokia Corporation
|
||||||
|
#
|
||||||
|
# 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_policy import policy
|
||||||
|
|
||||||
|
from vitrage.common.policies import base
|
||||||
|
|
||||||
|
SERVICE = 'get service list'
|
||||||
|
|
||||||
|
rules = [
|
||||||
|
policy.DocumentedRuleDefault(
|
||||||
|
name=SERVICE,
|
||||||
|
check_str=base.UNPROTECTED,
|
||||||
|
description='Get the vitrage services for the OpenStack cluster',
|
||||||
|
operations=[
|
||||||
|
{
|
||||||
|
'path': '/service',
|
||||||
|
'method': 'GET'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def list_rules():
|
||||||
|
return rules
|
21
vitrage/coordination/__init__.py
Normal file
21
vitrage/coordination/__init__.py
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
# Copyright 2019 - Nokia Corporation
|
||||||
|
#
|
||||||
|
# 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_config import cfg
|
||||||
|
|
||||||
|
OPTS = [
|
||||||
|
cfg.StrOpt('backend_url',
|
||||||
|
help='The backend URL to use for the coordination service. If '
|
||||||
|
'left empty, membership api will not work')
|
||||||
|
]
|
113
vitrage/coordination/coordination.py
Normal file
113
vitrage/coordination/coordination.py
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
# Copyright 2019 - Nokia Corporation
|
||||||
|
#
|
||||||
|
# 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 json
|
||||||
|
import os
|
||||||
|
import psutil
|
||||||
|
import socket
|
||||||
|
|
||||||
|
import six
|
||||||
|
import tenacity
|
||||||
|
import tooz.coordination
|
||||||
|
|
||||||
|
from oslo_log import log
|
||||||
|
from oslo_utils import timeutils
|
||||||
|
|
||||||
|
LOG = log.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class Coordinator(object):
|
||||||
|
def __init__(self, conf, my_id=None):
|
||||||
|
self.conf = conf
|
||||||
|
self.backend_url = self.conf.coordination.backend_url
|
||||||
|
self.my_id = my_id or ' '.join(psutil.Process(os.getpid()).cmdline())
|
||||||
|
self.coordinator = None
|
||||||
|
if self.backend_url:
|
||||||
|
self.coordinator = tooz.coordination.get_coordinator(
|
||||||
|
self.backend_url, six.b('%s_%s' % (my_id, os.getpid())))
|
||||||
|
|
||||||
|
def start(self):
|
||||||
|
if self.backend_url:
|
||||||
|
try:
|
||||||
|
self.coordinator.start(start_heart=True)
|
||||||
|
LOG.info('Coordination backend started successfully.')
|
||||||
|
except tooz.coordination.ToozError:
|
||||||
|
LOG.exception('Error connecting to coordination backend.')
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
if not self.is_active():
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
self.coordinator.stop()
|
||||||
|
except tooz.coordination.ToozError:
|
||||||
|
LOG.exception('Error connecting to coordination backend.')
|
||||||
|
|
||||||
|
def is_active(self):
|
||||||
|
return self.coordinator and self.coordinator.is_started
|
||||||
|
|
||||||
|
@tenacity.retry(stop=tenacity.stop_after_attempt(5))
|
||||||
|
def join_group(self, group_id='vitrage'):
|
||||||
|
if not self.is_active() or not group_id:
|
||||||
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
|
now = timeutils.utcnow(with_timezone=True).replace(microsecond=0)
|
||||||
|
isoformat = now.isoformat()
|
||||||
|
|
||||||
|
capabilities = json.dumps(
|
||||||
|
{
|
||||||
|
'name': self.my_id,
|
||||||
|
'hostname': socket.gethostname(),
|
||||||
|
'process': os.getpid(),
|
||||||
|
'created': isoformat
|
||||||
|
}
|
||||||
|
)
|
||||||
|
join_req = self.coordinator.join_group(six.b(group_id),
|
||||||
|
six.b(capabilities))
|
||||||
|
join_req.get()
|
||||||
|
|
||||||
|
LOG.info('Joined service group:%s, member:%s',
|
||||||
|
group_id, self.my_id)
|
||||||
|
|
||||||
|
return
|
||||||
|
except tooz.coordination.MemberAlreadyExist:
|
||||||
|
return
|
||||||
|
except tooz.coordination.GroupNotCreated as e:
|
||||||
|
create_grp_req = self.coordinator.create_group(six.b(group_id))
|
||||||
|
|
||||||
|
try:
|
||||||
|
create_grp_req.get()
|
||||||
|
except tooz.coordination.GroupAlreadyExist:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Re-raise exception to join group again.
|
||||||
|
raise e
|
||||||
|
|
||||||
|
def leave_group(self, group_id):
|
||||||
|
if self.is_active():
|
||||||
|
self.coordinator.leave_group(six.b(group_id))
|
||||||
|
LOG.info('Left group %s', group_id)
|
||||||
|
|
||||||
|
def get_services(self, group_id='vitrage'):
|
||||||
|
if not self.is_active():
|
||||||
|
return []
|
||||||
|
|
||||||
|
while True:
|
||||||
|
get_members_req = self.coordinator.get_members(six.b(group_id))
|
||||||
|
try:
|
||||||
|
return [json.loads(
|
||||||
|
self.coordinator.get_member_capabilities(
|
||||||
|
six.b(group_id), member).get().decode('us-ascii'))
|
||||||
|
for member in get_members_req.get()]
|
||||||
|
except tooz.coordination.GroupNotCreated:
|
||||||
|
self.join_group(group_id)
|
32
vitrage/coordination/service.py
Normal file
32
vitrage/coordination/service.py
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
# Copyright 2019 - Nokia Corporation
|
||||||
|
#
|
||||||
|
# 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 cotyledon
|
||||||
|
|
||||||
|
from vitrage.coordination.coordination import Coordinator
|
||||||
|
|
||||||
|
|
||||||
|
class Service(cotyledon.Service):
|
||||||
|
|
||||||
|
def __init__(self, worker_id, conf):
|
||||||
|
super(Service, self).__init__(worker_id)
|
||||||
|
self.coordinator = Coordinator(conf, '%s worker(%s)' % (self.name,
|
||||||
|
worker_id))
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
self.coordinator.start()
|
||||||
|
self.coordinator.join_group()
|
||||||
|
|
||||||
|
def terminate(self):
|
||||||
|
self.coordinator.stop()
|
@ -36,6 +36,7 @@ from vitrage.api_handler.apis.webhook import WebhookApis
|
|||||||
from vitrage.common.constants import TemplateStatus as TStatus
|
from vitrage.common.constants import TemplateStatus as TStatus
|
||||||
from vitrage.common.constants import TemplateTypes as TType
|
from vitrage.common.constants import TemplateTypes as TType
|
||||||
from vitrage.common.exception import VitrageError
|
from vitrage.common.exception import VitrageError
|
||||||
|
from vitrage.coordination import service as coord
|
||||||
from vitrage.entity_graph import EVALUATOR_TOPIC
|
from vitrage.entity_graph import EVALUATOR_TOPIC
|
||||||
from vitrage.evaluator.actions.base import ActionMode
|
from vitrage.evaluator.actions.base import ActionMode
|
||||||
from vitrage.evaluator.scenario_evaluator import ScenarioEvaluator
|
from vitrage.evaluator.scenario_evaluator import ScenarioEvaluator
|
||||||
@ -214,12 +215,12 @@ class GraphWorkersManager(cotyledon.ServiceManager):
|
|||||||
os._exit(0)
|
os._exit(0)
|
||||||
|
|
||||||
|
|
||||||
class GraphCloneWorkerBase(cotyledon.Service):
|
class GraphCloneWorkerBase(coord.Service):
|
||||||
def __init__(self,
|
def __init__(self,
|
||||||
worker_id,
|
worker_id,
|
||||||
conf,
|
conf,
|
||||||
task_queues):
|
task_queues):
|
||||||
super(GraphCloneWorkerBase, self).__init__(worker_id)
|
super(GraphCloneWorkerBase, self).__init__(worker_id, conf)
|
||||||
self._conf = conf
|
self._conf = conf
|
||||||
self._task_queue = task_queues[worker_id]
|
self._task_queue = task_queues[worker_id]
|
||||||
self._entity_graph = NXGraph()
|
self._entity_graph = NXGraph()
|
||||||
@ -232,6 +233,7 @@ class GraphCloneWorkerBase(cotyledon.Service):
|
|||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
|
super(GraphCloneWorkerBase, self).run()
|
||||||
self._entity_graph.notifier._subscriptions = [] # Quick n dirty
|
self._entity_graph.notifier._subscriptions = [] # Quick n dirty
|
||||||
self._init_instance()
|
self._init_instance()
|
||||||
if self._entity_graph.num_vertices():
|
if self._entity_graph.num_vertices():
|
||||||
|
@ -12,22 +12,22 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
import cotyledon
|
|
||||||
|
|
||||||
from oslo_log import log
|
from oslo_log import log
|
||||||
import oslo_messaging as oslo_m
|
import oslo_messaging as oslo_m
|
||||||
from oslo_utils import importutils
|
from oslo_utils import importutils
|
||||||
|
|
||||||
|
from vitrage.coordination import service as coord
|
||||||
from vitrage import messaging
|
from vitrage import messaging
|
||||||
from vitrage.opts import register_opts
|
from vitrage.opts import register_opts
|
||||||
|
|
||||||
LOG = log.getLogger(__name__)
|
LOG = log.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class MachineLearningService(cotyledon.Service):
|
class MachineLearningService(coord.Service):
|
||||||
|
|
||||||
def __init__(self, worker_id, conf):
|
def __init__(self, worker_id, conf):
|
||||||
super(MachineLearningService, self).__init__(worker_id)
|
super(MachineLearningService, self).__init__(worker_id, conf)
|
||||||
self.conf = conf
|
self.conf = conf
|
||||||
self.machine_learning_plugins = self.get_machine_learning_plugins(conf)
|
self.machine_learning_plugins = self.get_machine_learning_plugins(conf)
|
||||||
transport = messaging.get_transport(conf)
|
transport = messaging.get_transport(conf)
|
||||||
@ -38,6 +38,7 @@ class MachineLearningService(cotyledon.Service):
|
|||||||
[VitrageEventEndpoint(self.machine_learning_plugins)])
|
[VitrageEventEndpoint(self.machine_learning_plugins)])
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
|
super(MachineLearningService, self).run()
|
||||||
LOG.info("Vitrage Machine Learning Service - Starting...")
|
LOG.info("Vitrage Machine Learning Service - Starting...")
|
||||||
|
|
||||||
self.listener.start()
|
self.listener.start()
|
||||||
@ -45,6 +46,7 @@ class MachineLearningService(cotyledon.Service):
|
|||||||
LOG.info("Vitrage Machine Learning Service - Started!")
|
LOG.info("Vitrage Machine Learning Service - Started!")
|
||||||
|
|
||||||
def terminate(self):
|
def terminate(self):
|
||||||
|
super(MachineLearningService, self).terminate()
|
||||||
LOG.info("Vitrage Machine Learning Service - Stopping...")
|
LOG.info("Vitrage Machine Learning Service - Stopping...")
|
||||||
|
|
||||||
self.listener.stop()
|
self.listener.stop()
|
||||||
|
@ -11,26 +11,28 @@
|
|||||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
import cotyledon
|
|
||||||
from oslo_log import log
|
from oslo_log import log
|
||||||
import oslo_messaging
|
import oslo_messaging
|
||||||
from oslo_utils import importutils
|
from oslo_utils import importutils
|
||||||
|
|
||||||
|
from vitrage.coordination import service as coord
|
||||||
from vitrage import messaging
|
from vitrage import messaging
|
||||||
from vitrage.opts import register_opts
|
from vitrage.opts import register_opts
|
||||||
|
|
||||||
LOG = log.getLogger(__name__)
|
LOG = log.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class VitrageNotifierService(cotyledon.Service):
|
class VitrageNotifierService(coord.Service):
|
||||||
|
|
||||||
def __init__(self, worker_id, conf):
|
def __init__(self, worker_id, conf):
|
||||||
super(VitrageNotifierService, self).__init__(worker_id)
|
super(VitrageNotifierService, self).__init__(worker_id, conf)
|
||||||
self.conf = conf
|
self.conf = conf
|
||||||
self.notifiers = self.get_notifier_plugins(conf)
|
self.notifiers = self.get_notifier_plugins(conf)
|
||||||
self._init_listeners(self.conf)
|
self._init_listeners(self.conf)
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
|
super(VitrageNotifierService, self).run()
|
||||||
|
|
||||||
LOG.info("Vitrage Notifier Service - Starting...")
|
LOG.info("Vitrage Notifier Service - Starting...")
|
||||||
|
|
||||||
for listener in self.listeners:
|
for listener in self.listeners:
|
||||||
@ -39,6 +41,7 @@ class VitrageNotifierService(cotyledon.Service):
|
|||||||
LOG.info("Vitrage Notifier Service - Started!")
|
LOG.info("Vitrage Notifier Service - Started!")
|
||||||
|
|
||||||
def terminate(self):
|
def terminate(self):
|
||||||
|
super(VitrageNotifierService, self).terminate()
|
||||||
LOG.info("Vitrage Notifier Service - Stopping...")
|
LOG.info("Vitrage Notifier Service - Stopping...")
|
||||||
|
|
||||||
for listener in self.listeners:
|
for listener in self.listeners:
|
||||||
|
@ -19,6 +19,7 @@ from oslo_log import log
|
|||||||
from oslo_utils import importutils
|
from oslo_utils import importutils
|
||||||
|
|
||||||
import vitrage.api
|
import vitrage.api
|
||||||
|
import vitrage.coordination
|
||||||
import vitrage.datasources
|
import vitrage.datasources
|
||||||
import vitrage.entity_graph.consistency
|
import vitrage.entity_graph.consistency
|
||||||
import vitrage.evaluator
|
import vitrage.evaluator
|
||||||
@ -63,6 +64,7 @@ def list_opts():
|
|||||||
('webhook', vitrage.notifier.plugins.webhook.OPTS),
|
('webhook', vitrage.notifier.plugins.webhook.OPTS),
|
||||||
('snmp_parsing', vitrage.snmp_parsing.OPTS),
|
('snmp_parsing', vitrage.snmp_parsing.OPTS),
|
||||||
('zaqar', vitrage.notifier.plugins.zaqar.OPTS),
|
('zaqar', vitrage.notifier.plugins.zaqar.OPTS),
|
||||||
|
('coordination', vitrage.coordination.OPTS),
|
||||||
('DEFAULT', itertools.chain(
|
('DEFAULT', itertools.chain(
|
||||||
vitrage.os_clients.OPTS,
|
vitrage.os_clients.OPTS,
|
||||||
vitrage.rpc.OPTS,
|
vitrage.rpc.OPTS,
|
||||||
|
@ -17,7 +17,6 @@ from __future__ import print_function
|
|||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
|
|
||||||
from concurrent.futures import ThreadPoolExecutor
|
from concurrent.futures import ThreadPoolExecutor
|
||||||
import cotyledon
|
|
||||||
import dateutil.parser
|
import dateutil.parser
|
||||||
from futurist import periodics
|
from futurist import periodics
|
||||||
|
|
||||||
@ -31,6 +30,7 @@ from vitrage.common.constants import HistoryProps as HProps
|
|||||||
from vitrage.common.constants import NotifierEventTypes as NETypes
|
from vitrage.common.constants import NotifierEventTypes as NETypes
|
||||||
from vitrage.common.constants import VertexProperties as VProps
|
from vitrage.common.constants import VertexProperties as VProps
|
||||||
from vitrage.common.utils import spawn
|
from vitrage.common.utils import spawn
|
||||||
|
from vitrage.coordination import service as coord
|
||||||
from vitrage import messaging
|
from vitrage import messaging
|
||||||
from vitrage.storage.sqlalchemy import models
|
from vitrage.storage.sqlalchemy import models
|
||||||
from vitrage.utils.datetime import utcnow
|
from vitrage.utils.datetime import utcnow
|
||||||
@ -38,9 +38,9 @@ from vitrage.utils.datetime import utcnow
|
|||||||
LOG = log.getLogger(__name__)
|
LOG = log.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class PersistorService(cotyledon.Service):
|
class PersistorService(coord.Service):
|
||||||
def __init__(self, worker_id, conf, db_connection):
|
def __init__(self, worker_id, conf, db_connection):
|
||||||
super(PersistorService, self).__init__(worker_id)
|
super(PersistorService, self).__init__(worker_id, conf)
|
||||||
self.conf = conf
|
self.conf = conf
|
||||||
self.db_connection = db_connection
|
self.db_connection = db_connection
|
||||||
transport = messaging.get_transport(conf)
|
transport = messaging.get_transport(conf)
|
||||||
@ -52,6 +52,7 @@ class PersistorService(cotyledon.Service):
|
|||||||
self.scheduler = Scheduler(conf, db_connection)
|
self.scheduler = Scheduler(conf, db_connection)
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
|
super(PersistorService, self).run()
|
||||||
LOG.info("Vitrage Persistor Service - Starting...")
|
LOG.info("Vitrage Persistor Service - Starting...")
|
||||||
|
|
||||||
self.listener.start()
|
self.listener.start()
|
||||||
@ -60,6 +61,7 @@ class PersistorService(cotyledon.Service):
|
|||||||
LOG.info("Vitrage Persistor Service - Started!")
|
LOG.info("Vitrage Persistor Service - Started!")
|
||||||
|
|
||||||
def terminate(self):
|
def terminate(self):
|
||||||
|
super(PersistorService, self).terminate()
|
||||||
LOG.info("Vitrage Persistor Service - Stopping...")
|
LOG.info("Vitrage Persistor Service - Stopping...")
|
||||||
|
|
||||||
self.listener.stop()
|
self.listener.stop()
|
||||||
|
@ -15,7 +15,6 @@
|
|||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
import json
|
import json
|
||||||
|
|
||||||
import cotyledon
|
|
||||||
from oslo_log import log
|
from oslo_log import log
|
||||||
import oslo_messaging
|
import oslo_messaging
|
||||||
from oslo_utils import uuidutils
|
from oslo_utils import uuidutils
|
||||||
@ -28,6 +27,7 @@ from pysnmp.proto.rfc1902 import Integer
|
|||||||
import sys
|
import sys
|
||||||
|
|
||||||
from vitrage.common.constants import EventProperties
|
from vitrage.common.constants import EventProperties
|
||||||
|
from vitrage.coordination import service as coord
|
||||||
from vitrage.datasources.transformer_base import extract_field_value
|
from vitrage.datasources.transformer_base import extract_field_value
|
||||||
from vitrage.messaging import get_transport
|
from vitrage.messaging import get_transport
|
||||||
from vitrage.snmp_parsing.properties import SnmpEventProperties as SEProps
|
from vitrage.snmp_parsing.properties import SnmpEventProperties as SEProps
|
||||||
@ -36,16 +36,17 @@ from vitrage.utils.file import load_yaml_file
|
|||||||
LOG = log.getLogger(__name__)
|
LOG = log.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class SnmpParsingService(cotyledon.Service):
|
class SnmpParsingService(coord.Service):
|
||||||
RUN_FOREVER = 1
|
RUN_FOREVER = 1
|
||||||
|
|
||||||
def __init__(self, worker_id, conf):
|
def __init__(self, worker_id, conf):
|
||||||
super(SnmpParsingService, self).__init__(worker_id)
|
super(SnmpParsingService, self).__init__(worker_id, conf)
|
||||||
self.conf = conf
|
self.conf = conf
|
||||||
self.listening_port = conf.snmp_parsing.snmp_listening_port
|
self.listening_port = conf.snmp_parsing.snmp_listening_port
|
||||||
self._init_oslo_notifier()
|
self._init_oslo_notifier()
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
|
super(SnmpParsingService, self).run()
|
||||||
LOG.info("Vitrage SNMP Parsing Service - Starting...")
|
LOG.info("Vitrage SNMP Parsing Service - Starting...")
|
||||||
|
|
||||||
transport_dispatcher = AsyncoreDispatcher()
|
transport_dispatcher = AsyncoreDispatcher()
|
||||||
@ -72,6 +73,7 @@ class SnmpParsingService(cotyledon.Service):
|
|||||||
raise
|
raise
|
||||||
|
|
||||||
def terminate(self):
|
def terminate(self):
|
||||||
|
super(SnmpParsingService, self).terminate()
|
||||||
LOG.info("Vitrage SNMP Parsing Service - Stopping...")
|
LOG.info("Vitrage SNMP Parsing Service - Stopping...")
|
||||||
LOG.info("Vitrage SNMP Parsing Service - Stopped!")
|
LOG.info("Vitrage SNMP Parsing Service - Stopped!")
|
||||||
|
|
||||||
|
@ -20,7 +20,8 @@ import uuid
|
|||||||
|
|
||||||
|
|
||||||
from keystonemiddleware import fixture as ksm_fixture
|
from keystonemiddleware import fixture as ksm_fixture
|
||||||
from mock import mock
|
# noinspection PyPackageRequirements
|
||||||
|
import mock
|
||||||
from vitrage.tests.functional.api.v1 import FunctionalTest
|
from vitrage.tests.functional.api.v1 import FunctionalTest
|
||||||
|
|
||||||
EVENT_DETAILS = {
|
EVENT_DETAILS = {
|
||||||
|
@ -18,7 +18,8 @@
|
|||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from mock import mock
|
# noinspection PyPackageRequirements
|
||||||
|
import mock
|
||||||
from six.moves import http_client as httplib
|
from six.moves import http_client as httplib
|
||||||
from vitrage.tests.functional.api.v1 import FunctionalTest
|
from vitrage.tests.functional.api.v1 import FunctionalTest
|
||||||
|
|
||||||
|
@ -14,9 +14,9 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
# noinspection PyPackageRequirements
|
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from mock import mock
|
# noinspection PyPackageRequirements
|
||||||
|
import mock
|
||||||
import requests_mock
|
import requests_mock
|
||||||
from vitrage.middleware.keycloak import KeycloakAuth
|
from vitrage.middleware.keycloak import KeycloakAuth
|
||||||
from vitrage.tests.functional.api.v1 import FunctionalTest
|
from vitrage.tests.functional.api.v1 import FunctionalTest
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
# noinspection PyPackageRequirements
|
# noinspection PyPackageRequirements
|
||||||
from mock import mock
|
import mock
|
||||||
from vitrage.common.utils import compress_obj
|
from vitrage.common.utils import compress_obj
|
||||||
|
|
||||||
from vitrage.storage.sqlalchemy import models
|
from vitrage.storage.sqlalchemy import models
|
||||||
|
84
vitrage/tests/functional/api/v1/test_service.py
Normal file
84
vitrage/tests/functional/api/v1/test_service.py
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
# Copyright 2019 - Nokia Corporation
|
||||||
|
#
|
||||||
|
# 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 datetime import datetime
|
||||||
|
import os
|
||||||
|
import socket
|
||||||
|
|
||||||
|
# noinspection PyPackageRequirements
|
||||||
|
from iso8601.iso8601 import UTC
|
||||||
|
# noinspection PyPackageRequirements
|
||||||
|
import mock
|
||||||
|
from oslo_utils import timeutils
|
||||||
|
# noinspection PyPackageRequirements
|
||||||
|
import webtest
|
||||||
|
|
||||||
|
from vitrage.api import app
|
||||||
|
from vitrage.coordination.coordination import Coordinator
|
||||||
|
from vitrage.tests.functional.api.v1 import FunctionalTest
|
||||||
|
|
||||||
|
|
||||||
|
class ServiceTest(FunctionalTest):
|
||||||
|
|
||||||
|
SERVICE_CREATION_TIME = datetime(2015, 1, 26, 12, 57, 4, tzinfo=UTC)
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwds):
|
||||||
|
super(ServiceTest, self).__init__(*args, **kwds)
|
||||||
|
self.auth = 'noauth'
|
||||||
|
|
||||||
|
def test_get_services_no_backend(self):
|
||||||
|
resp = self.get_json('/service/', expect_errors=True)
|
||||||
|
self.assertEqual(500, resp.status_code)
|
||||||
|
self.assertIn('Service API not supported', resp.text)
|
||||||
|
|
||||||
|
def test_get_services_no_connection_to_backend(self):
|
||||||
|
self._use_zake_as_backend()
|
||||||
|
with mock.patch('pecan.request') as request:
|
||||||
|
request.coordinator.is_active.return_value = False
|
||||||
|
resp = self.get_json('/service/', expect_errors=True)
|
||||||
|
|
||||||
|
self.assertEqual(500, resp.status_code)
|
||||||
|
self.assertIn('Failed to connect to coordination backend',
|
||||||
|
resp.text)
|
||||||
|
|
||||||
|
@mock.patch.object(timeutils, 'utcnow')
|
||||||
|
def test_get_services(self, utcnow):
|
||||||
|
now = self._mock_service_creation_time(utcnow)
|
||||||
|
|
||||||
|
# NOTE(eyalb) we want to force coordinator to be initialized with a
|
||||||
|
# custom name otherwise it will take the command line string as a name
|
||||||
|
name = 'vitrage'
|
||||||
|
with mock.patch('vitrage.coordination.coordination.Coordinator',
|
||||||
|
new=lambda _: Coordinator(self.CONF, name)):
|
||||||
|
self._use_zake_as_backend()
|
||||||
|
|
||||||
|
data = self.get_json('/service/')
|
||||||
|
|
||||||
|
self.assert_list_equal([
|
||||||
|
{
|
||||||
|
'name': name,
|
||||||
|
'hostname': socket.gethostname(),
|
||||||
|
'process': os.getpid(),
|
||||||
|
'created': now
|
||||||
|
}
|
||||||
|
], data)
|
||||||
|
|
||||||
|
def _mock_service_creation_time(self, utcnow):
|
||||||
|
utcnow.return_value = self.SERVICE_CREATION_TIME
|
||||||
|
return utcnow.return_value.isoformat()
|
||||||
|
|
||||||
|
# noinspection PyAttributeOutsideInit
|
||||||
|
def _use_zake_as_backend(self):
|
||||||
|
self.CONF.set_override('backend_url', 'zake://', 'coordination')
|
||||||
|
self.app = webtest.TestApp(app.load_app(self.CONF))
|
@ -12,8 +12,10 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
from mock import mock
|
# noinspection PyPackageRequirements
|
||||||
|
import mock
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
|
# noinspection PyPackageRequirements
|
||||||
from testtools import matchers
|
from testtools import matchers
|
||||||
|
|
||||||
from vitrage.common.constants import DatasourceOpts as DSOpts
|
from vitrage.common.constants import DatasourceOpts as DSOpts
|
||||||
@ -61,12 +63,12 @@ class PrometheusDriverTest(base.BaseTest):
|
|||||||
# Test Action
|
# Test Action
|
||||||
observed_valid_ip = driver._adjust_label_value(valid_ip)
|
observed_valid_ip = driver._adjust_label_value(valid_ip)
|
||||||
observed_not_ip = driver._adjust_label_value(not_ip)
|
observed_not_ip = driver._adjust_label_value(not_ip)
|
||||||
observed_unvalid_ip = driver._adjust_label_value(invalid_ip)
|
observed_invalid_ip = driver._adjust_label_value(invalid_ip)
|
||||||
|
|
||||||
# Test assertions
|
# Test assertions
|
||||||
self.assertEqual(hostname, observed_valid_ip)
|
self.assertEqual(hostname, observed_valid_ip)
|
||||||
self.assertEqual(not_ip, observed_not_ip)
|
self.assertEqual(not_ip, observed_not_ip)
|
||||||
self.assertEqual(invalid_ip, observed_unvalid_ip)
|
self.assertEqual(invalid_ip, observed_invalid_ip)
|
||||||
|
|
||||||
@mock.patch('socket.gethostbyaddr')
|
@mock.patch('socket.gethostbyaddr')
|
||||||
def test_calculate_host_vitrage_entity_unique_props(self, mock_socket):
|
def test_calculate_host_vitrage_entity_unique_props(self, mock_socket):
|
||||||
|
@ -124,6 +124,9 @@ class TestSnmpParsing(base.BaseTest):
|
|||||||
super(TestSnmpParsing, cls).setUpClass()
|
super(TestSnmpParsing, cls).setUpClass()
|
||||||
cls.conf = cfg.ConfigOpts()
|
cls.conf = cfg.ConfigOpts()
|
||||||
cls.conf.register_opts(cls.OPTS, group='snmp_parsing')
|
cls.conf.register_opts(cls.OPTS, group='snmp_parsing')
|
||||||
|
cls.conf.register_opt(
|
||||||
|
cfg.StrOpt('backend_url', default='zake://'), group='coordination'
|
||||||
|
)
|
||||||
|
|
||||||
def test_convert_binds_to_dict(self):
|
def test_convert_binds_to_dict(self):
|
||||||
parsing_service = SnmpParsingService(1, self.conf)
|
parsing_service = SnmpParsingService(1, self.conf)
|
||||||
|
Loading…
Reference in New Issue
Block a user