diff options
Diffstat (limited to 'ssh-rsync.write')
-rwxr-xr-x | ssh-rsync.write | 193 |
1 files changed, 0 insertions, 193 deletions
diff --git a/ssh-rsync.write b/ssh-rsync.write deleted file mode 100755 index fba550cd..00000000 --- a/ssh-rsync.write +++ /dev/null @@ -1,193 +0,0 @@ -#!/usr/bin/python -# Copyright (C) 2013 Codethink Limited -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; version 2 of the License. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - - -'''A Morph deployment write extension for upgrading systems over ssh.''' - - -import cliapp -import os -import sys -import time -import tempfile - -import morphlib.writeexts - -class SshRsyncWriteExtension(morphlib.writeexts.WriteExtension): - - '''Upgrade a running baserock system with ssh and rsync. - - It assumes the system is baserock-based and has a btrfs partition. - - The location command line argument is the 'user@hostname' string - that will be passed to ssh and rsync - - ''' - - def process_args(self, args): - if len(args) != 2: - raise cliapp.AppException('Wrong number of command line args') - - temp_root, location = args - - self.check_valid_target(location) - self.upgrade_remote_system(location, temp_root) - - def upgrade_remote_system(self, location, temp_root): - root_disk = self.find_root_disk(location) - version_label = os.environ.get('VERSION_LABEL') - - try: - self.status(msg='Creating remote mount point') - remote_mnt = cliapp.ssh_runcmd(location, ['mktemp', '-d']).strip() - - self.status(msg='Mounting root disk') - cliapp.ssh_runcmd(location, ['mount', root_disk, remote_mnt]) - - version_root = os.path.join(remote_mnt, 'systems', version_label) - run_dir = os.path.join(version_root, 'run') - orig_dir = os.path.join(version_root, 'orig') - try: - self.status(msg='Creating %s' % version_root) - cliapp.ssh_runcmd(location, ['mkdir', version_root]) - - self.create_remote_orig(location, version_root, remote_mnt, - temp_root) - - self.status(msg='Creating "run" subvolume') - cliapp.ssh_runcmd(location, ['btrfs', 'subvolume', - 'snapshot', orig_dir, run_dir]) - - self.install_remote_kernel(location, version_root, temp_root) - default_path = os.path.join(remote_mnt, 'systems', 'default') - if self.bootloader_is_wanted(): - output = cliapp.ssh_runcmd(location, ['sh', '-c', - 'test -e "$1" && stat -c %F "$1"' - ' || ' - 'echo missing file', - '-', default_path]) - if output != "symbolic link": - # we are upgrading and old system that does - # not have an updated extlinux config file - self.update_remote_extlinux(location, remote_mnt, - version_label) - cliapp.ssh_runcmd(location, ['ln', '-s', '-f', - version_label, - default_path]) - except Exception as e: - try: - cliapp.ssh_runcmd(location, - ['btrfs', 'subvolume', 'delete', run_dir]) - cliapp.ssh_runcmd(location, - ['btrfs', 'subvolume', 'delete', orig_dir]) - cliapp.ssh_runcmd(location, ['rm', '-rf', version_root]) - except: - pass - raise e - - except: - raise - else: - self.status(msg='Removing temporary mounts') - cliapp.ssh_runcmd(location, ['umount', root_disk]) - cliapp.ssh_runcmd(location, ['rmdir', remote_mnt]) - - def update_remote_extlinux(self, location, remote_mnt, version_label): - '''Install/reconfigure extlinux on location''' - - self.status(msg='Creating extlinux.conf') - config = os.path.join(remote_mnt, 'extlinux.conf') - temp_file = tempfile.mkstemp()[1] - with open(temp_file, 'w') as f: - f.write('default linux\n') - f.write('timeout 1\n') - f.write('label linux\n') - f.write('kernel /systems/default/kernel\n') - f.write('append root=/dev/sda ' - 'rootflags=subvol=systems/default/run ' - 'init=/sbin/init rw\n') - - cliapp.ssh_runcmd(location, ['mv', config, config+'~']) - - try: - cliapp.runcmd(['rsync', '-as', temp_file, - '%s:%s' % (location, config)]) - except Exception as e: - try: - cliapp.ssh_runcmd(location, ['mv', config+'~', config]) - except: - pass - raise e - - def create_remote_orig(self, location, version_root, remote_mnt, - temp_root): - '''Create the subvolume version_root/orig on location''' - - self.status(msg='Creating "orig" subvolume') - old_orig = self.get_old_orig(location, remote_mnt) - new_orig = os.path.join(version_root, 'orig') - cliapp.ssh_runcmd(location, ['btrfs', 'subvolume', 'snapshot', - old_orig, new_orig]) - - cliapp.runcmd(['rsync', '-as', '--checksum', '--numeric-ids', - '--delete', temp_root, '%s:%s' % (location, new_orig)]) - - def get_old_orig(self, location, remote_mnt): - '''Identify which subvolume to snapshot from''' - - # rawdisk upgrades use 'factory' - return os.path.join(remote_mnt, 'systems', 'factory', 'orig') - - def find_root_disk(self, location): - '''Read /proc/mounts on location to find which device contains "/"''' - - self.status(msg='Finding device that contains "/"') - contents = cliapp.ssh_runcmd(location, ['cat', '/proc/mounts']) - for line in contents.splitlines(): - line_words = line.split() - if (line_words[1] == '/' and line_words[0] != 'rootfs'): - return line_words[0] - - def install_remote_kernel(self, location, version_root, temp_root): - '''Install the kernel in temp_root inside version_root on location''' - - self.status(msg='Installing kernel') - image_names = ['vmlinuz', 'zImage', 'uImage'] - kernel_dest = os.path.join(version_root, 'kernel') - for name in image_names: - try_path = os.path.join(temp_root, 'boot', name) - if os.path.exists(try_path): - cliapp.runcmd(['rsync', '-as', try_path, - '%s:%s' % (location, kernel_dest)]) - - def check_valid_target(self, location): - try: - cliapp.ssh_runcmd(location, ['true']) - except Exception as e: - raise cliapp.AppException('%s does not respond to ssh:\n%s' - % (location, e)) - - try: - cliapp.ssh_runcmd(location, ['test', '-d', '/baserock']) - except: - raise cliapp.AppException('%s is not a baserock system' % location) - - try: - cliapp.ssh_runcmd(location, ['which', 'rsync']) - except: - raise cliapp.AppException('%s does not have rsync') - -SshRsyncWriteExtension().run() |