diff planemo/lib/python3.7/site-packages/boto/pyami/installers/ubuntu/ebs.py @ 0:d30785e31577 draft

"planemo upload commit 6eee67778febed82ddd413c3ca40b3183a3898f1"
author guerler
date Fri, 31 Jul 2020 00:18:57 -0400
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/planemo/lib/python3.7/site-packages/boto/pyami/installers/ubuntu/ebs.py	Fri Jul 31 00:18:57 2020 -0400
@@ -0,0 +1,238 @@
+# Copyright (c) 2006-2009 Mitch Garnaat http://garnaat.org/
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish, dis-
+# tribute, sublicense, and/or sell copies of the Software, and to permit
+# persons to whom the Software is furnished to do so, subject to the fol-
+# lowing conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
+# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+# IN THE SOFTWARE.
+#
+"""
+Automated installer to attach, format and mount an EBS volume.
+This installer assumes that you want the volume formatted as
+an XFS file system.  To drive this installer, you need the
+following section in the boto config passed to the new instance.
+You also need to install dateutil by listing python-dateutil
+in the list of packages to be installed in the Pyami seciont
+of your boto config file.
+
+If there is already a device mounted at the specified mount point,
+the installer assumes that it is the ephemeral drive and unmounts
+it, remounts it as /tmp and chmods it to 777.
+
+Config file section::
+
+    [EBS]
+    volume_id = <the id of the EBS volume, should look like vol-xxxxxxxx>
+    logical_volume_name = <the name of the logical volume that contaings
+        a reference to the physical volume to be mounted. If this parameter
+        is supplied, it overrides the volume_id setting.>
+    device = <the linux device the EBS volume should be mounted on>
+    mount_point = <directory to mount device, defaults to /ebs>
+
+"""
+import boto
+from boto.manage.volume import Volume
+from boto.exception import EC2ResponseError
+import os, time
+from boto.pyami.installers.ubuntu.installer import Installer
+from string import Template
+
+BackupScriptTemplate = """#!/usr/bin/env python
+# Backup EBS volume
+import boto
+from boto.pyami.scriptbase import ScriptBase
+import traceback
+
+class Backup(ScriptBase):
+
+    def main(self):
+        try:
+            ec2 = boto.connect_ec2()
+            self.run("/usr/sbin/xfs_freeze -f ${mount_point}", exit_on_error = True)
+            snapshot = ec2.create_snapshot('${volume_id}')
+            boto.log.info("Snapshot created: %s " %  snapshot)
+        except Exception as e:
+            self.notify(subject="${instance_id} Backup Failed", body=traceback.format_exc())
+            boto.log.info("Snapshot created: ${volume_id}")
+        except Exception as e:
+            self.notify(subject="${instance_id} Backup Failed", body=traceback.format_exc())
+        finally:
+            self.run("/usr/sbin/xfs_freeze -u ${mount_point}")
+
+if __name__ == "__main__":
+    b = Backup()
+    b.main()
+"""
+
+BackupCleanupScript= """#!/usr/bin/env python
+import boto
+from boto.manage.volume import Volume
+
+# Cleans Backups of EBS volumes
+
+for v in Volume.all():
+    v.trim_snapshots(True)
+"""
+
+TagBasedBackupCleanupScript= """#!/usr/bin/env python
+import boto
+
+# Cleans Backups of EBS volumes
+
+ec2 = boto.connect_ec2()
+ec2.trim_snapshots()
+"""
+
+class EBSInstaller(Installer):
+    """
+    Set up the EBS stuff
+    """
+
+    def __init__(self, config_file=None):
+        super(EBSInstaller, self).__init__(config_file)
+        self.instance_id = boto.config.get('Instance', 'instance-id')
+        self.device = boto.config.get('EBS', 'device', '/dev/sdp')
+        self.volume_id = boto.config.get('EBS', 'volume_id')
+        self.logical_volume_name = boto.config.get('EBS', 'logical_volume_name')
+        self.mount_point = boto.config.get('EBS', 'mount_point', '/ebs')
+
+    def attach(self):
+        ec2 = boto.connect_ec2()
+        if self.logical_volume_name:
+            # if a logical volume was specified, override the specified volume_id
+            # (if there was one) with the current AWS volume for the logical volume:
+            logical_volume = next(Volume.find(name=self.logical_volume_name))
+            self.volume_id = logical_volume._volume_id
+        volume = ec2.get_all_volumes([self.volume_id])[0]
+        # wait for the volume to be available. The volume may still be being created
+        # from a snapshot.
+        while volume.update() != 'available':
+            boto.log.info('Volume %s not yet available. Current status = %s.' % (volume.id, volume.status))
+            time.sleep(5)
+        instance = ec2.get_only_instances([self.instance_id])[0]
+        attempt_attach = True
+        while attempt_attach:
+            try:
+                ec2.attach_volume(self.volume_id, self.instance_id, self.device)
+                attempt_attach = False
+            except EC2ResponseError as e:
+                if e.error_code != 'IncorrectState':
+                    # if there's an EC2ResonseError with the code set to IncorrectState, delay a bit for ec2
+                    # to realize the instance is running, then try again. Otherwise, raise the error:
+                    boto.log.info('Attempt to attach the EBS volume %s to this instance (%s) returned %s. Trying again in a bit.' % (self.volume_id, self.instance_id, e.errors))
+                    time.sleep(2)
+                else:
+                    raise e
+        boto.log.info('Attached volume %s to instance %s as device %s' % (self.volume_id, self.instance_id, self.device))
+        # now wait for the volume device to appear
+        while not os.path.exists(self.device):
+            boto.log.info('%s still does not exist, waiting 2 seconds' % self.device)
+            time.sleep(2)
+
+    def make_fs(self):
+        boto.log.info('make_fs...')
+        has_fs = self.run('fsck %s' % self.device)
+        if has_fs != 0:
+            self.run('mkfs -t xfs %s' % self.device)
+
+    def create_backup_script(self):
+        t = Template(BackupScriptTemplate)
+        s = t.substitute(volume_id=self.volume_id, instance_id=self.instance_id,
+                         mount_point=self.mount_point)
+        fp = open('/usr/local/bin/ebs_backup', 'w')
+        fp.write(s)
+        fp.close()
+        self.run('chmod +x /usr/local/bin/ebs_backup')
+
+    def create_backup_cleanup_script(self, use_tag_based_cleanup=False):
+        fp = open('/usr/local/bin/ebs_backup_cleanup', 'w')
+        if use_tag_based_cleanup:
+            fp.write(TagBasedBackupCleanupScript)
+        else:
+            fp.write(BackupCleanupScript)
+        fp.close()
+        self.run('chmod +x /usr/local/bin/ebs_backup_cleanup')
+
+    def handle_mount_point(self):
+        boto.log.info('handle_mount_point')
+        if not os.path.isdir(self.mount_point):
+            boto.log.info('making directory')
+            # mount directory doesn't exist so create it
+            self.run("mkdir %s" % self.mount_point)
+        else:
+            boto.log.info('directory exists already')
+            self.run('mount -l')
+            lines = self.last_command.output.split('\n')
+            for line in lines:
+                t = line.split()
+                if t and t[2] == self.mount_point:
+                    # something is already mounted at the mount point
+                    # unmount that and mount it as /tmp
+                    if t[0] != self.device:
+                        self.run('umount %s' % self.mount_point)
+                        self.run('mount %s /tmp' % t[0])
+                        break
+        self.run('chmod 777 /tmp')
+        # Mount up our new EBS volume onto mount_point
+        self.run("mount %s %s" % (self.device, self.mount_point))
+        self.run('xfs_growfs %s' % self.mount_point)
+
+    def update_fstab(self):
+        f = open("/etc/fstab", "a")
+        f.write('%s\t%s\txfs\tdefaults 0 0\n' % (self.device, self.mount_point))
+        f.close()
+
+    def install(self):
+        # First, find and attach the volume
+        self.attach()
+
+        # Install the xfs tools
+        self.run('apt-get -y install xfsprogs xfsdump')
+
+        # Check to see if the filesystem was created or not
+        self.make_fs()
+
+        # create the /ebs directory for mounting
+        self.handle_mount_point()
+
+        # create the backup script
+        self.create_backup_script()
+
+        # Set up the backup script
+        minute = boto.config.get('EBS', 'backup_cron_minute', '0')
+        hour = boto.config.get('EBS', 'backup_cron_hour', '4,16')
+        self.add_cron("ebs_backup", "/usr/local/bin/ebs_backup", minute=minute, hour=hour)
+
+        # Set up the backup cleanup script
+        minute = boto.config.get('EBS', 'backup_cleanup_cron_minute')
+        hour = boto.config.get('EBS', 'backup_cleanup_cron_hour')
+        if (minute is not None) and (hour is not None):
+            # Snapshot clean up can either be done via the manage module, or via the new tag based
+            # snapshot code, if the snapshots have been tagged with the name of the associated
+            # volume. Check for the presence of the new configuration flag, and use the appropriate
+            # cleanup method / script:
+            use_tag_based_cleanup = boto.config.has_option('EBS', 'use_tag_based_snapshot_cleanup')
+            self.create_backup_cleanup_script(use_tag_based_cleanup)
+            self.add_cron("ebs_backup_cleanup", "/usr/local/bin/ebs_backup_cleanup", minute=minute, hour=hour)
+
+        # Set up the fstab
+        self.update_fstab()
+
+    def main(self):
+        if not os.path.exists(self.device):
+            self.install()
+        else:
+            boto.log.info("Device %s is already attached, skipping EBS Installer" % self.device)