1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
|
#
# Copyright (c) 2014 Juniper Networks, Inc. All rights reserved.
#
"""
This file contains implementation of database model for contrail config daemons
"""
from vnc_api.common.exceptions import NoIdError
class DBBase(object):
# This is the base class for all DB objects. All derived objects must
# have a class member called _dict of dictionary type.
# The init method of this class must be callled before using any functions
_logger = None
_cassandra = None
_manager = None
@classmethod
def init(cls, manager, logger, cassandra):
cls._logger = logger
cls._cassandra = cassandra
cls._manager = manager
# end init
class __metaclass__(type):
def __iter__(cls):
for i in cls._dict:
yield i
# end __iter__
def values(cls):
for i in cls._dict.values():
yield i
# end values
def items(cls):
for i in cls._dict.items():
yield i
# end items
# end __metaclass__
@classmethod
def get(cls, key):
if key in cls._dict:
return cls._dict[key]
return None
# end get
@classmethod
def locate(cls, key, *args):
if key not in cls._dict:
try:
cls._dict[key] = cls(key, *args)
except NoIdError as e:
cls._logger.debug(
"Exception %s while creating %s for %s",
e, cls.__name__, key)
return None
return cls._dict[key]
# end locate
@classmethod
def delete(cls, key):
if key in cls._dict:
del cls._dict[key]
# end delete
def get_ref_uuid_from_dict(self, obj_dict, ref_name):
if ref_name in obj_dict:
return obj_dict[ref_name][0]['uuid']
else:
return None
def add_ref(self, ref_type, ref):
if hasattr(self, ref_type):
setattr(self, ref_type, ref)
elif hasattr(self, ref_type+'s'):
ref_set = getattr(self, ref_type+'s')
ref_set.add(ref)
# end add_ref
def delete_ref(self, ref_type, ref):
if hasattr(self, ref_type) and getattr(self, ref_type) == ref:
setattr(self, ref_type, None)
elif hasattr(self, ref_type+'s'):
ref_set = getattr(self, ref_type+'s')
ref_set.discard(ref)
# end delete_ref
def add_to_parent(self, obj_dict):
self.parent_type = obj_dict.get('parent_type')
self.parent_id = obj_dict.get('parent_uuid')
if not self.parent_type or not self.parent_id:
return
p_obj = self._OBJ_TYPE_MAP[self.parent_type].get(self.parent_id)
if p_obj is not None:
p_obj.add_ref(self.obj_type, self.uuid)
# end
def remove_from_parent(self):
if not self.parent_type or not self.parent_id:
return
p_obj = self._OBJ_TYPE_MAP[self.parent_type].get(self.parent_id)
if p_obj is not None:
p_obj.delete_ref(self.obj_type, self.uuid)
def update_single_ref(self, ref_type, obj):
refs = obj.get(ref_type+'_refs') or obj.get(ref_type+'_back_refs')
if refs:
try:
new_id = refs[0]['uuid']
except KeyError:
fq_name = refs[0]['to']
new_id = self._cassandra.fq_name_to_uuid(ref_type, fq_name)
else:
new_id = None
old_id = getattr(self, ref_type, None)
if old_id == new_id:
return
ref_obj = self._OBJ_TYPE_MAP[ref_type].get(old_id)
if ref_obj is not None:
ref_obj.delete_ref(self.obj_type, self.uuid)
ref_obj = self._OBJ_TYPE_MAP[ref_type].get(new_id)
if ref_obj is not None:
ref_obj.add_ref(self.obj_type, self.uuid)
setattr(self, ref_type, new_id)
# end update_single_ref
def set_children(self, ref_type, obj):
refs = obj.get(ref_type+'s')
new_refs = set()
for ref in refs or []:
try:
new_id = ref['uuid']
except KeyError:
fq_name = ref['to']
new_id = self._cassandra.fq_name_to_uuid(ref_type, fq_name)
new_refs.add(new_id)
setattr(self, ref_type+'s', new_refs)
# end
def update_multiple_refs(self, ref_type, obj):
refs = obj.get(ref_type+'_refs') or obj.get(ref_type+'_back_refs')
new_refs = set()
for ref in refs or []:
try:
new_id = ref['uuid']
except KeyError:
fq_name = ref['to']
new_id = self._cassandra.fq_name_to_uuid(ref_type, fq_name)
new_refs.add(new_id)
old_refs = getattr(self, ref_type+'s')
for ref_id in old_refs - new_refs:
ref_obj = self._OBJ_TYPE_MAP[ref_type].get(ref_id)
if ref_obj is not None:
ref_obj.delete_ref(self.obj_type, self.uuid)
for ref_id in new_refs - old_refs:
ref_obj = self._OBJ_TYPE_MAP[ref_type].get(ref_id)
if ref_obj is not None:
ref_obj.add_ref(self.obj_type, self.uuid)
setattr(self, ref_type+'s', new_refs)
# end update_multiple_refs
def read_obj(self, uuid, obj_type=None):
method_name = "_cassandra_%s_read" % (obj_type or self.obj_type)
method = getattr(self._cassandra, method_name)
ok, objs = method([uuid])
if not ok:
self._logger.error(
'Cannot read %s %s, error %s' % (obj_type, uuid, objs))
raise NoIdError('')
return objs[0]
# end read_obj
def get_parent_uuid(self, obj):
if 'parent_uuid' in obj:
return obj['parent_uuid']
else:
parent_type = obj['parent_type'].replace('-', '_')
parent_fq_name = obj['fq_name'][:-1]
return self._cassandra.fq_name_to_uuid(parent_type, parent_fq_name)
# end get_parent_uuid
@classmethod
def find_by_name_or_uuid(cls, name_or_uuid):
obj = cls.get(name_or_uuid)
if obj:
return obj
for obj in cls.values():
if obj.name == name_or_uuid:
return obj
return None
# end find_by_name_or_uuid
@classmethod
def reset(cls):
cls._dict = {}
# end class DBBase
DBBase._OBJ_TYPE_MAP = {
}
|