5
5
# Write to config DB
6
6
config_db = ConfigDBConnector()
7
7
config_db.connect()
8
- config_db.set_entry ('BGP_NEIGHBOR', '10.0.0.1', {
8
+ config_db.mod_entry ('BGP_NEIGHBOR', '10.0.0.1', {
9
9
'admin_status': state
10
10
})
11
11
17
17
config_db.listen()
18
18
19
19
"""
20
-
21
20
import sys
22
21
import time
23
22
from .dbconnector import SonicV2Connector
24
23
24
+ PY3K = sys .version_info >= (3 , 0 )
25
+
25
26
class ConfigDBConnector (SonicV2Connector ):
26
27
27
28
INIT_INDICATOR = 'CONFIG_DB_INITIALIZED'
28
29
TABLE_NAME_SEPARATOR = '|'
29
30
KEY_SEPARATOR = '|'
30
31
31
- def __init__ (self ):
32
- # Connect to Redis through TCP, which does not requires root.
33
- super (ConfigDBConnector , self ).__init__ (host = '127.0.0.1' )
32
+ def __init__ (self , ** kwargs ):
33
+ # By default, connect to Redis through TCP, which does not requires root.
34
+ if len (kwargs ) == 0 :
35
+ kwargs ['host' ] = '127.0.0.1'
36
+ super (ConfigDBConnector , self ).__init__ (** kwargs )
34
37
self .handlers = {}
35
38
36
39
def __wait_for_db_init (self ):
@@ -99,16 +102,28 @@ def __raw_to_typed(self, raw_data):
99
102
if raw_data == None :
100
103
return None
101
104
typed_data = {}
102
- for key in raw_data :
105
+ for raw_key in raw_data :
106
+ key = raw_key
107
+ if PY3K :
108
+ key = raw_key .decode ('utf-8' )
109
+
103
110
# "NULL:NULL" is used as a placeholder for objects with no attributes
104
111
if key == "NULL" :
105
112
pass
106
113
# A column key with ending '@' is used to mark list-typed table items
107
114
# TODO: Replace this with a schema-based typing mechanism.
108
115
elif key .endswith ("@" ):
109
- typed_data [key [:- 1 ]] = raw_data [key ].split (',' )
116
+ value = ""
117
+ if PY3K :
118
+ value = raw_data [raw_key ].decode ("utf-8" ).split (',' )
119
+ else :
120
+ value = raw_data [raw_key ].split (',' )
121
+ typed_data [key [:- 1 ]] = value
110
122
else :
111
- typed_data [key ] = raw_data [key ]
123
+ if PY3K :
124
+ typed_data [key ] = raw_data [raw_key ].decode ('utf-8' )
125
+ else :
126
+ typed_data [key ] = raw_data [raw_key ]
112
127
return typed_data
113
128
114
129
def __typed_to_raw (self , typed_data ):
@@ -142,6 +157,29 @@ def deserialize_key(key):
142
157
143
158
def set_entry (self , table , key , data ):
144
159
"""Write a table entry to config db.
160
+ Remove extra fields in the db which are not in the data.
161
+ Args:
162
+ table: Table name.
163
+ key: Key of table entry, or a tuple of keys if it is a multi-key table.
164
+ data: Table row data in a form of dictionary {'column_key': 'value', ...}.
165
+ Pass {} as data will create an entry with no column if not already existed.
166
+ Pass None as data will delete the entry.
167
+ """
168
+ key = self .serialize_key (key )
169
+ client = self .redis_clients [self .CONFIG_DB ]
170
+ _hash = '{}{}{}' .format (table .upper (), self .TABLE_NAME_SEPARATOR , key )
171
+ if data == None :
172
+ client .delete (_hash )
173
+ else :
174
+ original = self .get_entry (table , key )
175
+ client .hmset (_hash , self .__typed_to_raw (data ))
176
+ for k in [ k for k in original .keys () if k not in data .keys () ]:
177
+ if type (original [k ]) == list :
178
+ k = k + '@'
179
+ client .hdel (_hash , self .serialize_key (k ))
180
+
181
+ def mod_entry (self , table , key , data ):
182
+ """Modify a table entry to config db.
145
183
Args:
146
184
table: Table name.
147
185
key: Key of table entry, or a tuple of keys if it is a multi-key table.
@@ -187,16 +225,22 @@ def get_table(self, table):
187
225
data = {}
188
226
for key in keys :
189
227
try :
190
- (_ , row ) = key .split (self .TABLE_NAME_SEPARATOR , 1 )
191
228
entry = self .__raw_to_typed (client .hgetall (key ))
192
- if entry != None :
193
- data [self .deserialize_key (row )] = entry
229
+ if entry :
230
+ if PY3K :
231
+ key = key .decode ('utf-8' )
232
+ (_ , row ) = key .split (self .TABLE_NAME_SEPARATOR , 1 )
233
+ data [self .deserialize_key (row )] = entry
234
+ else :
235
+ (_ , row ) = key .split (self .TABLE_NAME_SEPARATOR , 1 )
236
+ data [self .deserialize_key (row )] = entry
194
237
except ValueError :
195
238
pass #Ignore non table-formated redis entries
196
239
return data
197
240
198
- def set_config (self , data ):
199
- """Write multiple tables into config db.
241
+ def mod_config (self , data ):
242
+ """Write multiple tables into config db.
243
+ Extra entries/fields in the db which are not in the data are kept.
200
244
Args:
201
245
data: config data in a dictionary form
202
246
{
@@ -208,7 +252,7 @@ def set_config(self, data):
208
252
for table_name in data :
209
253
table_data = data [table_name ]
210
254
for key in table_data :
211
- self .set_entry (table_name , key , table_data [key ])
255
+ self .mod_entry (table_name , key , table_data [key ])
212
256
213
257
def get_config (self ):
214
258
"""Read all config data.
0 commit comments