From 8f24fc7d0b65f04a9009dda9bad193458c2d5813 Mon Sep 17 00:00:00 2001 From: Ian Date: Mon, 26 Feb 2018 13:03:52 +0100 Subject: [PATCH 1/3] deploy script will check if the programs are installed before prompting for the robots IP --- deploy.py | 102 +++++++++++++++++++++++++++++++++--------------------- 1 file changed, 63 insertions(+), 39 deletions(-) diff --git a/deploy.py b/deploy.py index b25ceca..30ec259 100755 --- a/deploy.py +++ b/deploy.py @@ -32,7 +32,7 @@ # our imports import tmuxify -from ip_check import * +from ip_check import ip_check __author__ = 'Paul Genssler and Lutz Thies' __copyright__ = 'Copyright (c) 2017' @@ -61,20 +61,6 @@ def __init__(self, settings): self.pscp = os.path.join(bin_path, 'pscp.exe') self.putty = os.path.join(bin_path, 'putty.exe') - # check for pscp - if not os.path.exists(self.pscp): - url = ROBOLAB_SERVER + 'pscp.exe' - with urllib.request.urlopen(url) as download,\ - open(self.pscp, 'wb') as file: - file.write(download.read()) - - # check for putty - if not os.path.exists(self.putty): - url = ROBOLAB_SERVER + 'putty.exe' - with urllib.request.urlopen(url) as download,\ - open(self.putty, 'wb') as file: - file.write(download.read()) - # check for the backup command self.backupfile = os.path.join(bin_path, 'backup.txt') if not os.path.exists(self.backupfile): @@ -109,6 +95,28 @@ def execute(): os.path.join(bin_path, 'exec.txt'), '-t']) print('Done') + @staticmethod + def install(): + check_internet() + pscp = os.path.join(bin_path, 'pscp.exe') + putty = os.path.join(bin_path, 'putty.exe') + + # check for pscp + if not os.path.exists(pscp): + url = ROBOLAB_SERVER + 'pscp.exe' + with urllib.request.urlopen(url) as download,\ + open(pscp, 'wb') as file: + file.write(download.read()) + + # check for putty + if not os.path.exists(putty): + url = ROBOLAB_SERVER + 'putty.exe' + with urllib.request.urlopen(url) as download,\ + open(putty, 'wb') as file: + file.write(download.read()) + + + class Unix: @@ -122,12 +130,40 @@ def __init__(self, settings): with open(self.backupfile, 'w') as new_backup: new_backup.write(raw_backup.format('#!/usr/bin/env bash\n\n')) + @staticmethod + def backup(): + with open(os.path.join(bin_path, 'backup.sh'), 'r') as backupinput: + subprocess.call(['sshpass', '-p', settings['password'], 'ssh', '-o', + 'StrictHostKeyChecking=no', 'robot@{}'.format( + settings['ip']), 'bash'], + stdin=backupinput) + print('Done') + + @staticmethod + def copy_files(): + subprocess.call(['sshpass', '-p', settings['password'], 'scp', '-o', + 'StrictHostKeyChecking=no', '-r', + os.path.join(src_path), + 'robot@{}:/home/robot/'.format( + settings['ip'])]) + print('Done') + + @staticmethod + def execute(): + subprocess.call(['sshpass', '-p', settings['password'], + 'ssh','robot@{}'.format(settings['ip']), '-t', + tmuxify.build_call(settings['password'])]) + print('Done') + + @staticmethod + def install(): + check_internet() # check for sshpass try: with open(os.devnull, 'w') as devnull: subprocess.call(['sshpass', '-V'], stdout=devnull) except FileNotFoundError: - if settings['os'] == 'Darwin': + if "darwin" in sys.platform: try: print('Installing sshpass') with open(os.devnull, 'w') as devnull: @@ -150,30 +186,7 @@ def __init__(self, settings): https://gist.github.com/arunoda/7790979''') sys.exit(1) - @staticmethod - def backup(): - with open(os.path.join(bin_path, 'backup.sh'), 'r') as backupinput: - subprocess.call(['sshpass', '-p', settings['password'], 'ssh', '-o', - 'StrictHostKeyChecking=no', 'robot@{}'.format( - settings['ip']), 'bash'], - stdin=backupinput) - print('Done') - - @staticmethod - def copy_files(): - subprocess.call(['sshpass', '-p', settings['password'], 'scp', '-o', - 'StrictHostKeyChecking=no', '-r', - os.path.join(src_path), - 'robot@{}:/home/robot/'.format( - settings['ip'])]) - print('Done') - @staticmethod - def execute(): - subprocess.call(['sshpass', '-p', settings['password'], - 'ssh','robot@{}'.format(settings['ip']), '-t', - tmuxify.build_call(settings['password'])]) - print('Done') def main(copy=True, backup=False): @@ -202,10 +215,20 @@ def main(copy=True, backup=False): system.execute() +def check_internet(): + try: + urllib.request.urlopen("http://google.com", timeout=1) + except urllib.request.URLError: + print("You will need to be connected to the internet!") + sys.exit(1) + + def first_start(): """ Asks the user for necessary information and stores it """ + global settings + Windows.install() if "win" in sys.platform else Unix.install() init_dict = dict() init_dict['os'] = platform.system() init_dict['ip'] = ip_check() @@ -220,6 +243,7 @@ def abort(signal, frame): print('\rJob canceled by user!') sys.exit(0) + signal.signal(signal.SIGINT, abort) raw_backup = '''{}if [ ! -d ~/src ] From eb3a299a935a24b6b57d4ff4511ace421375e92d Mon Sep 17 00:00:00 2001 From: Ian Date: Mon, 26 Feb 2018 16:31:21 +0100 Subject: [PATCH 2/3] Added the update flag, so that freshmen could potentially update the deploy script from within the other deploy script --- deploy.py | 68 ++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 42 insertions(+), 26 deletions(-) diff --git a/deploy.py b/deploy.py index 30ec259..dd69bd1 100755 --- a/deploy.py +++ b/deploy.py @@ -24,6 +24,7 @@ import os import sys import json +import shutil import signal import platform import subprocess @@ -46,10 +47,10 @@ # static global variables ROBOLAB_SERVER = 'http://robolab.inf.tu-dresden.de/files/' -home = os.path.dirname(os.path.abspath(__file__)) -src_path = os.path.join(os.path.abspath(os.path.join(home, os.pardir)), 'src') -settings_path = os.path.join(home, '.bin', 'settings.json') -bin_path = os.path.join(home, '.bin') +HOME = os.path.dirname(os.path.abspath(__file__)) +SRC_PATH = os.path.join(os.path.abspath(os.path.join(HOME, os.pardir)), 'src') +SETTINGS_PATH = os.path.join(HOME, '.bin', 'settings.json') +BIN_PATH = os.path.join(HOME, '.bin') settings = dict() @@ -58,48 +59,48 @@ class Windows: def __init__(self, settings): self.ip = settings['ip'] self.password = settings['password'] - self.pscp = os.path.join(bin_path, 'pscp.exe') - self.putty = os.path.join(bin_path, 'putty.exe') + self.pscp = os.path.join(BIN_PATH, 'pscp.exe') + self.putty = os.path.join(BIN_PATH, 'putty.exe') # check for the backup command - self.backupfile = os.path.join(bin_path, 'backup.txt') + self.backupfile = os.path.join(BIN_PATH, 'backup.txt') if not os.path.exists(self.backupfile): with open(self.backupfile, 'w') as new_backup: new_backup.write(raw_backup.format('')) # check the file containing the command that will be executed - self.execfile = os.path.join(bin_path, 'exec.txt') + self.execfile = os.path.join(BIN_PATH, 'exec.txt') with open(self.execfile, 'w') as new_exec: new_exec.write(tmuxify.build_call(settings['password'])) @staticmethod def backup(): - subprocess.call([os.path.join(bin_path, 'putty.exe'), '-pw', + subprocess.call([os.path.join(BIN_PATH, 'putty.exe'), '-pw', settings['password'], '-ssh', 'robot@{}'.format(settings['ip']), '-m', - os.path.join(bin_path, 'backup.txt'), '-t']) + os.path.join(BIN_PATH, 'backup.txt'), '-t']) print('Done') @staticmethod def copy_files(): - subprocess.call([os.path.join(bin_path, 'pscp.exe'), '-pw', - settings['password'], '-r', src_path, + subprocess.call([os.path.join(BIN_PATH, 'pscp.exe'), '-pw', + settings['password'], '-r', SRC_PATH, 'robot@{ip}:/home/robot/'.format(ip=settings['ip'])]) print('Done') @staticmethod def execute(): - subprocess.call([os.path.join(bin_path, 'putty.exe'), '-pw', + subprocess.call([os.path.join(BIN_PATH, 'putty.exe'), '-pw', settings['password'], '-ssh', 'robot@{}'.format(settings['ip']), '-m', - os.path.join(bin_path, 'exec.txt'), '-t']) + os.path.join(BIN_PATH, 'exec.txt'), '-t']) print('Done') @staticmethod def install(): check_internet() - pscp = os.path.join(bin_path, 'pscp.exe') - putty = os.path.join(bin_path, 'putty.exe') + pscp = os.path.join(BIN_PATH, 'pscp.exe') + putty = os.path.join(BIN_PATH, 'putty.exe') # check for pscp if not os.path.exists(pscp): @@ -125,14 +126,14 @@ def __init__(self, settings): self.password = settings['password'] # check for backup.sh - self.backupfile = os.path.join(bin_path, 'backup.sh') + self.backupfile = os.path.join(BIN_PATH, 'backup.sh') if not os.path.exists(self.backupfile): with open(self.backupfile, 'w') as new_backup: new_backup.write(raw_backup.format('#!/usr/bin/env bash\n\n')) @staticmethod def backup(): - with open(os.path.join(bin_path, 'backup.sh'), 'r') as backupinput: + with open(os.path.join(BIN_PATH, 'backup.sh'), 'r') as backupinput: subprocess.call(['sshpass', '-p', settings['password'], 'ssh', '-o', 'StrictHostKeyChecking=no', 'robot@{}'.format( settings['ip']), 'bash'], @@ -143,7 +144,7 @@ def backup(): def copy_files(): subprocess.call(['sshpass', '-p', settings['password'], 'scp', '-o', 'StrictHostKeyChecking=no', '-r', - os.path.join(src_path), + os.path.join(SRC_PATH), 'robot@{}:/home/robot/'.format( settings['ip'])]) print('Done') @@ -192,9 +193,9 @@ def install(): def main(copy=True, backup=False): # get the settings or create new ones global settings - if not os.path.exists(settings_path): + if not os.path.exists(SETTINGS_PATH): first_start() - with open(settings_path) as file: + with open(SETTINGS_PATH) as file: settings = json.load(file) # get the platform specific routines @@ -220,7 +221,9 @@ def check_internet(): urllib.request.urlopen("http://google.com", timeout=1) except urllib.request.URLError: print("You will need to be connected to the internet!") - sys.exit(1) + print("Please connect to a wifi with an internet connection to download") + print("the essential tools and press Enter to proceed...") + input() def first_start(): @@ -234,8 +237,8 @@ def first_start(): init_dict['ip'] = ip_check() init_dict['password'] = getpass('Enter the password of the "robot" user: ') # create paths and dump the data - os.makedirs(os.path.join(bin_path), exist_ok=True) - with open(settings_path, 'w') as dump_file: + os.makedirs(os.path.join(BIN_PATH), exist_ok=True) + with open(SETTINGS_PATH, 'w') as dump_file: json.dump(init_dict, dump_file, indent=4) @@ -262,7 +265,7 @@ def abort(signal, frame): if __name__ == '__main__': - os.chdir(home) + os.chdir(HOME) print('RoboLab deploy script', 'v.' + __version__) parser = argparse.ArgumentParser() parser.add_argument( @@ -271,11 +274,24 @@ def abort(signal, frame): '-e', '--execute-only', help='do not copy files', action='store_false', default=True) parser.add_argument( '-b', '--backup', help='backup files on the brick', action='store_true', default=False) + parser.add_argument( + '-U', '--update', help='Reload the robolab-deploy', action='store_true', default=False) args = parser.parse_args() print('If you need to change the IP address or password, please run\n\ ./deploy.py -c') + if not args.update: + main(copy=args.execute_only, backup=args.backup) + else: + for file in os.listdir(os.getcwd()): + filepath = os.path.join(os.getcwd(), file) + if os.path.isfile(filepath): + os.remove(filepath) + else: + shutil.rmtree(filepath) + os.chdir(os.getcwd() + "/../") + os.execv(sys.executable, ["python3"] + [(str(os.getcwd()) + "/deploy.py")]) + if args.configure: first_start() - main(copy=args.execute_only, backup=args.backup) From dfded1cae7444820896b182c8c00786a9ba93b15 Mon Sep 17 00:00:00 2001 From: Ian Date: Tue, 27 Feb 2018 12:49:08 +0100 Subject: [PATCH 3/3] Linux users should now also be prompted to install sshpass. And some PEPifications --- deploy.py | 115 +++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 87 insertions(+), 28 deletions(-) diff --git a/deploy.py b/deploy.py index dd69bd1..c829259 100755 --- a/deploy.py +++ b/deploy.py @@ -37,7 +37,12 @@ __author__ = 'Paul Genssler and Lutz Thies' __copyright__ = 'Copyright (c) 2017' -__credits__ = ['Felix Döring', 'Paul Genssler', 'Lutz Thies', 'Felix Wittwer'] +__credits__ = [ + 'Felix Döring', + 'Paul Genssler', + 'Lutz Thies', + 'Felix Wittwer', + "Ian Alexander List"] __license__ = 'MIT' __version__ = '1.3.3' @@ -117,8 +122,6 @@ def install(): file.write(download.read()) - - class Unix: def __init__(self, settings): @@ -134,19 +137,37 @@ def __init__(self, settings): @staticmethod def backup(): with open(os.path.join(BIN_PATH, 'backup.sh'), 'r') as backupinput: - subprocess.call(['sshpass', '-p', settings['password'], 'ssh', '-o', - 'StrictHostKeyChecking=no', 'robot@{}'.format( - settings['ip']), 'bash'], - stdin=backupinput) + subprocess.call([ + 'sshpass', + '-p', + settings['password'], + 'ssh', + '-o', + 'StrictHostKeyChecking=no', + 'robot@{}'.format(settings['ip']), + 'bash' + ], + stdin=backupinput + ) print('Done') @staticmethod def copy_files(): - subprocess.call(['sshpass', '-p', settings['password'], 'scp', '-o', - 'StrictHostKeyChecking=no', '-r', - os.path.join(SRC_PATH), - 'robot@{}:/home/robot/'.format( - settings['ip'])]) + try: + subprocess.call([ + 'sshpass', + '-p', + settings['password'], + 'scp', + '-o', + 'StrictHostKeyChecking=no', + '-r', + os.path.join(SRC_PATH), + 'robot@{}:/home/robot/'.format(settings['ip']) + ]) + except OSError: + Unix.install() + Unix.copy_files() print('Done') @staticmethod @@ -178,14 +199,30 @@ def install(): (http://brew.sh)') sys.exit(1) else: - print('''Please install sshpass - -with apt-get: -sudo apt-get install sshpass - -Further information: -https://gist.github.com/arunoda/7790979''') - sys.exit(1) + pacmans = { + 'yum': ['yum', 'install'], + 'apt-get': ['apt-get', 'install'], + 'pacman': ['pacman', '-S'] + } + pacman_found = False + for pacman in pacmans.keys(): + try: + with open(os.devnull, 'r') as devnull: + subprocess.call([pacmans[pacman][0], '-h'], + stdout=devnull) + subprocess.call([ + 'sudo', + pacmans[pacman][0], + pacmans[pacman][1], + 'sshpass' + ]) + pacman_found = True + except OSError: + continue + if not pacman_found: + print("Your package manager was not found.") + print("Please manually install sshpass and rerun the deploy script") + sys.exit(1) @@ -195,8 +232,8 @@ def main(copy=True, backup=False): global settings if not os.path.exists(SETTINGS_PATH): first_start() - with open(SETTINGS_PATH) as file: - settings = json.load(file) + with open(SETTINGS_PATH) as s_file: + settings = json.load(s_file) # get the platform specific routines print('Remembered OS is', settings['os']) @@ -221,7 +258,7 @@ def check_internet(): urllib.request.urlopen("http://google.com", timeout=1) except urllib.request.URLError: print("You will need to be connected to the internet!") - print("Please connect to a wifi with an internet connection to download") + print("Please ensure an internet connection to download") print("the essential tools and press Enter to proceed...") input() @@ -269,13 +306,32 @@ def abort(signal, frame): print('RoboLab deploy script', 'v.' + __version__) parser = argparse.ArgumentParser() parser.add_argument( - '-c', '--configure', help='reset and create new configuration', action='store_true') + '-c', + '--configure', + help='reset and create new configuration', + action='store_true' + ) parser.add_argument( - '-e', '--execute-only', help='do not copy files', action='store_false', default=True) + '-e', + '--execute-only', + help='do not copy files', + action='store_false', + default=True + ) parser.add_argument( - '-b', '--backup', help='backup files on the brick', action='store_true', default=False) + '-b', + '--backup', + help='backup files on the brick', + action='store_true', + default=False + ) parser.add_argument( - '-U', '--update', help='Reload the robolab-deploy', action='store_true', default=False) + '-U', + '--update', + help='Reload the robolab-deploy', + action='store_true', + default=False + ) args = parser.parse_args() print('If you need to change the IP address or password, please run\n\ @@ -291,7 +347,10 @@ def abort(signal, frame): else: shutil.rmtree(filepath) os.chdir(os.getcwd() + "/../") - os.execv(sys.executable, ["python3"] + [(str(os.getcwd()) + "/deploy.py")]) + os.execv( + sys.executable, + ["python3"] + [(str(os.getcwd()) + "/deploy.py")] + ) if args.configure: first_start()