comparison 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
comparison
equal deleted inserted replaced
-1:000000000000 0:d30785e31577
1 # Copyright (c) 2006-2009 Mitch Garnaat http://garnaat.org/
2 #
3 # Permission is hereby granted, free of charge, to any person obtaining a
4 # copy of this software and associated documentation files (the
5 # "Software"), to deal in the Software without restriction, including
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
8 # persons to whom the Software is furnished to do so, subject to the fol-
9 # lowing conditions:
10 #
11 # The above copyright notice and this permission notice shall be included
12 # in all copies or substantial portions of the Software.
13 #
14 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
16 # ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
17 # SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
20 # IN THE SOFTWARE.
21 #
22 """
23 Automated installer to attach, format and mount an EBS volume.
24 This installer assumes that you want the volume formatted as
25 an XFS file system. To drive this installer, you need the
26 following section in the boto config passed to the new instance.
27 You also need to install dateutil by listing python-dateutil
28 in the list of packages to be installed in the Pyami seciont
29 of your boto config file.
30
31 If there is already a device mounted at the specified mount point,
32 the installer assumes that it is the ephemeral drive and unmounts
33 it, remounts it as /tmp and chmods it to 777.
34
35 Config file section::
36
37 [EBS]
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
40 a reference to the physical volume to be mounted. If this parameter
41 is supplied, it overrides the volume_id setting.>
42 device = <the linux device the EBS volume should be mounted on>
43 mount_point = <directory to mount device, defaults to /ebs>
44
45 """
46 import boto
47 from boto.manage.volume import Volume
48 from boto.exception import EC2ResponseError
49 import os, time
50 from boto.pyami.installers.ubuntu.installer import Installer
51 from string import Template
52
53 BackupScriptTemplate = """#!/usr/bin/env python
54 # Backup EBS volume
55 import boto
56 from boto.pyami.scriptbase import ScriptBase
57 import traceback
58
59 class Backup(ScriptBase):
60
61 def main(self):
62 try:
63 ec2 = boto.connect_ec2()
64 self.run("/usr/sbin/xfs_freeze -f ${mount_point}", exit_on_error = True)
65 snapshot = ec2.create_snapshot('${volume_id}')
66 boto.log.info("Snapshot created: %s " % snapshot)
67 except Exception as e:
68 self.notify(subject="${instance_id} Backup Failed", body=traceback.format_exc())
69 boto.log.info("Snapshot created: ${volume_id}")
70 except Exception as e:
71 self.notify(subject="${instance_id} Backup Failed", body=traceback.format_exc())
72 finally:
73 self.run("/usr/sbin/xfs_freeze -u ${mount_point}")
74
75 if __name__ == "__main__":
76 b = Backup()
77 b.main()
78 """
79
80 BackupCleanupScript= """#!/usr/bin/env python
81 import boto
82 from boto.manage.volume import Volume
83
84 # Cleans Backups of EBS volumes
85
86 for v in Volume.all():
87 v.trim_snapshots(True)
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
99 class EBSInstaller(Installer):
100 """
101 Set up the EBS stuff
102 """
103
104 def __init__(self, config_file=None):
105 super(EBSInstaller, self).__init__(config_file)
106 self.instance_id = boto.config.get('Instance', 'instance-id')
107 self.device = boto.config.get('EBS', 'device', '/dev/sdp')
108 self.volume_id = boto.config.get('EBS', 'volume_id')
109 self.logical_volume_name = boto.config.get('EBS', 'logical_volume_name')
110 self.mount_point = boto.config.get('EBS', 'mount_point', '/ebs')
111
112 def attach(self):
113 ec2 = boto.connect_ec2()
114 if self.logical_volume_name:
115 # if a logical volume was specified, override the specified volume_id
116 # (if there was one) with the current AWS volume for the logical volume:
117 logical_volume = next(Volume.find(name=self.logical_volume_name))
118 self.volume_id = logical_volume._volume_id
119 volume = ec2.get_all_volumes([self.volume_id])[0]
120 # wait for the volume to be available. The volume may still be being created
121 # from a snapshot.
122 while volume.update() != 'available':
123 boto.log.info('Volume %s not yet available. Current status = %s.' % (volume.id, volume.status))
124 time.sleep(5)
125 instance = ec2.get_only_instances([self.instance_id])[0]
126 attempt_attach = True
127 while attempt_attach:
128 try:
129 ec2.attach_volume(self.volume_id, self.instance_id, self.device)
130 attempt_attach = False
131 except EC2ResponseError as e:
132 if e.error_code != 'IncorrectState':
133 # if there's an EC2ResonseError with the code set to IncorrectState, delay a bit for ec2
134 # to realize the instance is running, then try again. Otherwise, raise the error:
135 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))
136 time.sleep(2)
137 else:
138 raise e
139 boto.log.info('Attached volume %s to instance %s as device %s' % (self.volume_id, self.instance_id, self.device))
140 # now wait for the volume device to appear
141 while not os.path.exists(self.device):
142 boto.log.info('%s still does not exist, waiting 2 seconds' % self.device)
143 time.sleep(2)
144
145 def make_fs(self):
146 boto.log.info('make_fs...')
147 has_fs = self.run('fsck %s' % self.device)
148 if has_fs != 0:
149 self.run('mkfs -t xfs %s' % self.device)
150
151 def create_backup_script(self):
152 t = Template(BackupScriptTemplate)
153 s = t.substitute(volume_id=self.volume_id, instance_id=self.instance_id,
154 mount_point=self.mount_point)
155 fp = open('/usr/local/bin/ebs_backup', 'w')
156 fp.write(s)
157 fp.close()
158 self.run('chmod +x /usr/local/bin/ebs_backup')
159
160 def create_backup_cleanup_script(self, use_tag_based_cleanup=False):
161 fp = open('/usr/local/bin/ebs_backup_cleanup', 'w')
162 if use_tag_based_cleanup:
163 fp.write(TagBasedBackupCleanupScript)
164 else:
165 fp.write(BackupCleanupScript)
166 fp.close()
167 self.run('chmod +x /usr/local/bin/ebs_backup_cleanup')
168
169 def handle_mount_point(self):
170 boto.log.info('handle_mount_point')
171 if not os.path.isdir(self.mount_point):
172 boto.log.info('making directory')
173 # mount directory doesn't exist so create it
174 self.run("mkdir %s" % self.mount_point)
175 else:
176 boto.log.info('directory exists already')
177 self.run('mount -l')
178 lines = self.last_command.output.split('\n')
179 for line in lines:
180 t = line.split()
181 if t and t[2] == self.mount_point:
182 # something is already mounted at the mount point
183 # unmount that and mount it as /tmp
184 if t[0] != self.device:
185 self.run('umount %s' % self.mount_point)
186 self.run('mount %s /tmp' % t[0])
187 break
188 self.run('chmod 777 /tmp')
189 # Mount up our new EBS volume onto mount_point
190 self.run("mount %s %s" % (self.device, self.mount_point))
191 self.run('xfs_growfs %s' % self.mount_point)
192
193 def update_fstab(self):
194 f = open("/etc/fstab", "a")
195 f.write('%s\t%s\txfs\tdefaults 0 0\n' % (self.device, self.mount_point))
196 f.close()
197
198 def install(self):
199 # First, find and attach the volume
200 self.attach()
201
202 # Install the xfs tools
203 self.run('apt-get -y install xfsprogs xfsdump')
204
205 # Check to see if the filesystem was created or not
206 self.make_fs()
207
208 # create the /ebs directory for mounting
209 self.handle_mount_point()
210
211 # create the backup script
212 self.create_backup_script()
213
214 # Set up the backup script
215 minute = boto.config.get('EBS', 'backup_cron_minute', '0')
216 hour = boto.config.get('EBS', 'backup_cron_hour', '4,16')
217 self.add_cron("ebs_backup", "/usr/local/bin/ebs_backup", minute=minute, hour=hour)
218
219 # Set up the backup cleanup script
220 minute = boto.config.get('EBS', 'backup_cleanup_cron_minute')
221 hour = boto.config.get('EBS', 'backup_cleanup_cron_hour')
222 if (minute is not None) and (hour is not None):
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)
229 self.add_cron("ebs_backup_cleanup", "/usr/local/bin/ebs_backup_cleanup", minute=minute, hour=hour)
230
231 # Set up the fstab
232 self.update_fstab()
233
234 def main(self):
235 if not os.path.exists(self.device):
236 self.install()
237 else:
238 boto.log.info("Device %s is already attached, skipping EBS Installer" % self.device)