Repository URL to install this package:
|
Version:
1:7.26.0-1 ▾
|
datadog-agent
/
opt
/
datadog-agent
/
embedded
/
lib
/
python3.8
/
site-packages
/
rethinkdb
/
_dump.py
|
|---|
#!/usr/bin/env python
# Copyright 2018 RethinkDB
#
# Licensed under the Apache License, Version 2.0 (the 'License');
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an 'AS IS' BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# This file incorporates work covered by the following copyright:
# Copyright 2010-2016 RethinkDB, all rights reserved.
'''`rethinkdb-dump` creates an archive of data from a RethinkDB cluster'''
from __future__ import print_function
import datetime
import os
import platform
import shutil
import sys
import tarfile
import tempfile
import time
import traceback
from rethinkdb import _export, utils_common
from rethinkdb.logger import default_logger
usage = "rethinkdb dump [-c HOST:PORT] [-p] [--password-file FILENAME] [--tls-cert FILENAME] [-f FILE] " \
"[--clients NUM] [-e (DB | DB.TABLE)]..."
help_epilog = '''
EXAMPLES:
rethinkdb dump -c mnemosyne:39500
Archive all data from a cluster running on host 'mnemosyne' with a client port at 39500.
rethinkdb dump -e test -f rdb_dump.tar.gz
Archive only the 'test' database from a local cluster into a named file.
rethinkdb dump -c hades -e test.subscribers -p
Archive a specific table from a cluster running on host 'hades' which requires a password.'''
def parse_options(argv, prog=None):
parser = utils_common.CommonOptionsParser(usage=usage, epilog=help_epilog, prog=prog)
parser.add_option(
"-f",
"--file",
dest="out_file",
metavar="FILE",
default=None,
help='file to write archive to (defaults to rethinkdb_dump_DATE_TIME.tar.gz);\nif FILE is -, use standard '
'output (note that intermediate files will still be written to the --temp-dir directory)')
parser.add_option(
"-e",
"--export",
dest="db_tables",
metavar="DB|DB.TABLE",
default=[],
type='db_table',
help='limit dump to the given database or table (may be specified multiple times)',
action="append")
parser.add_option("--temp-dir", dest="temp_dir", metavar="directory", default=None,
help='the directory to use for intermediary results')
parser.add_option(
"--overwrite-file",
dest="overwrite",
default=False,
help="overwrite -f/--file if it exists",
action="store_true")
parser.add_option(
"--clients",
dest="clients",
metavar="NUM",
default=3,
help='number of tables to export simultaneously (default: 3)',
type="pos_int")
parser.add_option(
"--read-outdated",
dest="outdated",
default=False,
help='use outdated read mode',
action="store_true")
options, args = parser.parse_args(argv)
# Check validity of arguments
if len(args) != 0:
raise parser.error("No positional arguments supported. Unrecognized option(s): %s" % args)
# Add dump name
if platform.system() == "Windows" or platform.system().lower().startswith('cygwin'):
options.dump_name = "rethinkdb_dump_%s" % datetime.datetime.today().strftime(
"%Y-%m-%dT%H-%M-%S") # no colons in name
else:
options.dump_name = "rethinkdb_dump_%s" % datetime.datetime.today().strftime("%Y-%m-%dT%H:%M:%S")
# Verify valid output file
if options.out_file == "-":
options.out_file = sys.stdout
options.quiet = True
elif options.out_file is None:
options.out_file = os.path.realpath("%s.tar.gz" % options.dump_name)
else:
options.out_file = os.path.realpath(options.out_file)
if options.out_file is not sys.stdout:
if os.path.exists(options.out_file) and not options.overwrite:
parser.error("Output file already exists: %s" % options.out_file)
if os.path.exists(options.out_file) and not os.path.isfile(options.out_file):
parser.error("There is a non-file at the -f/--file location: %s" % options.out_file)
# Verify valid client count
if options.clients < 1:
raise RuntimeError("Error: invalid number of clients (%d), must be greater than zero" % options.clients)
# Make sure the temporary directory exists and is accessible
if options.temp_dir is not None:
if not os.path.exists(options.temp_dir):
try:
os.makedirs(options.temp_dir)
except OSError:
parser.error("Could not create temporary directory: %s" % options.temp_dir)
if not os.path.isdir(options.temp_dir):
parser.error("Temporary directory doesn't exist or is not a directory: %s" % options.temp_dir)
if not os.access(options.temp_dir, os.W_OK):
parser.error("Temporary directory inaccessible: %s" % options.temp_dir)
return options
def main(argv=None, prog=None):
options = parse_options(argv or sys.argv[1:], prog=prog)
try:
if not options.quiet:
# Print a warning about the capabilities of dump, so no one is confused (hopefully)
print("""\
NOTE: 'rethinkdb-dump' saves data, secondary indexes, and write hooks, but does *not* save
cluster metadata. You will need to recreate your cluster setup yourself after
you run 'rethinkdb-restore'.""")
try:
start_time = time.time()
archive = None
# -- _export options - need to be kep in-sync with _export
options.directory = os.path.realpath(tempfile.mkdtemp(dir=options.temp_dir))
options.fields = None
options.delimiter = None
options.format = 'json'
# -- export to a directory
if not options.quiet:
print(" Exporting to temporary directory...")
try:
_export.run(options)
except Exception as exc:
default_logger.exception(exc)
if options.debug:
sys.stderr.write('\n%s\n' % traceback.format_exc())
raise Exception("Error: export failed, %s" % exc)
# -- zip directory
if not options.quiet:
print(" Zipping export directory...")
try:
if hasattr(options.out_file, 'read'):
archive = tarfile.open(fileobj=options.out_file, mode="w:gz")
else:
archive = tarfile.open(name=options.out_file, mode="w:gz")
for curr, _, files in os.walk(os.path.realpath(options.directory)):
for data_file in files:
full_path = os.path.join(options.directory, curr, data_file)
archive_path = os.path.join(options.dump_name, os.path.relpath(full_path, options.directory))
archive.add(full_path, arcname=archive_path)
os.unlink(full_path)
finally:
if archive:
archive.close()
# --
if not options.quiet:
print(
"Done (%.2f seconds): %s" %
(time.time() -
start_time,
options.out_file.name if hasattr(
options.out_file,
'name') else options.out_file))
except KeyboardInterrupt:
time.sleep(0.2)
raise RuntimeError("Interrupted")
finally:
if os.path.exists(options.directory):
shutil.rmtree(options.directory)
except Exception as ex:
if options.debug:
traceback.print_exc()
print(ex, file=sys.stderr)
return 1
return 0
if __name__ == "__main__":
sys.exit(main())