nova instance transformer and tests
Change-Id: Id3eb11592c36ac196680f6b6d21bf40f1a67aebf
This commit is contained in:
parent
c7942a5d85
commit
797240c436
@ -6,9 +6,10 @@ pbr>=1.6
|
||||
Babel>=1.3
|
||||
networkx>=1.10
|
||||
oslo.log>=1.12.0 # Apache-2.0
|
||||
oslo.policy>=0.3.0
|
||||
pecan>=0.8.0
|
||||
PasteDeploy>=1.5.0
|
||||
Werkzeug>=0.7
|
||||
oslo.policy>=0.3.0
|
||||
keystonemiddleware>=2.3.0
|
||||
stevedore>=1.5.0 # Apache-2.0
|
||||
exrex>=0.9.4
|
||||
|
@ -39,3 +39,8 @@ all_files = 1
|
||||
|
||||
[upload_sphinx]
|
||||
upload-dir = doc/build/html
|
||||
|
||||
[entry_points]
|
||||
vitrage.transformers =
|
||||
nova.instance = vitrage.entity_graph.transformer.nova_transformer.InstanceTransformer
|
||||
nova.host = vitrage.entity_graph.transformer.nova_transformer.HostTransformer
|
||||
|
@ -15,3 +15,5 @@ testrepository>=0.0.18
|
||||
testscenarios>=0.4
|
||||
testtools>=1.4.0
|
||||
exrex>=0.9.4
|
||||
stevedore>=1.5.0 # Apache-2.0
|
||||
|
||||
|
1
vitrage/common/__init__.py
Normal file
1
vitrage/common/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
__author__ = 'stack'
|
41
vitrage/common/constants.py
Normal file
41
vitrage/common/constants.py
Normal file
@ -0,0 +1,41 @@
|
||||
# Copyright 2015 - Alcatel-Lucent
|
||||
#
|
||||
# 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.
|
||||
|
||||
|
||||
class VertexConstants(object):
|
||||
TYPE = 'TYPE'
|
||||
SUB_TYPE = 'SUB_TYPE'
|
||||
ID = 'ID'
|
||||
IS_VERTEX_DELETED = 'IS_VERTEX_DELETED'
|
||||
VERTEX_DELETION_TIMESTAMP = 'VERTEX_DELETION_TIMESTAMP'
|
||||
STATE = 'STATE'
|
||||
PROJECT = 'PROJECT'
|
||||
UPDATE_TIMESTAMP = 'UPDATE_TIMESTAMP'
|
||||
|
||||
|
||||
class EdgeConstants(object):
|
||||
RELATION_NAME = 'RELATION_NAME'
|
||||
IS_EDGE_DELETED = 'IS_EDGE_DELETED'
|
||||
EDGE_DELETION_TIMESTAMP = 'EDGE_DELETION_TIMESTAMP'
|
||||
|
||||
|
||||
class EdgeLabels(object):
|
||||
ON = 'on'
|
||||
CONTAINS = 'contains'
|
||||
|
||||
|
||||
class SynchronizerMessageMode(object):
|
||||
SNAPSHOT = 'snapshot'
|
||||
INIT_SNAPSHOT = 'init_snapshot'
|
||||
UPDATE = 'update'
|
@ -1,30 +0,0 @@
|
||||
# Copyright 2015 - Alcatel-Lucent
|
||||
#
|
||||
# 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.
|
||||
|
||||
# Vertex properties
|
||||
TYPE = 'TYPE'
|
||||
SUB_TYPE = 'SUB_TYPE'
|
||||
ID = 'ID'
|
||||
VERTEX_ID = 'VERTEX_ID'
|
||||
EVENT_TYPE = 'EVENT_TYPE'
|
||||
IS_VERTEX_DELETED = 'IS_VERTEX_DELETED'
|
||||
VERTEX_DELETION_TIMESTAMP = 'VERTEX_DELETION_TIMESTAMP'
|
||||
STATE = 'STATE'
|
||||
PROJECT = 'PROJECT'
|
||||
TIMESTAMP = 'TIMESTAMP'
|
||||
|
||||
# Edge properties
|
||||
RELATION_NAME = 'RELATION_NAME'
|
||||
IS_EDGE_DELETED = 'IS_EDGE_DELETED'
|
||||
EDGE_DELETION_TIMESTAMP = 'EDGE_DELETION_TIMESTAMP'
|
@ -13,12 +13,19 @@
|
||||
# under the License.
|
||||
|
||||
import abc
|
||||
import six
|
||||
|
||||
from collections import namedtuple
|
||||
from oslo_log import log as logging
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
EntityWrapper = \
|
||||
namedtuple('EntityWrapper', ['entity_vertex', 'neighbors'], 'action')
|
||||
|
||||
|
||||
@six.add_metaclass(abc.ABCMeta)
|
||||
class Transformer(object):
|
||||
|
||||
@abc.abstractmethod
|
||||
@ -28,13 +35,14 @@ class Transformer(object):
|
||||
:return: An EntityWrapper. EntityWrapper is namedTuple that contains
|
||||
an entity vertex and a list of vertex and an edge pair that describe
|
||||
the entity's neighbors.
|
||||
:rtype: EntityWrapper
|
||||
"""
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def get_key_fields(self):
|
||||
def key_fields(self):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def get_key(self, entity_event):
|
||||
def extract_key(self, entity_event):
|
||||
pass
|
||||
|
47
vitrage/entity_graph/transformer/nova_transformer.py
Normal file
47
vitrage/entity_graph/transformer/nova_transformer.py
Normal file
@ -0,0 +1,47 @@
|
||||
# Copyright 2015 - Alcatel-Lucent
|
||||
#
|
||||
# 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_log import log as logging
|
||||
from vitrage.common.constants import VertexConstants as vertex_cons
|
||||
from vitrage.entity_graph.transformer import base
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
KEY_SEPARATOR = ':'
|
||||
|
||||
ENTITY_TYPE = 'RESOURCE'
|
||||
INSTANCE_SUB_TYPE = 'nova.instance'
|
||||
HOST_SUB_TYPE = 'nova.host'
|
||||
|
||||
|
||||
class InstanceTransformer(base.Transformer):
|
||||
|
||||
# # Fields returned from Nova Instance snapshot
|
||||
ENTITY_ID_DICT = {'snapshot': 'id',
|
||||
'init_snapshot': 'id',
|
||||
'update': 'instance_id'}
|
||||
|
||||
def transform(self, entity_event):
|
||||
pass
|
||||
|
||||
def key_fields(self):
|
||||
return [vertex_cons.TYPE, vertex_cons.SUB_TYPE, vertex_cons.ID]
|
||||
|
||||
def extract_key(self, entity_event):
|
||||
|
||||
sync_mode = entity_event['sync_mode']
|
||||
return KEY_SEPARATOR.join(
|
||||
[ENTITY_TYPE,
|
||||
INSTANCE_SUB_TYPE,
|
||||
entity_event[self.ENTITY_ID_DICT[sync_mode]]])
|
29
vitrage/entity_graph/transformer/transformer_manager.py
Normal file
29
vitrage/entity_graph/transformer/transformer_manager.py
Normal file
@ -0,0 +1,29 @@
|
||||
# Copyright 2014 - Mirantis, Inc.
|
||||
# Copyright 2014 - StackStorm, Inc.
|
||||
#
|
||||
# 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_log import log as logging
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class TransformerManager(object):
|
||||
|
||||
def __init__(self):
|
||||
self.transformers = self.register_transformer_classes()
|
||||
|
||||
@staticmethod
|
||||
def register_transformer_classes():
|
||||
pass
|
@ -67,7 +67,7 @@ class Edge(object):
|
||||
:param source_id: source vertex id
|
||||
:type source_id: str
|
||||
|
||||
:param target_id: target vertex id
|
||||
:param target_id: target vertex id`
|
||||
:type target_id: str
|
||||
|
||||
:param label:
|
||||
|
@ -25,14 +25,14 @@ multiple instances of the same entity type.
|
||||
|
||||
from os.path import curdir
|
||||
from os import walk
|
||||
from random import randint
|
||||
import random
|
||||
|
||||
from entity_model import CommonEntityModel as cem
|
||||
|
||||
|
||||
def _get_filename_path(filename):
|
||||
base_dir = None
|
||||
for i in walk("../%s" % curdir):
|
||||
for i in walk("../../%s" % curdir):
|
||||
if i[0].find('resources') != -1 and filename in i[2]:
|
||||
base_dir = i[0]
|
||||
break
|
||||
@ -46,8 +46,6 @@ class MockEventGenerator(object):
|
||||
"""Represents a single generator.
|
||||
|
||||
A generator can generate events for several instances of the same type
|
||||
|
||||
file is expected to be in the ../resources folder
|
||||
"""
|
||||
|
||||
def __init__(self, filename, instance_num, generator_name='generator'):
|
||||
@ -75,7 +73,7 @@ class MockEventGenerator(object):
|
||||
param_type = line_params[1].lower()
|
||||
params_dict[param_type][line_params[0]] = line_params[2]
|
||||
except KeyError as ke:
|
||||
print("Syntax error: {0}".format(ke.message))
|
||||
print("Syntax error ({0}): {1}".format(ke.errno, ke.strerror))
|
||||
|
||||
def prepare_instance_models(self):
|
||||
"""Create the models for all the instances """
|
||||
@ -97,7 +95,7 @@ class MockEventGenerator(object):
|
||||
|
||||
data_stream = []
|
||||
for _ in xrange(event_num):
|
||||
model = self.models[randint(0, self.instance_num - 1)]
|
||||
model = self.models[random.randint(0, self.instance_num - 1)]
|
||||
model.generate_dynamic_params()
|
||||
data_stream.append(model.params)
|
||||
return data_stream
|
||||
|
@ -20,7 +20,7 @@ of what can be returned
|
||||
|
||||
usage example:
|
||||
test_entity_spec_list = [
|
||||
{'filename': '../resources/mock_nova_instance_config_1.txt',
|
||||
{'filename': '../resources/mock_nova_inst_snapshot.txt',
|
||||
'#instances': 10,
|
||||
'name': 'Instance (vm) generator'
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
event_type S snapshot
|
||||
sync_mode D snapshot|init_snapshot
|
||||
OS-DCF:diskConfig S AUTO
|
||||
OS-EXT-AZ:availability_zone S nova
|
||||
OS-EXT-SRV-ATTR:host D [a-z]{4}-devstack
|
@ -1,4 +1,4 @@
|
||||
event_type S update
|
||||
sync_mode S update
|
||||
u-OS-DCF:diskConfig S AUTO
|
||||
u-OS-EXT-AZ:availability_zone S nova
|
||||
u-OS-EXT-SRV-ATTR:host D [a-z]{4}-devstack
|
||||
@ -22,7 +22,7 @@ u-config_drive D True|False
|
||||
u-created D \d{2}:\d{2}:\d{2} \d{2}:\d{2}:\d{2}
|
||||
u-flavor D m1.nano
|
||||
u-hostId D [0-9a-f]{56}
|
||||
u-id S [0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}
|
||||
instance_id S [0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}
|
||||
u-image D cirros-[a-z]+ ([a-z0-9]+)
|
||||
u-key_name D -
|
||||
u-metadata D \{\}
|
@ -13,8 +13,16 @@
|
||||
# under the License.
|
||||
|
||||
from oslotest import base
|
||||
import sys
|
||||
|
||||
|
||||
class BaseTest(base.BaseTestCase):
|
||||
|
||||
"""Test case base class for all unit tests."""
|
||||
|
||||
def assert_list_equal(self, l1, l2):
|
||||
if tuple(sys.version_info)[0:2] < (2, 7):
|
||||
# for python 2.6 compatibility
|
||||
self.assertEqual(l1, l2)
|
||||
else:
|
||||
super(BaseTest, self).assertListEqual(l1, l2)
|
||||
|
@ -1,26 +0,0 @@
|
||||
# Copyright 2015 - Alcatel-Lucent
|
||||
#
|
||||
# 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_log import log as logging
|
||||
from vitrage.tests.unit import base
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class TransformNovaInstanceTest(base.BaseTest):
|
||||
|
||||
def test_transform_instance(self):
|
||||
|
||||
LOG.debug('Test transform Nova instance into entity wrapper')
|
||||
self.assertTrue(True)
|
83
vitrage/tests/unit/transformers/test_nova_transformers.py
Normal file
83
vitrage/tests/unit/transformers/test_nova_transformers.py
Normal file
@ -0,0 +1,83 @@
|
||||
# Copyright 2015 - Alcatel-Lucent
|
||||
#
|
||||
# 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_log import log as logging
|
||||
|
||||
from vitrage.common.constants import VertexConstants as vertexCons
|
||||
from vitrage.entity_graph.transformer import nova_transformer as nt
|
||||
from vitrage.tests.mocks import mock_syncronizer as mock_sync
|
||||
from vitrage.tests.unit import base
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def get_nova_instance_transformer():
|
||||
return nt.InstanceTransformer()
|
||||
|
||||
|
||||
def get_instance_entity_spec_list(config_file_path, number_of_instances):
|
||||
|
||||
"""Returns a list of nova instance specifications by
|
||||
|
||||
given specific configuration file.
|
||||
|
||||
:rtype : list
|
||||
"""
|
||||
return {
|
||||
'filename': config_file_path,
|
||||
'#instances': number_of_instances,
|
||||
'name': 'Instance generator'
|
||||
}
|
||||
|
||||
|
||||
class NovaInstanceTransformerTest(base.BaseTest):
|
||||
|
||||
def test_key_fields(self):
|
||||
LOG.debug('Test get key fields from nova instance transformer')
|
||||
transformer = get_nova_instance_transformer()
|
||||
|
||||
expected_key_fields = [vertexCons.TYPE,
|
||||
vertexCons.SUB_TYPE,
|
||||
vertexCons.ID]
|
||||
observed_key_fields = transformer.key_fields()
|
||||
self.assert_list_equal(expected_key_fields, observed_key_fields)
|
||||
|
||||
def test_extract_key(self):
|
||||
LOG.debug('Test get key from nova instance transformer')
|
||||
|
||||
transformer = get_nova_instance_transformer()
|
||||
|
||||
instance_specifications = [
|
||||
get_instance_entity_spec_list('mock_nova_inst_snapshot.txt', 1),
|
||||
get_instance_entity_spec_list('mock_nova_inst_update.txt', 1)
|
||||
]
|
||||
|
||||
spec_list = mock_sync.get_mock_generators(instance_specifications)
|
||||
instance_events = mock_sync.generate_random_events_list(spec_list)
|
||||
|
||||
for event in instance_events:
|
||||
observed_key = transformer.extract_key(event)
|
||||
observed_key_fields = observed_key.split(nt.KEY_SEPARATOR)
|
||||
|
||||
self.assertEqual(nt.ENTITY_TYPE, observed_key_fields[0])
|
||||
self.assertEqual(nt.INSTANCE_SUB_TYPE, observed_key_fields[1])
|
||||
|
||||
event_id = event[transformer.ENTITY_ID_DICT[event['sync_mode']]]
|
||||
self.assertEqual(event_id, observed_key_fields[2])
|
||||
|
||||
expected_key = nt.KEY_SEPARATOR.join(
|
||||
[nt.ENTITY_TYPE,
|
||||
nt.INSTANCE_SUB_TYPE,
|
||||
event_id])
|
||||
self.assertEqual(expected_key, observed_key)
|
1
vitrage/utils/__init__.py
Normal file
1
vitrage/utils/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
__author__ = 'stack'
|
Loading…
Reference in New Issue
Block a user