Skip to content

Commit df60038

Browse files
author
Falco Falco
committed
Merge remote-tracking branch 'msft_github/master'
* msft_github/master: [configdb]: Addopt get_table method to work with python3. (sonic-net#26) [configdb]: add mod_entry, rename set_config to mod_config (sonic-net#25) [configdb] fix bug of leaving unwanted columns in a hash (sonic-net#23) Revert "Add support to remove the key of table entry (sonic-net#15)" (sonic-net#24) Add support to remove the key of table entry (sonic-net#15) [configdb] support redis connecting methods other than TCP (sonic-net#22) [interface]: Extend the max data wait time to 60s (sonic-net#21)
2 parents 11e7341 + a0418a1 commit df60038

File tree

2 files changed

+59
-15
lines changed

2 files changed

+59
-15
lines changed

src/swsssdk/configdb.py

+58-14
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
# Write to config DB
66
config_db = ConfigDBConnector()
77
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', {
99
'admin_status': state
1010
})
1111
@@ -17,20 +17,23 @@
1717
config_db.listen()
1818
1919
"""
20-
2120
import sys
2221
import time
2322
from .dbconnector import SonicV2Connector
2423

24+
PY3K = sys.version_info >= (3, 0)
25+
2526
class ConfigDBConnector(SonicV2Connector):
2627

2728
INIT_INDICATOR = 'CONFIG_DB_INITIALIZED'
2829
TABLE_NAME_SEPARATOR = '|'
2930
KEY_SEPARATOR = '|'
3031

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)
3437
self.handlers = {}
3538

3639
def __wait_for_db_init(self):
@@ -99,16 +102,28 @@ def __raw_to_typed(self, raw_data):
99102
if raw_data == None:
100103
return None
101104
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+
103110
# "NULL:NULL" is used as a placeholder for objects with no attributes
104111
if key == "NULL":
105112
pass
106113
# A column key with ending '@' is used to mark list-typed table items
107114
# TODO: Replace this with a schema-based typing mechanism.
108115
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
110122
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]
112127
return typed_data
113128

114129
def __typed_to_raw(self, typed_data):
@@ -142,6 +157,29 @@ def deserialize_key(key):
142157

143158
def set_entry(self, table, key, data):
144159
"""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.
145183
Args:
146184
table: Table name.
147185
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):
187225
data = {}
188226
for key in keys:
189227
try:
190-
(_, row) = key.split(self.TABLE_NAME_SEPARATOR, 1)
191228
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
194237
except ValueError:
195238
pass #Ignore non table-formated redis entries
196239
return data
197240

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.
200244
Args:
201245
data: config data in a dictionary form
202246
{
@@ -208,7 +252,7 @@ def set_config(self, data):
208252
for table_name in data:
209253
table_data = data[table_name]
210254
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])
212256

213257
def get_config(self):
214258
"""Read all config data.

src/swsssdk/interface.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ class DBInterface(object):
111111
Time to wait for any given message to arrive via pub-sub.
112112
"""
113113

114-
PUB_SUB_MAXIMUM_DATA_WAIT = 30.0 # seconds
114+
PUB_SUB_MAXIMUM_DATA_WAIT = 60.0 # seconds
115115
"""
116116
Maximum allowable time to wait on a specific pub-sub notification.
117117
"""

0 commit comments

Comments
 (0)