Refactor resource.py/Resource
Create a class of 'Recource' to replace the original definition. It will bring several advantages. 1. The new class will be used as tuple which can't be modified, accessed by name or index. 2. The instance of new class can be hashable whatever the type of members of instace. So, it can be used in method of 'build_graph'. 3. Add some other functions to it, such as transform it to dict. 4. It is easy to chose members of it to be serialized by modifing the definition of property of 'Resource'. Change-Id: Ib5f3fea53bff9fe0a7c3b88339af26b70a6b7d3c
This commit is contained in:
parent
c24b80e8ce
commit
b1255e1966
|
@ -11,10 +11,34 @@
|
|||
# under the License.
|
||||
|
||||
|
||||
from collections import namedtuple
|
||||
class Resource(object):
|
||||
__slots__ = ('type', 'id', 'name', 'extra_info')
|
||||
|
||||
_Resource = namedtuple("Resource", ('type', 'id', 'name', 'extra_info'))
|
||||
def __init__(self, type, id, name, extra_info=None):
|
||||
self.type = type
|
||||
self.id = id
|
||||
self.name = name
|
||||
self.extra_info = extra_info
|
||||
|
||||
def __setattr__(self, key, value):
|
||||
try:
|
||||
getattr(self, key)
|
||||
except AttributeError:
|
||||
pass
|
||||
else:
|
||||
raise AttributeError()
|
||||
|
||||
def Resource(type, id, name, extra_info=None):
|
||||
return _Resource(type, id, name, extra_info)
|
||||
return super(Resource, self).__setattr__(key, value)
|
||||
|
||||
def __hash__(self):
|
||||
return hash(self.key)
|
||||
|
||||
def __eq__(self, other):
|
||||
return self.key == other.key
|
||||
|
||||
def to_dict(self):
|
||||
return {item: getattr(self, item) for item in self.__slots__}
|
||||
|
||||
@property
|
||||
def key(self):
|
||||
return (self.type, self.id, self.name)
|
||||
|
|
|
@ -40,15 +40,7 @@ class CompleteProtectTask(task.Task):
|
|||
|
||||
def get_flow(context, protectable_registry, workflow_engine, plan, provider,
|
||||
checkpoint):
|
||||
# The 'extra-info' field of resources in plan is optional
|
||||
# The extra_info field of the resource is a dict.
|
||||
# The dict can not be handled by build_graph. It will throw a
|
||||
# error. TypeError: unhashable type: 'dict'
|
||||
resources = set()
|
||||
for item in plan.get("resources"):
|
||||
item["extra_info"] = None
|
||||
resources.add(Resource(**item))
|
||||
|
||||
resources = set(Resource(**item) for item in plan.get("resources"))
|
||||
resource_graph = protectable_registry.build_graph(context,
|
||||
resources)
|
||||
checkpoint.resource_graph = resource_graph
|
||||
|
|
|
@ -219,7 +219,9 @@ def unpack_graph(packed_graph):
|
|||
|
||||
def serialize_resource_graph(resource_graph):
|
||||
packed_resource_graph = pack_graph(resource_graph)
|
||||
return jsonutils.dumps(packed_resource_graph)
|
||||
return jsonutils.dumps(
|
||||
packed_resource_graph,
|
||||
default=lambda r: (r.type, r.id, r.name, r.extra_info))
|
||||
|
||||
|
||||
def deserialize_resource_graph(serialized_resource_graph):
|
||||
|
|
|
@ -320,9 +320,7 @@ class ProtectionManager(manager.Manager):
|
|||
'err': six.text_type(err)})
|
||||
raise
|
||||
|
||||
return dict(id=resource_instance.id, name=resource_instance.name,
|
||||
type=resource_instance.type,
|
||||
extra_info=resource_instance.extra_info)
|
||||
return resource_instance.to_dict()
|
||||
|
||||
@messaging.expected_exceptions(exception.ListProtectableResourceFailed)
|
||||
def list_protectable_dependents(self, context,
|
||||
|
@ -334,7 +332,7 @@ class ProtectionManager(manager.Manager):
|
|||
'id': protectable_id})
|
||||
|
||||
parent_resource = Resource(type=protectable_type, id=protectable_id,
|
||||
name="", extra_info=None)
|
||||
name="")
|
||||
|
||||
registry = self.protectable_registry
|
||||
try:
|
||||
|
@ -346,13 +344,7 @@ class ProtectionManager(manager.Manager):
|
|||
'err': six.text_type(err)})
|
||||
raise
|
||||
|
||||
result = []
|
||||
for resource in dependent_resources:
|
||||
result.append(dict(type=resource.type, id=resource.id,
|
||||
name=resource.name,
|
||||
extra_info=resource.extra_info))
|
||||
|
||||
return result
|
||||
return [resource.to_dict() for resource in dependent_resources]
|
||||
|
||||
def list_providers(self, context, marker=None, limit=None,
|
||||
sort_keys=None, sort_dirs=None, filters=None):
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
|
||||
from karbor import exception
|
||||
from karbor.i18n import _
|
||||
from karbor.resource import Resource
|
||||
from karbor.services.protection.graph import build_graph
|
||||
import six
|
||||
|
||||
|
@ -109,15 +108,7 @@ class ProtectableRegistry(object):
|
|||
|
||||
def build_graph(self, context, resources):
|
||||
def fetch_dependent_resources_context(resource):
|
||||
dependent_resources = self.fetch_dependent_resources(
|
||||
context, resource)
|
||||
# The extra_info field of the resource is a dict
|
||||
# The dict can not be handled by build_graph, it will throw a
|
||||
# error. TypeError: unhashable type: 'dict'
|
||||
return [Resource(type=dependent_resource.type,
|
||||
id=dependent_resource.id,
|
||||
name=dependent_resource.name, extra_info=None)
|
||||
for dependent_resource in dependent_resources]
|
||||
return self.fetch_dependent_resources(context, resource)
|
||||
|
||||
return build_graph(
|
||||
start_nodes=resources,
|
||||
|
|
|
@ -14,6 +14,7 @@ from oslo_serialization import jsonutils
|
|||
from oslo_serialization import msgpackutils
|
||||
|
||||
from karbor import exception
|
||||
from karbor import resource
|
||||
import karbor.services.protection.graph as graph
|
||||
from karbor.tests import base
|
||||
|
||||
|
@ -143,6 +144,25 @@ class GraphBuilderTest(base.TestCase):
|
|||
unserialized = graph.unpack_graph(fmt.loads(serialized))
|
||||
self.assertEqual(test_graph, unserialized)
|
||||
|
||||
def test_graph_serialize(self):
|
||||
resource_a = resource.Resource('server', 0, 'a', {'name': 'a'})
|
||||
resource_b = resource.Resource('volume', 1, 'b', {'name': 'b'})
|
||||
test_base = {
|
||||
resource_a: [resource_b],
|
||||
resource_b: []
|
||||
}
|
||||
test_graph = graph.build_graph(test_base.keys(), test_base.__getitem__)
|
||||
self.assertIn(
|
||||
graph.serialize_resource_graph(test_graph),
|
||||
[
|
||||
'[{"0x1": ["server", 0, "a", {"name": "a"}], '
|
||||
'"0x0": ["volume", 1, "b", {"name": "b"}]}, '
|
||||
'[["0x1", ["0x0"]]]]',
|
||||
'[{"0x0": ["volume", 1, "b", {"name": "b"}], '
|
||||
'"0x1": ["server", 0, "a", {"name": "a"}]}, '
|
||||
'[["0x1", ["0x0"]]]]'
|
||||
])
|
||||
|
||||
def test_graph_deserialize_unordered_adjacency(self):
|
||||
test_base = {
|
||||
"A1": ["B1", "B2"],
|
||||
|
|
Loading…
Reference in New Issue