| OLD | NEW |
| 1 # Copyright (c) 2006-2009 Mitch Garnaat http://garnaat.org/ | 1 # Copyright (c) 2006-2009 Mitch Garnaat http://garnaat.org/ |
| 2 # | 2 # |
| 3 # Permission is hereby granted, free of charge, to any person obtaining a | 3 # Permission is hereby granted, free of charge, to any person obtaining a |
| 4 # copy of this software and associated documentation files (the | 4 # copy of this software and associated documentation files (the |
| 5 # "Software"), to deal in the Software without restriction, including | 5 # "Software"), to deal in the Software without restriction, including |
| 6 # without limitation the rights to use, copy, modify, merge, publish, dis- | 6 # without limitation the rights to use, copy, modify, merge, publish, dis- |
| 7 # tribute, sublicense, and/or sell copies of the Software, and to permit | 7 # tribute, sublicense, and/or sell copies of the Software, and to permit |
| 8 # persons to whom the Software is furnished to do so, subject to the fol- | 8 # persons to whom the Software is furnished to do so, subject to the fol- |
| 9 # lowing conditions: | 9 # lowing conditions: |
| 10 # | 10 # |
| (...skipping 27 matching lines...) Expand all Loading... |
| 38 volume_id = <the id of the EBS volume, should look like vol-xxxxxxxx> | 38 volume_id = <the id of the EBS volume, should look like vol-xxxxxxxx> |
| 39 logical_volume_name = <the name of the logical volume that contaings | 39 logical_volume_name = <the name of the logical volume that contaings |
| 40 a reference to the physical volume to be mounted. If this parameter | 40 a reference to the physical volume to be mounted. If this parameter |
| 41 is supplied, it overrides the volume_id setting.> | 41 is supplied, it overrides the volume_id setting.> |
| 42 device = <the linux device the EBS volume should be mounted on> | 42 device = <the linux device the EBS volume should be mounted on> |
| 43 mount_point = <directory to mount device, defaults to /ebs> | 43 mount_point = <directory to mount device, defaults to /ebs> |
| 44 | 44 |
| 45 """ | 45 """ |
| 46 import boto | 46 import boto |
| 47 from boto.manage.volume import Volume | 47 from boto.manage.volume import Volume |
| 48 from boto.exception import EC2ResponseError |
| 48 import os, time | 49 import os, time |
| 49 from boto.pyami.installers.ubuntu.installer import Installer | 50 from boto.pyami.installers.ubuntu.installer import Installer |
| 50 from string import Template | 51 from string import Template |
| 51 | 52 |
| 52 BackupScriptTemplate = """#!/usr/bin/env python | 53 BackupScriptTemplate = """#!/usr/bin/env python |
| 53 # Backup EBS volume | 54 # Backup EBS volume |
| 54 import boto | 55 import boto |
| 55 from boto.pyami.scriptbase import ScriptBase | 56 from boto.pyami.scriptbase import ScriptBase |
| 56 import traceback | 57 import traceback |
| 57 | 58 |
| 58 class Backup(ScriptBase): | 59 class Backup(ScriptBase): |
| 59 | 60 |
| 60 def main(self): | 61 def main(self): |
| 61 try: | 62 try: |
| 62 ec2 = boto.connect_ec2() | 63 ec2 = boto.connect_ec2() |
| 63 self.run("/usr/sbin/xfs_freeze -f ${mount_point}") | 64 self.run("/usr/sbin/xfs_freeze -f ${mount_point}", exit_on_error = T
rue) |
| 64 snapshot = ec2.create_snapshot('${volume_id}') | 65 snapshot = ec2.create_snapshot('${volume_id}') |
| 65 boto.log.info("Snapshot created: %s " % snapshot) | 66 boto.log.info("Snapshot created: %s " % snapshot) |
| 66 except Exception, e: | 67 except Exception, e: |
| 67 self.notify(subject="${instance_id} Backup Failed", body=traceback.f
ormat_exc()) | 68 self.notify(subject="${instance_id} Backup Failed", body=traceback.f
ormat_exc()) |
| 68 boto.log.info("Snapshot created: ${volume_id}") | 69 boto.log.info("Snapshot created: ${volume_id}") |
| 69 except Exception, e: | 70 except Exception, e: |
| 70 self.notify(subject="${instance_id} Backup Failed", body=traceback.f
ormat_exc()) | 71 self.notify(subject="${instance_id} Backup Failed", body=traceback.f
ormat_exc()) |
| 71 finally: | 72 finally: |
| 72 self.run("/usr/sbin/xfs_freeze -u ${mount_point}") | 73 self.run("/usr/sbin/xfs_freeze -u ${mount_point}") |
| 73 | 74 |
| 74 if __name__ == "__main__": | 75 if __name__ == "__main__": |
| 75 b = Backup() | 76 b = Backup() |
| 76 b.main() | 77 b.main() |
| 77 """ | 78 """ |
| 78 | 79 |
| 79 BackupCleanupScript= """#!/usr/bin/env python | 80 BackupCleanupScript= """#!/usr/bin/env python |
| 80 import boto | 81 import boto |
| 81 from boto.manage.volume import Volume | 82 from boto.manage.volume import Volume |
| 82 | 83 |
| 83 # Cleans Backups of EBS volumes | 84 # Cleans Backups of EBS volumes |
| 84 | 85 |
| 85 for v in Volume.all(): | 86 for v in Volume.all(): |
| 86 v.trim_snapshots(True) | 87 v.trim_snapshots(True) |
| 87 """ | 88 """ |
| 88 | 89 |
| 90 TagBasedBackupCleanupScript= """#!/usr/bin/env python |
| 91 import boto |
| 92 |
| 93 # Cleans Backups of EBS volumes |
| 94 |
| 95 ec2 = boto.connect_ec2() |
| 96 ec2.trim_snapshots() |
| 97 """ |
| 98 |
| 89 class EBSInstaller(Installer): | 99 class EBSInstaller(Installer): |
| 90 """ | 100 """ |
| 91 Set up the EBS stuff | 101 Set up the EBS stuff |
| 92 """ | 102 """ |
| 93 | 103 |
| 94 def __init__(self, config_file=None): | 104 def __init__(self, config_file=None): |
| 95 Installer.__init__(self, config_file) | 105 Installer.__init__(self, config_file) |
| 96 self.instance_id = boto.config.get('Instance', 'instance-id') | 106 self.instance_id = boto.config.get('Instance', 'instance-id') |
| 97 self.device = boto.config.get('EBS', 'device', '/dev/sdp') | 107 self.device = boto.config.get('EBS', 'device', '/dev/sdp') |
| 98 self.volume_id = boto.config.get('EBS', 'volume_id') | 108 self.volume_id = boto.config.get('EBS', 'volume_id') |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 140 | 150 |
| 141 def create_backup_script(self): | 151 def create_backup_script(self): |
| 142 t = Template(BackupScriptTemplate) | 152 t = Template(BackupScriptTemplate) |
| 143 s = t.substitute(volume_id=self.volume_id, instance_id=self.instance_id, | 153 s = t.substitute(volume_id=self.volume_id, instance_id=self.instance_id, |
| 144 mount_point=self.mount_point) | 154 mount_point=self.mount_point) |
| 145 fp = open('/usr/local/bin/ebs_backup', 'w') | 155 fp = open('/usr/local/bin/ebs_backup', 'w') |
| 146 fp.write(s) | 156 fp.write(s) |
| 147 fp.close() | 157 fp.close() |
| 148 self.run('chmod +x /usr/local/bin/ebs_backup') | 158 self.run('chmod +x /usr/local/bin/ebs_backup') |
| 149 | 159 |
| 150 def create_backup_cleanup_script(self): | 160 def create_backup_cleanup_script(self, use_tag_based_cleanup = False): |
| 151 fp = open('/usr/local/bin/ebs_backup_cleanup', 'w') | 161 fp = open('/usr/local/bin/ebs_backup_cleanup', 'w') |
| 152 fp.write(BackupCleanupScript) | 162 if use_tag_based_cleanup: |
| 163 fp.write(TagBasedBackupCleanupScript) |
| 164 else: |
| 165 fp.write(BackupCleanupScript) |
| 153 fp.close() | 166 fp.close() |
| 154 self.run('chmod +x /usr/local/bin/ebs_backup_cleanup') | 167 self.run('chmod +x /usr/local/bin/ebs_backup_cleanup') |
| 155 | 168 |
| 156 def handle_mount_point(self): | 169 def handle_mount_point(self): |
| 157 boto.log.info('handle_mount_point') | 170 boto.log.info('handle_mount_point') |
| 158 if not os.path.isdir(self.mount_point): | 171 if not os.path.isdir(self.mount_point): |
| 159 boto.log.info('making directory') | 172 boto.log.info('making directory') |
| 160 # mount directory doesn't exist so create it | 173 # mount directory doesn't exist so create it |
| 161 self.run("mkdir %s" % self.mount_point) | 174 self.run("mkdir %s" % self.mount_point) |
| 162 else: | 175 else: |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 200 | 213 |
| 201 # Set up the backup script | 214 # Set up the backup script |
| 202 minute = boto.config.get('EBS', 'backup_cron_minute', '0') | 215 minute = boto.config.get('EBS', 'backup_cron_minute', '0') |
| 203 hour = boto.config.get('EBS', 'backup_cron_hour', '4,16') | 216 hour = boto.config.get('EBS', 'backup_cron_hour', '4,16') |
| 204 self.add_cron("ebs_backup", "/usr/local/bin/ebs_backup", minute=minute,
hour=hour) | 217 self.add_cron("ebs_backup", "/usr/local/bin/ebs_backup", minute=minute,
hour=hour) |
| 205 | 218 |
| 206 # Set up the backup cleanup script | 219 # Set up the backup cleanup script |
| 207 minute = boto.config.get('EBS', 'backup_cleanup_cron_minute') | 220 minute = boto.config.get('EBS', 'backup_cleanup_cron_minute') |
| 208 hour = boto.config.get('EBS', 'backup_cleanup_cron_hour') | 221 hour = boto.config.get('EBS', 'backup_cleanup_cron_hour') |
| 209 if (minute != None) and (hour != None): | 222 if (minute != None) and (hour != None): |
| 210 self.create_backup_cleanup_script(); | 223 # Snapshot clean up can either be done via the manage module, or via
the new tag based |
| 224 # snapshot code, if the snapshots have been tagged with the name of
the associated |
| 225 # volume. Check for the presence of the new configuration flag, and
use the appropriate |
| 226 # cleanup method / script: |
| 227 use_tag_based_cleanup = boto.config.has_option('EBS', 'use_tag_based
_snapshot_cleanup') |
| 228 self.create_backup_cleanup_script(use_tag_based_cleanup); |
| 211 self.add_cron("ebs_backup_cleanup", "/usr/local/bin/ebs_backup_clean
up", minute=minute, hour=hour) | 229 self.add_cron("ebs_backup_cleanup", "/usr/local/bin/ebs_backup_clean
up", minute=minute, hour=hour) |
| 212 | 230 |
| 213 # Set up the fstab | 231 # Set up the fstab |
| 214 self.update_fstab() | 232 self.update_fstab() |
| 215 | 233 |
| 216 def main(self): | 234 def main(self): |
| 217 if not os.path.exists(self.device): | 235 if not os.path.exists(self.device): |
| 218 self.install() | 236 self.install() |
| 219 else: | 237 else: |
| 220 boto.log.info("Device %s is already attached, skipping EBS Installer
" % self.device) | 238 boto.log.info("Device %s is already attached, skipping EBS Installer
" % self.device) |
| OLD | NEW |