Example #1
0
def _get_attached_volumes(connection, instance_id=None):
  """Returns all the volumes that are attached to a particular instance.
  Alternatively, this function could've been a generator with the
  yield keyword."""
  if not instance_id:
    instance_id = common.get_self_instance_id()

  volumes = connection.get_all_volumes()
  attached_volumes = []
  for volume in volumes:
    if (volume.attach_data.instance_id == instance_id and
      volume.attachment_state() == "attached"):
      attached_volumes.append(volume)
  return attached_volumes
Example #2
0
def _email(subject, body):
  """Sends an email to _EMAIL_RECIPIENT with useful debugging info."""
  if not _EMAIL_RECIPIENT:
    return
  if not _EMAIL_SENDER:
    return
  message_content = "Backup script message!<br/>"
  message_content += "from instance id {}<br/>--<br/><br/>".format(
    common.get_self_instance_id())
  message_content += body
  message = email.mime.text.MIMEText(message_content, "html")
  message['From'] = _EMAIL_SENDER
  message['Subject'] = subject
  message['To'] = _EMAIL_RECIPIENT
  logging.info("Sending email to {}: {}".format(_EMAIL_RECIPIENT, subject))
  smtp = smtplib.SMTP("127.0.0.1")
  smtp.sendmail(_EMAIL_SENDER, [_EMAIL_RECIPIENT], message.as_string())
  smtp.quit()
Example #3
0
def main():  # pylint: disable=R0914
  _log("Running backup script. It is now {}".format(
    datetime.datetime.now().strftime(_DATETIME_FORMAT)))

  config = _load_config()
  connection = common.connect()

  self_instance_id = common.get_self_instance_id()
  self_instance = common.get_self_instance(connection)
  self_instance_name = (self_instance.tags['Name'] if 'Name' in
                        self_instance.tags else self_instance_id)
  attached_volumes = _get_attached_volumes(connection, self_instance_id)
  mounted_storages = _get_mounted_storages()
  freezer = Freezer()

  for name, rules in config.iteritems():
    try:
      path = rules['path']
      if rules['path'] not in mounted_storages:
        raise Exception("Cannot find mount for {}".format(path))

      extra_description = (rules['description'] if 'description' in rules
                           else "")
      storage = mounted_storages[path]

      _run_before_commands(rules)

      volume_ids = []
      for device in storage.devices:
        volume = _get_volume_used_by_device(device, attached_volumes)
        if not volume:
          raise Exception("Cannot find volume attached to {}".format(
          device))
        volume_ids.append({
          "device": device,
          "volume_id": volume.id,
        })

      _log("Preparing to back up {}".format(storage.mount_point))
      freezer.freeze(storage)
      for timing_rule in _TIMING_MAP:
        if timing_rule in rules:
          snapshots = _get_snapshots(connection, self_instance_name,
            timing_rule)
          if len(snapshots):
            # Check if we already took a recent snapshot for this duration
            most_recent_dt_string = snapshots[0].tags['Backup-Datetime']
            most_recent_dt = datetime.datetime.strptime(most_recent_dt_string,
              _DATETIME_FORMAT)
            now_dt = datetime.datetime.now()
            duration_between_backups = _TIMING_MAP[timing_rule]
            if now_dt - most_recent_dt < duration_between_backups:
              _log("Not snapshotting {} / {} because it's too soon.".format(
                name, timing_rule))
              continue

          for vol_and_device in volume_ids:
            volume_id = vol_and_device['volume_id']
            device = vol_and_device['device']

            snap_datetime = datetime.datetime.now().strftime(_DATETIME_FORMAT)
            full_desc = _build_full_description(name, self_instance_id,
              snap_datetime, timing_rule, storage, device,
              extra_description)
            short_name = " ".join([self_instance_name, timing_rule,
              device.replace("/dev/", ""), snap_datetime])

            _snapshot_volume(connection, volume_id, full_desc, {
              'Name': short_name,
              'Backup-Datetime': snap_datetime,
              'Backup-Device': device,
              'Backup-Instance-Name': self_instance_name,
              'Backup-Type': timing_rule
            })

            _delete_old_snapshots(connection, snapshots, timing_rule, device,
                                  int(rules[timing_rule]))

      freezer.unfreeze(storage)

      _run_after_commands(rules)

    except Exception, err:
      _error(err)
    finally: