Skip to content

Commit

Permalink
[sonic-py-common] porting sonic_db_dump_load.py from sonic-py-swsssdk…
Browse files Browse the repository at this point in the history
… to sonic-py-common (#12185)

Porting sonic_db_dump_load.py from sonic-py-swsssdk to sonic-py-common.

#### Why I did it
sonic-py-swsssdk will be deprecate, so porting sonic_db_dump_load.py to sonic-py-common.

#### How I did it
Copy sonic_db_dump_load.py to sonic-py-common, and fix minor API different.

#### How to verify it
Pass all E2E test.
The platform_tests/test_advanced_reboot.py::test_warm_reboot will cover this script.

#### Which release branch to backport (provide reason below if selected)

<!--
- Note we only backport fixes to a release branch, *not* features!
- Please also provide a reason for the backporting below.
- e.g.
- [x] 202006
-->

- [ ] 201811
- [ ] 201911
- [ ] 202006
- [ ] 202012
- [ ] 202106
- [ ] 202111
- [ ] 202205

#### Description for the changelog
Porting sonic_db_dump_load.py from sonic-py-swsssdk to sonic-py-common.

#### Ensure to add label/tag for the feature raised. example - [PR#2174](sonic-net/sonic-utilities#2174) where, Generic Config and Update feature has been labelled as GCU.

#### Link to config_db schema for YANG module changes
<!--
Provide a link to config_db schema for the table for which YANG model
is defined
Link should point to correct section on https://github.com/Azure/sonic-buildimage/blob/master/src/sonic-yang-models/doc/Configuration.md
-->

#### A picture of a cute animal (not mandatory but encouraged)
  • Loading branch information
liuh-80 committed Sep 29, 2022
1 parent 8c7e0f8 commit 1f9c89a
Show file tree
Hide file tree
Showing 2 changed files with 145 additions and 0 deletions.
6 changes: 6 additions & 0 deletions src/sonic-py-common/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@
'pytest',
'mock==3.0.5' # For python 2. Version >=4.0.0 drops support for py2
],
entry_points={
'console_scripts': [
'sonic-db-load = sonic_py_common.sonic_db_dump_load:sonic_db_dump_load',
'sonic-db-dump = sonic_py_common.sonic_db_dump_load:sonic_db_dump_load',
],
},
classifiers=[
'Intended Audience :: Developers',
'Operating System :: Linux',
Expand Down
139 changes: 139 additions & 0 deletions src/sonic-py-common/sonic_py_common/sonic_db_dump_load.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
## ref: https://github.com/p/redis-dump-load/blob/7bbdb1eaea0a51ed4758d3ce6ca01d497a4e7429/redisdl.py

def sonic_db_dump_load():
import optparse
import os.path
import re
import sys
from redisdl import dump, load
from swsscommon.swsscommon import SonicDBConfig

DUMP = 1
LOAD = 2

def options_to_kwargs(options):
args = {}
if options.password:
args['password'] = options.password
if options.encoding:
args['encoding'] = options.encoding
# dump only
if hasattr(options, 'pretty') and options.pretty:
args['pretty'] = True
if hasattr(options, 'keys') and options.keys:
args['keys'] = options.keys
# load only
if hasattr(options, 'use_expireat') and options.use_expireat:
args['use_expireat'] = True
if hasattr(options, 'empty') and options.empty:
args['empty'] = True
if hasattr(options, 'backend') and options.backend:
args['streaming_backend'] = options.backend
if hasattr(options, 'dbname') and options.dbname:
if options.conntype == 'tcp':
args['host'] = SonicDBConfig.getDbHostname(options.dbname)
args['port'] = SonicDBConfig.getDbPort(options.dbname)
args['db'] = SonicDBConfig.getDbId(options.dbname)
args['unix_socket_path'] = None
elif options.conntype == "unix_socket":
args['host'] = None
args['port'] = None
args['db'] = SonicDBConfig.getDbId(options.dbname)
args['unix_socket_path'] = SonicDBConfig.getDbSock(options.dbname)
else:
raise TypeError('redis connection type is tcp or unix_socket')

return args

def do_dump(options):
if options.output:
output = open(options.output, 'w')
else:
output = sys.stdout

kwargs = options_to_kwargs(options)
dump(output, **kwargs)

if options.output:
output.close()

def do_load(options, args):
if len(args) > 0:
input = open(args[0], 'rb')
else:
input = sys.stdin

kwargs = options_to_kwargs(options)
load(input, **kwargs)

if len(args) > 0:
input.close()

script_name = os.path.basename(sys.argv[0])
if re.search(r'load(?:$|\.)', script_name):
action = help = LOAD
elif re.search(r'dump(?:$|\.)', script_name):
action = help = DUMP
else:
# default is dump, however if dump is specifically requested
# we don't show help text for toggling between dumping and loading
action = DUMP
help = None

if help == LOAD:
usage = "Usage: %prog [options] [FILE]"
usage += "\n\nLoad data from FILE (which must be a JSON dump previously created"
usage += "\nby redisdl) into specified or default redis."
usage += "\n\nIf FILE is omitted standard input is read."
elif help == DUMP:
usage = "Usage: %prog [options]"
usage += "\n\nDump data from specified or default redis."
usage += "\n\nIf no output file is specified, dump to standard output."
else:
usage = "Usage: %prog [options]"
usage += "\n %prog -l [options] [FILE]"
usage += "\n\nDump data from redis or load data into redis."
usage += "\n\nIf input or output file is specified, dump to standard output and load"
usage += "\nfrom standard input."
parser = optparse.OptionParser(usage=usage)
parser.add_option('-w', '--password', help='connect with PASSWORD')
if help == DUMP:
parser.add_option('-n', '--dbname', help='dump DATABASE (APPL_DB/ASIC_DB...)')
parser.add_option('-t', '--conntype', help='indicate redis connection type (tcp[default] or unix_socket)', default='tcp')
parser.add_option('-k', '--keys', help='dump only keys matching specified glob-style pattern')
parser.add_option('-o', '--output', help='write to OUTPUT instead of stdout')
parser.add_option('-y', '--pretty', help='split output on multiple lines and indent it', action='store_true')
parser.add_option('-E', '--encoding', help='set encoding to use while decoding data from redis', default='utf-8')
elif help == LOAD:
parser.add_option('-n', '--dbname', help='dump DATABASE (APPL_DB/ASIC_DB...)')
parser.add_option('-t', '--conntype', help='indicate redis connection type (tcp[default] or unix_socket)', default='tcp')
parser.add_option('-e', '--empty', help='delete all keys in destination db prior to loading', action='store_true')
parser.add_option('-E', '--encoding', help='set encoding to use while encoding data to redis', default='utf-8')
parser.add_option('-B', '--backend', help='use specified streaming backend')
parser.add_option('-A', '--use-expireat', help='use EXPIREAT rather than TTL/EXPIRE', action='store_true')
else:
parser.add_option('-l', '--load', help='load data into redis (default is to dump data from redis)', action='store_true')
parser.add_option('-n', '--dbname', help='dump DATABASE (APPL_DB/ASIC_DB/COUNTERS_DB/LOGLEVEL_DB/CONFIG_DB...)')
parser.add_option('-t', '--conntype', help='indicate redis connection type (tcp[default] or unix_socket)', default='tcp')
parser.add_option('-k', '--keys', help='dump only keys matching specified glob-style pattern')
parser.add_option('-o', '--output', help='write to OUTPUT instead of stdout (dump mode only)')
parser.add_option('-y', '--pretty', help='split output on multiple lines and indent it (dump mode only)', action='store_true')
parser.add_option('-e', '--empty', help='delete all keys in destination db prior to loading (load mode only)', action='store_true')
parser.add_option('-E', '--encoding', help='set encoding to use while decoding data from redis', default='utf-8')
parser.add_option('-A', '--use-expireat', help='use EXPIREAT rather than TTL/EXPIRE', action='store_true')
parser.add_option('-B', '--backend', help='use specified streaming backend (load mode only)')
options, args = parser.parse_args()

if hasattr(options, 'load') and options.load:
action = LOAD

if action == DUMP:
if len(args) > 0:
parser.print_help()
exit(4)
do_dump(options)
else:
if len(args) > 1:
parser.print_help()
exit(4)
do_load(options, args)

0 comments on commit 1f9c89a

Please sign in to comment.