OLD | NEW |
(Empty) | |
| 1 #!/usr/bin/env python |
| 2 # Copyright (c) 2009 Chris Moyer http://kopertop.blogspot.com/ |
| 3 # |
| 4 # Permission is hereby granted, free of charge, to any person obtaining a |
| 5 # copy of this software and associated documentation files (the |
| 6 # "Software"), to deal in the Software without restriction, including |
| 7 # without limitation the rights to use, copy, modify, merge, publish, dis- |
| 8 # tribute, sublicense, and/or sell copies of the Software, and to permit |
| 9 # persons to whom the Software is furnished to do so, subject to the fol- |
| 10 # lowing conditions: |
| 11 # |
| 12 # The above copyright notice and this permission notice shall be included |
| 13 # in all copies or substantial portions of the Software. |
| 14 # |
| 15 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
| 16 # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- |
| 17 # ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT |
| 18 # SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, |
| 19 # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| 20 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS |
| 21 |
| 22 # |
| 23 # Tools to dump and recover an SDB domain |
| 24 # |
| 25 VERSION = "%prog version 1.0" |
| 26 import boto |
| 27 import time |
| 28 from boto import sdb |
| 29 |
| 30 # Allow support for JSON |
| 31 try: |
| 32 import simplejson as json |
| 33 except: |
| 34 try: |
| 35 import json |
| 36 except: |
| 37 json = False |
| 38 |
| 39 def choice_input(options, default=None, title=None): |
| 40 """ |
| 41 Choice input |
| 42 """ |
| 43 if title == None: |
| 44 title = "Please choose" |
| 45 print title |
| 46 objects = [] |
| 47 for n, obj in enumerate(options): |
| 48 print "%s: %s" % (n, obj) |
| 49 objects.append(obj) |
| 50 choice = int(raw_input(">>> ")) |
| 51 try: |
| 52 choice = objects[choice] |
| 53 except: |
| 54 choice = default |
| 55 return choice |
| 56 |
| 57 def confirm(message="Are you sure?"): |
| 58 choice = raw_input("%s [yN] " % message) |
| 59 return choice and len(choice) > 0 and choice[0].lower() == "y" |
| 60 |
| 61 |
| 62 def dump_db(domain, file_name, use_json=False): |
| 63 """ |
| 64 Dump SDB domain to file |
| 65 """ |
| 66 f = open(file_name, "w") |
| 67 if use_json: |
| 68 for item in domain: |
| 69 data = {"name": item.name, "attributes": item} |
| 70 print >> f, json.dumps(data) |
| 71 else: |
| 72 doc = domain.to_xml(f) |
| 73 |
| 74 def empty_db(domain): |
| 75 """ |
| 76 Remove all entries from domain |
| 77 """ |
| 78 for item in domain: |
| 79 item.delete() |
| 80 |
| 81 def load_db(domain, file, use_json=False): |
| 82 """ |
| 83 Load a domain from a file, this doesn't overwrite any existing |
| 84 data in the file so if you want to do a full recovery and restore |
| 85 you need to call empty_db before calling this |
| 86 |
| 87 :param domain: The SDB Domain object to load to |
| 88 :param file: The File to load the DB from |
| 89 """ |
| 90 if use_json: |
| 91 for line in file.readlines(): |
| 92 if line: |
| 93 data = json.loads(line) |
| 94 item = domain.new_item(data['name']) |
| 95 item.update(data['attributes']) |
| 96 item.save() |
| 97 |
| 98 else: |
| 99 domain.from_xml(file) |
| 100 |
| 101 def create_db(domain_name, region_name): |
| 102 """Create a new DB |
| 103 |
| 104 :param domain: Name of the domain to create |
| 105 :type domain: str |
| 106 """ |
| 107 sdb = boto.sdb.connect_to_region(region_name) |
| 108 return sdb.create_domain(domain_name) |
| 109 |
| 110 if __name__ == "__main__": |
| 111 from optparse import OptionParser |
| 112 parser = OptionParser(version=VERSION, usage="Usage: %prog [--dump|--load|--
empty|--list|-l] [options]") |
| 113 |
| 114 # Commands |
| 115 parser.add_option("--dump", help="Dump domain to file", dest="dump", default
=False, action="store_true") |
| 116 parser.add_option("--load", help="Load domain contents from file", dest="loa
d", default=False, action="store_true") |
| 117 parser.add_option("--empty", help="Empty all contents of domain", dest="empt
y", default=False, action="store_true") |
| 118 parser.add_option("-l", "--list", help="List All domains", dest="list", defa
ult=False, action="store_true") |
| 119 parser.add_option("-c", "--create", help="Create domain", dest="create", def
ault=False, action="store_true") |
| 120 |
| 121 parser.add_option("-a", "--all-domains", help="Operate on all domains", acti
on="store_true", default=False, dest="all_domains") |
| 122 if json: |
| 123 parser.add_option("-j", "--use-json", help="Load/Store as JSON instead o
f XML", action="store_true", default=False, dest="json") |
| 124 parser.add_option("-d", "--domain", help="Do functions on domain (may be mor
e then one)", action="append", dest="domains") |
| 125 parser.add_option("-f", "--file", help="Input/Output file we're operating on
", dest="file_name") |
| 126 parser.add_option("-r", "--region", help="Region (e.g. us-east-1[default] or
eu-west-1)", default="us-east-1", dest="region_name") |
| 127 (options, args) = parser.parse_args() |
| 128 |
| 129 if options.create: |
| 130 for domain_name in options.domains: |
| 131 create_db(domain_name, options.region_name) |
| 132 exit() |
| 133 |
| 134 sdb = boto.sdb.connect_to_region(options.region_name) |
| 135 if options.list: |
| 136 for db in sdb.get_all_domains(): |
| 137 print db |
| 138 exit() |
| 139 |
| 140 if not options.dump and not options.load and not options.empty: |
| 141 parser.print_help() |
| 142 exit() |
| 143 |
| 144 |
| 145 |
| 146 |
| 147 # |
| 148 # Setup |
| 149 # |
| 150 if options.domains: |
| 151 domains = [] |
| 152 for domain_name in options.domains: |
| 153 domains.append(sdb.get_domain(domain_name)) |
| 154 elif options.all_domains: |
| 155 domains = sdb.get_all_domains() |
| 156 else: |
| 157 domains = [choice_input(options=sdb.get_all_domains(), title="No domain
specified, please choose one")] |
| 158 |
| 159 |
| 160 # |
| 161 # Execute the commands |
| 162 # |
| 163 stime = time.time() |
| 164 if options.empty: |
| 165 if confirm("WARNING!!! Are you sure you want to empty the following doma
ins?: %s" % domains): |
| 166 stime = time.time() |
| 167 for domain in domains: |
| 168 print "--------> Emptying %s <--------" % domain.name |
| 169 empty_db(domain) |
| 170 else: |
| 171 print "Canceling operations" |
| 172 exit() |
| 173 |
| 174 if options.dump: |
| 175 for domain in domains: |
| 176 print "--------> Dumping %s <---------" % domain.name |
| 177 if options.file_name: |
| 178 file_name = options.file_name |
| 179 else: |
| 180 file_name = "%s.db" % domain.name |
| 181 dump_db(domain, file_name, options.json) |
| 182 |
| 183 if options.load: |
| 184 for domain in domains: |
| 185 print "---------> Loading %s <----------" % domain.name |
| 186 if options.file_name: |
| 187 file_name = options.file_name |
| 188 else: |
| 189 file_name = "%s.db" % domain.name |
| 190 load_db(domain, open(file_name, "rb"), options.json) |
| 191 |
| 192 |
| 193 total_time = round(time.time() - stime, 2) |
| 194 print "--------> Finished in %s <--------" % total_time |
OLD | NEW |