def rsync_mountpoints(src_inst, src_vol, src_mnt, dst_inst, dst_vol, dst_mnt, encr=False): """Run `rsync` against mountpoints, copy disk label. :param src_inst: source instance; :param src_vol: source volume with label that will be copied to dst_vol; :param src_mnt: root or directory hierarchy to replicate; :param dst_inst: destination instance; :param dst_vol: destination volume, that will be marked with label from src_vol; :param dst_mnt: destination point where source hierarchy to place; :param encr: True if volume is encrypted; :type encr: bool.""" src_key_filename = config.get(src_inst.region.name, 'KEY_FILENAME') dst_key_filename = config.get(dst_inst.region.name, 'KEY_FILENAME') with config_temp_ssh(dst_inst.connection) as key_file: with settings(host_string=dst_inst.public_dns_name, key_filename=dst_key_filename): wait_for_sudo('cp /root/.ssh/authorized_keys ' '/root/.ssh/authorized_keys.bak') pub_key = local('ssh-keygen -y -f {0}'.format(key_file), True) append('/root/.ssh/authorized_keys', pub_key, use_sudo=True) if encr: sudo('screen -d -m sh -c "nc -l 60000 | gzip -dfc | ' 'sudo dd of={0} bs=16M"' .format(get_vol_dev(dst_vol)), pty=False) # dirty magick dst_ip = sudo( 'curl http://169.254.169.254/latest/meta-data/public-ipv4') with settings(host_string=src_inst.public_dns_name, key_filename=src_key_filename): put(key_file, '.ssh/', mirror_local_mode=True) dst_key_filename = os.path.split(key_file)[1] if encr: sudo('(dd if={0} bs=16M | gzip -cf --fast | nc -v {1} 60000)' .format(get_vol_dev(src_vol), dst_ip)) else: cmd = ( 'rsync -e "ssh -i .ssh/{key_file} -o ' 'StrictHostKeyChecking=no" -cahHAX --delete --inplace ' '--exclude /root/.bash_history ' '--exclude /home/*/.bash_history ' '--exclude /etc/ssh/moduli --exclude /etc/ssh/ssh_host_* ' '--exclude /etc/udev/rules.d/*persistent-net.rules ' '--exclude /var/lib/ec2/* --exclude=/mnt/* ' '--exclude=/proc/* --exclude=/tmp/* ' '{src_mnt}/ root@{rhost}:{dst_mnt}') wait_for_sudo(cmd.format( rhost=dst_inst.public_dns_name, dst_mnt=dst_mnt, key_file=dst_key_filename, src_mnt=src_mnt)) label = sudo('e2label {0}'.format(get_vol_dev(src_vol))) with settings(host_string=dst_inst.public_dns_name, key_filename=dst_key_filename): if not encr: sudo('e2label {0} {1}'.format(get_vol_dev(dst_vol), label)) wait_for_sudo('mv /root/.ssh/authorized_keys.bak ' '/root/.ssh/authorized_keys') run('sync', shell=False) run('for i in {1..20}; do sync; sleep 1; done &')
def rsync_mountpoints(src_inst, src_vol, src_mnt, dst_inst, dst_vol, dst_mnt, encr=False): """Run `rsync` against mountpoints, copy disk label. :param src_inst: source instance; :param src_vol: source volume with label that will be copied to dst_vol; :param src_mnt: root or directory hierarchy to replicate; :param dst_inst: destination instance; :param dst_vol: destination volume, that will be marked with label from src_vol; :param dst_mnt: destination point where source hierarchy to place; :param encr: True if volume is encrypted; :type encr: bool.""" src_key_filename = config.get(src_inst.region.name, 'KEY_FILENAME') dst_key_filename = config.get(dst_inst.region.name, 'KEY_FILENAME') with config_temp_ssh(dst_inst.connection) as key_file: with settings(host_string=dst_inst.public_dns_name, key_filename=dst_key_filename): wait_for_sudo('cp /root/.ssh/authorized_keys ' '/root/.ssh/authorized_keys.bak') pub_key = local('ssh-keygen -y -f {0}'.format(key_file), True) append('/root/.ssh/authorized_keys', pub_key, use_sudo=True) if encr: sudo('screen -d -m sh -c "nc -l 60000 | gzip -dfc | ' 'sudo dd of={0} bs=16M"' .format(get_vol_dev(dst_vol)), pty=False) # dirty magick dst_ip = sudo( 'curl http://169.254.169.254/latest/meta-data/public-ipv4') with settings(host_string=src_inst.public_dns_name, key_filename=src_key_filename): put(key_file, '.ssh/', mirror_local_mode=True) dst_key_filename = os.path.split(key_file)[1] if encr: sudo('(dd if={0} bs=16M | gzip -cf --fast | nc -v {1} 60000)' .format(get_vol_dev(src_vol), dst_ip)) else: cmd = ( 'rsync -e "ssh -i .ssh/{key_file} -o ' 'StrictHostKeyChecking=no" -cahHAX --delete --inplace ' '--exclude /root/.bash_history ' '--exclude /home/*/.bash_history ' '--exclude /etc/ssh/moduli --exclude /etc/ssh/ssh_host_* ' '--exclude /etc/udev/rules.d/*persistent-net.rules ' '--exclude /var/lib/ec2/* --exclude=/mnt/* ' '--exclude=/proc/* --exclude=/tmp/* ' '{src_mnt}/ root@{rhost}:{dst_mnt}') wait_for_sudo(cmd.format( rhost=dst_inst.public_dns_name, dst_mnt=dst_mnt, key_file=dst_key_filename, src_mnt=src_mnt)) label = sudo('e2label {0}'.format(get_vol_dev(src_vol))) with settings(host_string=dst_inst.public_dns_name, key_filename=dst_key_filename): if not encr: sudo('e2label {0} {1}'.format(get_vol_dev(dst_vol), label)) wait_for_sudo('mv /root/.ssh/authorized_keys.bak ' '/root/.ssh/authorized_keys') wait_for_sudo('sync', shell=False) wait_for_sudo('for i in {1..20}; do sync; sleep 1; done &')
def create_encrypted_instance( region_name, release='lucid', volume_size='8', architecture=None, type='t1.micro', name='encr_root', pw1=None, pw2=None, security_groups=''): """ Creates ubuntu instance with luks-encryted root volume. region_name Region where you want to create instance; release Ubuntu release name (lucid or natty). "lucid" by default; volume_size Size of volume in Gb (always remember, that script creates boot volume with size 1Gb, so minimal size of whole volume is 3Gb (1Gb for /boot 2Gb for /)). 8 by default; architecture "i386" or "x86_64". type Type of instance. 't1.micro' by default; name Name of luks encrypted volume. 'encr_root' by default; pw1, pw2 You can specify passwords in parameters to suppress password prompt; security_groups List of AWS Security Groups names formatted as string separated with semicolon ';'. To unlock go to https://ip_address_of_instance (only after reboot or shutdown). You can set up to 8 passwords. Defaut boot.key and boot.crt created for .amazonaws.com so must work for all instances. Process of creation is about 20 minutes long.""" assert volume_size >= 3, '1 GiB for /boot and 2 GiB for /' conn = get_region_conn(region_name) with config_temp_ssh(conn) as key_filename: key_pair = os.path.splitext(os.path.split(key_filename)[1])[0] zn = conn.get_all_zones()[-1] with create_temp_inst(zone=zn, key_pair=key_pair) as inst: vol = conn.create_volume(size=volume_size, zone=zn) dev = get_avail_dev_encr(inst) vol.attach(inst.id, dev) arch = architecture or config.get('DEFAULT', 'ARCHITECTURE') ubuntu_arch = 'amd64' if arch == 'x86_64' else arch make_encrypted_ubuntu(inst.public_dns_name, key_filename, 'ubuntu', ubuntu_arch, dev, name, release, pw1, pw2) description = dumps({ 'Volume': vol.id, 'Region': vol.region.name, 'Device': '/dev/sda', 'Type': type, 'Arch': arch, 'Root_dev_name': '/dev/sda1', 'Time': timestamp(), }) snap = vol.create_snapshot(description) wait_for(snap, '100%', limit=SNAP_TIME) vol.detach(force=True) wait_for(vol, 'available', limit=DETACH_TIME) vol.delete() HTTPS_SG = config.get('DEFAULT', 'HTTPS_SECURITY_GROUP') security_groups = ';'.join([security_groups, HTTPS_SG]) img, new_instance = create_ami(region_name, snap.id, 'RUN', security_groups=security_groups) logger.info('\nTo unlock go to:\n https://{0}\n' .format(new_instance.public_dns_name)) img.deregister() snap.delete()
def create_encrypted_instance(region_name, release='lucid', volume_size='8', architecture=None, type='t1.micro', name='encr_root', pw1=None, pw2=None, security_groups=''): """ Creates ubuntu instance with luks-encryted root volume. region_name Region where you want to create instance; release Ubuntu release name (lucid or natty). "lucid" by default; volume_size Size of volume in Gb (always remember, that script creates boot volume with size 1Gb, so minimal size of whole volume is 3Gb (1Gb for /boot 2Gb for /)). 8 by default; architecture "i386" or "x86_64". type Type of instance. 't1.micro' by default; name Name of luks encrypted volume. 'encr_root' by default; pw1, pw2 You can specify passwords in parameters to suppress password prompt; security_groups List of AWS Security Groups names formatted as string separated with semicolon ';'. To unlock go to https://ip_address_of_instance (only after reboot or shutdown). You can set up to 8 passwords. Defaut boot.key and boot.crt created for .amazonaws.com so must work for all instances. Process of creation is about 20 minutes long.""" assert volume_size >= 3, '1 GiB for /boot and 2 GiB for /' conn = get_region_conn(region_name) with config_temp_ssh(conn) as key_filename: key_pair = os.path.splitext(os.path.split(key_filename)[1])[0] zn = conn.get_all_zones()[-1] with create_temp_inst(zone=zn, key_pair=key_pair) as inst: vol = conn.create_volume(size=volume_size, zone=zn) dev = get_avail_dev_encr(inst) vol.attach(inst.id, dev) arch = architecture or config.get('DEFAULT', 'ARCHITECTURE') ubuntu_arch = 'amd64' if arch == 'x86_64' else arch make_encrypted_ubuntu(inst.public_dns_name, key_filename, 'ubuntu', ubuntu_arch, dev, name, release, pw1, pw2) description = dumps({ 'Volume': vol.id, 'Region': vol.region.name, 'Device': '/dev/sda', 'Type': type, 'Arch': arch, 'Root_dev_name': '/dev/sda1', 'Time': timestamp(), }) snap = vol.create_snapshot(description) wait_for(snap, '100%', limit=SNAP_TIME) vol.detach(force=True) wait_for(vol, 'available', limit=DETACH_TIME) vol.delete() HTTPS_SG = config.get('DEFAULT', 'HTTPS_SECURITY_GROUP') security_groups = ';'.join([security_groups, HTTPS_SG]) img, new_instance = create_ami(region_name, snap.id, 'RUN', security_groups=security_groups) logger.info('\nTo unlock go to:\n https://{0}\n'.format( new_instance.public_dns_name)) img.deregister() snap.delete()