blob: ff5a81b20465d20aace325984053051de0b72780 [file] [log] [blame]
Alexey Golubev6f55d7e2016-03-23 16:16:29 +03001#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3
4import os
5import sys
6import logging
7from cliff.app import App
8from cliff.commandmanager import CommandManager
9from cliff.command import Command
10
11from trsync.objects.rsync_mirror import TRsync
12
13class PushCmd(Command):
14 log = logging.getLogger(__name__)
15
16 def get_description(self):
17 return "push SRC to several DST with snapshots"
18
19 def get_parser(self, prog_name):
20 parser = super(PushCmd, self).get_parser(prog_name)
21 parser.add_argument('source', help='Source path')
22 parser.add_argument('mirror_name', help='Mirror name')
23 parser.add_argument('-d', '--dest',
24 nargs='+',
25 required=True,
26 help='Destination rsync url')
27 parser.add_argument('-t', '--timestamp',
28 required=False,
29 help='Specified timestamp will be used for snapshot.'
30 'Format:yyyy-mm-dd-hhMMSS')
31 parser.add_argument('--snapshot-dir',
32 required=False,
33 default='snapshots',
34 help='Directory name for snapshots. "snapshots" '
35 'by default')
36 parser.add_argument('--init-directory-structure',
37 action='store_true',
38 required=False,
39 default=False,
40 help='It specified, all directories including'
41 '"snapshots-dir" will be created on remote location')
42 parser.add_argument('--save-latest-days',
43 required=False,
44 default=61,
45 help='Snapshots for specified number of days will be '
46 'saved. All older will be removed. 61 by default. '
47 '0 mean that old snapshots will not be deleted, '
48 '"None" mean that all snapshots excluding latest '
49 'will be deleted')
50 parser.add_argument('--latest-successful-postfix',
51 required=False,
52 default='latest',
53 help='Postfix for symlink to latest successfully '
54 'synced snapshot. Also used as --link-dest target. '
55 '"latest" by default.')
56 parser.add_argument('-s', '--symlinks',
57 nargs='+',
58 required=False,
59 default=[],
60 help='Update additional symlinks relative destination')
61 parser.add_argument('--extra',
62 required=False,
63 default='',
64 #action='store_const',
65 help='String with additional rsync parameters. For '
66 'example it may be "\--dry-run --any-rsync-option".'
67 'Use "\\" to disable argparse to parse extra value.')
68
69 return parser
70
71 def take_action(self, parsed_args):
72 properties = vars(parsed_args)
73 source_dir = properties.pop('source', None)
74 mirror_name = properties.pop('mirror_name', None)
75 symlinks = properties.pop('symlinks', None)
76 servers = properties.pop('dest', None)
77 if properties['extra'].startswith('\\'):
78 properties['extra'] = properties['extra'][1:]
79 properties['rsync_extra_params'] = properties.pop('extra')
80 properties['save_latest_days'] = \
81 None if properties['save_latest_days'] == 'None' \
82 else int(properties['save_latest_days'])
83
84 failed = list()
85 for server in servers:
86 source_dir = os.path.realpath(source_dir)
87 if not source_dir.endswith('/'):
88 source_dir += '/'
89 remote = TRsync(server, **properties)
90 try:
91 remote.push(source_dir, mirror_name, symlinks=symlinks)
92 except Exception as e:
93 print e.message
94 failed.append(server)
95
96 if failed:
97 print "Failed to push to {}".format(str(failed))
98 sys.exit(1)
99 #self.app.stdout.write(parsed_args.arg + "\n")
100
101class RemoveCmd(Command):
102 log = logging.getLogger(__name__)
103
104 def get_description(self):
105 return "remove all specified paths from several DST recursively"
106
107 def get_parser(self, prog_name):
108 parser = super(RemoveCmd, self).get_parser(prog_name)
109
110 parser.add_argument('path',
111 nargs='+',
112 help='Path to remove')
113 parser.add_argument('-d', '--dest',
114 nargs='+',
115 required=True,
116 help='Destination rsync url')
117 parser.add_argument('--extra',
118 required=False,
119 default='',
120 help='String with additional rsync parameters. For '
121 'example it may be "\--dry-run --any-rsync-option".'
122 'Use "\\" to disable argparse to parse extra value.')
123 return parser
124
125 def take_action(self, parsed_args):
126 properties = vars(parsed_args)
127 servers = properties.pop('dest', None)
128 path = properties.pop('path', None)
129 if properties['extra'].startswith('\\'):
130 properties['extra'] = properties['extra'][1:]
131 properties['init_directory_structure'] = False
132 properties['rsync_extra_params'] = properties.pop('extra')# + ' --dry-run'
133
134 failed = list()
135 for server in servers:
136 remote = TRsync(server, **properties)
137 try:
138 print "Removing items {}".format(str(path))
139 remote.rm_all(path)
140 except Exception as e:
141 print e.message
142 failed.append(server)
143
144 if failed:
145 print "Failed to remove {}".format(str(failed))
146 sys.exit(1)
147
148class TRsyncApp(App):
149 log = logging.getLogger(__name__)
150
151 def __init__(self):
152 super(TRsyncApp, self).__init__(
153 description='TRsync',
154 version=trsync.__version__,
155 command_manager=CommandManager('trsync'),
156 deferred_help=True,
157 )
158
159def main(argv=sys.argv[1:]):
160 app = TRsyncApp()
161 return app.run(argv)
162
163if __name__ == '__main__':
164 sys.exit(main(sys.argv[1:]))