def reset_password(): # student_number = utils.input_styled( # 'Enter the student number of the student whose password you want to reset to "{}": '.format(default_pw)) password = getpass("Enter the admin password: "******"Who's password do you want to reset?") student_number = get_and_confirm_user(password) ssh_connection = SSH(hostname, username, password) prompt_string = "{}@{}:~$".format(username, hostname) command_response_list = [ ("sudo passwd {}".format(student_number), "[sudo] password for {}:".format(username), None), (password, "New password: "******"wolf", "Re-enter new password: "******"wolf", prompt_string, "password updated successfully"), ] success = ssh_connection.send_interactive_commands(command_response_list) if success: utils.print_success("Password for {} successfully reset to {}".format( student_number, default_pw)) ssh_connection.close()
def reset_password(): print("Who's password do you want to reset?") fullname, student_number = get_and_confirm_user() if not fullname: return password = getpass("Enter the admin password: "******"{}@{}:~$".format(username, hostname) command_response_list = [ ("sudo passwd {}".format(student_number), "[sudo] password for {}:".format(username), None), (password, "LDAP administrator password: "******"New password: "******"wolf", "Retype new password: "******"wolf", prompt_string, "password updated successfully"), ] success = ssh_connection.send_interactive_commands(command_response_list) if success: utils.print_success("Password for {} successfully reset to {}".format( student_number, default_pw)) else: utils.print_error("Something went wrong...") ssh_connection.close()
def create_home_dirs(username_list: list, password: str = None): """Sends the list of users to the file server and runs a script on that server to generate new home directories Arguments: username_list {list} -- list of usernames to generate home directories for Keyword Arguments: password {str} -- file server password (default: {None}) """ username_list_as_string = " ".join(username_list) make_home_dirs_cmd = 'ssh -t hackerspace_admin@tyrell "sudo /nfshome/makehomedirs.sh {}"'.format(username_list_as_string) command_response_list = [ (make_home_dirs_cmd, "hackerspace_admin@tyrell's password: "******"[sudo] password for hackerspace_admin: ", None), (password, "$", None), ] if not password: password = getpass("Enter the admin password: "******"Looks like it worked! Unless you see some nasty errors above...") return success else: utils.print_error("Something went wrong but I'm not smart enough to know what...") return False
def refresh_slideshow(username=None): if not username: username = utils.input_styled("Enter username: \n") # connects and checks to see if file with the same name already exisits ssh_connection = SSH(TV_FILE_SERVER, TV_FILE_SERVER_USER, TV_FILE_SERVER_PW) print("Updating movie maker script...") copy_movie_maker_to_host(ssh_connection) # Cycle through TV directories to find student folder for tv in range(1, 5): filepath = "{}/tv{}/".format(TV_ROOT, tv) command = 'ls {}'.format(filepath) dir_contents = ssh_connection.send_cmd(command, print_stdout=False).split() if username in dir_contents: utils.print_success("Found art for {} on TV# {}".format( username, tv)) # refresh the video utils.print_warning( "\nGonna regenerate video slideshow now, THIS MIGHT TAKE A WHILE!" ) generate_new_movie_file(ssh_connection, username, tv) return True utils.print_error( "\nSorry, I could find art for {}. Are you sure they have art uploaded to the server?" .format(username)) return None
def repair_user_desktop(): password = getpass("Enter the admin password: "******"Make sure the student is logged out before running this repair.\n") fullname, username = user_utils.get_and_confirm_user() if not fullname: return False home_dir = "/nfshome/{}".format(username) # First, make sure their home drive exists. Sometimes home drive creation fails when # creating new users in bulk! if ssh_connection.dir_exists(home_dir): command = "rm -r {}/.cache".format(home_dir) ssh_connection.send_cmd(command, sudo=True) print("I tried to delete their cache. That usually solves the problem...") utils.print_success("Have the student try logging in again.") else: # no home drive! Need to make it utils.print_warning("AH! It appears they don't have a home drive! I gonna try to create one for them now...") command = "bash /nfshome/makehomedirs.sh {}".format(username) ssh_connection.send_cmd(command, sudo=True) utils.print_success("Have the student try logging in again.") ssh_connection.close()
def add_user_to_group(username, group, password=None): if not password: password = getpass("Enter the admin password: "******"ldapaddusertogroup {username} {group}" success = ssh_connection.send_cmd(command, sudo=True) if success: utils.print_warning("The user will probably need to log out and back in again before the changes take effect.") return success
def regenerate_all_slideshows(): utils.print_warning( "This takes a LONG time, best to start this after school to let it run for few hours!" ) do_it = utils.confirm( "Are you sure you want to recreate all the slideshow videos?", yes_is_default=False) if not do_it: return # connects and checks to see if file with the same name already exisits ssh_connection = SSH(TV_FILE_SERVER, TV_FILE_SERVER_USER, TV_FILE_SERVER_PW) print("Updating movie maker script...") copy_movie_maker_to_host(ssh_connection) # Cycle through TV directories for tv in range(1, 5): filepath = "{}/tv{}/".format(TV_ROOT, tv) command = 'ls {}'.format(filepath) dir_contents = ssh_connection.send_cmd(command, print_stdout=False).split() for student_number in dir_contents: # TODO: check if it's a directory or not, skip non-directories test_dir_cmd = "test -d {}{}{} || echo nope".format( filepath, os.sep, student_number) not_a_dir = ssh_connection.send_cmd(test_dir_cmd, print_stdout=False) # note this is an empty string if dir exists if not_a_dir: continue # skip to next one utils.print_success("Found art folder for {} on TV# {}".format( student_number, tv)) # refresh the video utils.print_warning( "\nGonna regenerate video slideshow now, THIS MIGHT TAKE A WHILE!" ) generate_new_movie_file(ssh_connection, student_number, tv, silent=True) utils.print_success("\nFinished TV #{}\n".format(tv)) utils.print_success("Done!")
def archive_users(): ssh_connection = SSH(hostname, SERVER_USERNAME) for p in pwd.getpwall(): username = p[0] user_id = pwd.getpwnam(username).pw_uid account_creation_year = int(str(user_id)[:2]) is_not_system_user = 1000 < user_id < 60000 is_older_than_five_years = current_year - account_creation_year >= 5 if is_not_system_user and is_older_than_five_years: utils.print_error( f"Wiping home drive of user {user_id}: {username}\n") confirmation = utils.input_styled( "Are you sure you wish it proceed? [y/N] (q to quit): \n") if confirmation[0].lower() == "y": ssh_connection.send_cmd(f"rm -rf {home_root}{username}/", sudo=True) utils.print_warning(f'deleted {home_root}{username}/') skeleton = f"bash /nfshome/makehomedirs.sh {username}" ssh_connection.send_cmd(skeleton, sudo=True) utils.print_warning( f'place skeleton to {home_root}{username}/') if ssh_connection.dir_exists(f"{home_root}{username}"): utils.print_success( "User was successfully archived, skeleton placed.") else: utils.print_error( "FATAL: Unable to archive user (no home_dir)") elif confirmation == "q": break else: pass
def play(): # connect to pi-themes ssh_connection = SSH(hostname, pi.username, pi.password) session = ssh_connection.get_open_session() session.exec_command("sudo bash startthemes.sh") stdin = session.makefile("wb", -1) quitting = False while not quitting: #gets user input for whatever song they want to play song_number = utils.input_styled( "Give me a song number. (q to quit): \n") if song_number == 'q': quitting = True else: stdin.write(song_number + "\n") stdin.flush() ssh_connection.close()
def turn_tvs_off_or_on(): which_tvs = None not_quitting = True while not_quitting: user_input = utils.input_styled("o[n] or of[f] or [q]uit? ") if user_input == 'n': cmd = TV_ON_CMD elif user_input == 'f': cmd = TV_OFF_CMD elif user_input == 'q': return else: utils.print_error("Sorry, I didn't understand \"{}\". Hit 'n' for on or 'f' for off.".format(user_input)) continue user_input = utils.input_styled("Which TV #? (default = ALL) ") if user_input == 'q': return elif not user_input: # turn them all off which_tvs = valid_tvs elif user_input in valid_tvs: which_tvs = user_input else: utils.print_error("Sorry, I didn't understand \"{}\". Hit Enter to turn them all off, or enter a number for a specific TV.".format(user_input)) continue for tv_number in which_tvs: hostname = "pi-tv{}".format(tv_number) ssh_connection = SSH(hostname, pi.username, pi.password) ssh_connection.send_cmd(cmd) ssh_connection.close()
def speak(): # connects to pi themes ssh_connection = SSH(hostname, pi.username, pi.password) quitting = False while not quitting: #makes while loop and gets user input as to what to say dialogue_old = utils.input_styled( "What would you like me to say? (q to quit): \n") if dialogue_old == 'q': quitting = True else: #properly formats what they want to say (just puts it in quotes) dialogue_new = "\"{}\"".format(dialogue_old) #puts new dialogue into the command: https://www.dexterindustries.com/howto/make-your-raspberry-pi-speak/ command = "sudo espeak -a 200 {} 2>/dev/null".format(dialogue_new) #connects then sends command ssh_connection.send_cmd(command) ssh_connection.close()
def modify_user(username, ldif_changes_dict, password=None): """[summary] Args: username: ldap username ldif_changes_dict: a dictionary of ldif keys and their new values, e.g {'sn': 'COUTURE', 'givenName': 'TYLERE'} password: admin password """ if not password: password = getpass("Enter the admin password: "******"sudo ldapmodifyuser {}".format(username) EOF = '\x04' # Ctrl + D command_response_list = [] first = True for key, value in ldif_changes_dict.items(): if first: command_response_list.append((main_command, "[sudo] password for hackerspace_admin: ", None)) command_response_list.append((password, "dc=tbl", None)) first = False else: command_response_list.append((main_command, "dc=tbl", None)) change_tuple = (f"replace: {key}\n{key}: {value}\n{EOF}", '$', None) command_response_list.append(change_tuple) success = ssh_connection.send_interactive_commands(command_response_list) if success: utils.print_success("Looks like it worked to me?") return True else: utils.print_error("Something appears to have gone wrong. Hopefully there's a useful error message somewhere up there.") return False
def create_users_from_ldif(ldif_content: str, ssh_connection=None, password=None): """Save an ldif file on the authenticationserver and run ldapadd command to create new users with it. Use the provided ssh connect if supplied, otherwise create one. Arguments: ldif_content {str} -- string containing all the ldif entry to create the new users via `ldapadd` ssh_connection {[type]} -- [description] password {str} -- if user has already entered PW this prevent re-entering it. """ # if we were passed an ssh connection, leave it open, otherwise we need to create it and close it at the end. close_connection = False if ssh_connection else True if not ssh_connection: if not password: password = getpass("Enter the admin password: "******"{}" >> {}'.format(ldif_content, LDIF_FILENAME)) # use the ldif file to create the user with `ldapadd` # https://linux.die.net/man/1/ldapadd # -x Use simple authentiction instead of SASL. # -D Use the Distinguished Name binddn to bind to the LDAP directory. # -W Prompt for simple authentication. This is used instead of specifying the password on the command line. # -f Read the entry modification information from file instead of from standard input. ldap_add_cmd = "ldapadd -x -D cn=admin,dc=hackerspace,dc=tbl -W -f {}".format(LDIF_FILENAME) command_response_list = [ (ldap_add_cmd, "Enter LDAP Password: "******"$", "adding new entry"), ] success = ssh_connection.send_interactive_commands(command_response_list) # if we were passed an ssh connection, leave it open, otherwise close it. if close_connection: ssh_connection.close() return success
def get_student_name(student_number, password=None): """Get a student's full name from their student number. Return None if account doesn't exist. Arguments: student_number {str} -- username Keyword Arguments: password {str} -- admin password Returns: str -- student's full name, or None is student doesn't exist. """ hostname = socket.gethostname() # can use the local computer username = '******' if not password: password = getpass("Enter the admin password: "******"starting with", and after the username should be a colon : # this ensures unique results command = "getent passwd | grep ^{}:".format(student_number) result = ssh_connection.send_cmd(command, sudo=True, print_stdout=False) # results example, split on colons # ***** # [sudo] password for hackerspace_admin: # 9912345:x:16000:16000:John Doe:/home/9912345:/bin/bash user_info_list = result.split(':') # no user info returned, doesn't exist if len(user_info_list) == 2: return None else: return user_info_list[5]
def repair_user_desktop(): ssh_connection = SSH(hostname, username) print_warning("Make sure the student is logged out before running this repair.\n") student_number = input_styled("Enter Student Number: \n") command = "rm -r /nfshome/{}/.cache".format(student_number) ssh_connection.send_cmd(command, sudo=True) print_success("Have the student log in again. Their cache should be cleared now.") ssh_connection.close()
def create_downloads(): ssh_connection = SSH(HOSTNAME, SERVER_USERNAME) response = ssh_connection.send_cmd('getent passwd {16000..20000}', sudo=True) user_list = response.splitlines() for username_line in user_list: username = username_line.split(":")[0] print(username) if utils.user_exists(username): dls = f"/nfshome/{username}/Downloads" if ssh_connection.file_exists(f"/nfshome/{username}"): if not ssh_connection.file_exists(dls): print("home drive exists, make Download?") # input() ssh_connection.send_cmd(f"mkdir {dls}", sudo=True) ssh_connection.send_cmd(f"chown {username}:students {dls}", sudo=True) else: print("Downloads already exists, skipping...") else: print("no home dir, skipping")
def get_tv_containing_student(student_number): """ Search all pi-slideshow TV directories until directory with same number is found, return the TV # """ ssh_connection = SSH(TV_FILE_SERVER, TV_FILE_SERVER_USER, TV_FILE_SERVER_PW) for tv in range(1, 5): filepath = "{}/tv{}/".format(TV_ROOT, tv) command = 'ls {}'.format(filepath) dir_contents = ssh_connection.send_cmd(command, print_stdout=False).split() if student_number in dir_contents: utils.print_success("Found art for {} on TV# {}".format( student_number, tv)) ssh_connection.close() return tv ssh_connection.close() return None
def puppet_clear_certificates(hostname=None, password=None): if password is None: password = getpass("Enter the admin password: "******"Which computer? (e.g. 'tbl-h10-12', or '192.168.3.125' or [q]uit) ") if hostname == 'q': print("Quitting this.") return None remove_server_cert_cmd = "/opt/puppetlabs/bin/puppetserver ca clean --certname {}.hackerspace.tbl".format(hostname) ssh_connection_puppet = SSH(puppet_host, username, password) ssh_connection_puppet.send_cmd(remove_server_cert_cmd, sudo=True) ssh_connection_puppet.close() utils.print_warning("Ok, I tried to remov the old certificates from the puppet server.")
def reinstall_graphics_drivers(): password = getpass("Enter the admin password: "******"Enter the computer numbers, seperated by spaces (where # is from hostname tbl-h10-#-s e.g: 2 15 30): " ) num_list = numbers.split() for num in num_list: utils.print_warning("Trying computer #{}...".format(num)) good_host = False computer_host = "tbl-h10-{}-s".format(num) good_host = utils.host_exists(computer_host) if not good_host: # this computer # doesn't exist or can't connect utils.print_error( "Host not found. Does that computer exist? Is it on?") continue # now that we know we have a good host, ssh into it and try to run puppet ssh_connection = SSH(computer_host, username, password) nvidia_cmd = "bash /opt/NVIDIA-Linux-x86_64-430.50.run --disable-nouveau --run-nvidia-xconfig --no-x-check --silent" utils.print_warning = "Running command: {}".format(nvidia_cmd) utils.print_warning = "This may take a minute..." output = ssh_connection.send_cmd(nvidia_cmd, sudo=True) if "ERROR" in output: utils.print_error("It looks like something went wrong. Sorry!") print(output) else: utils.print_success( "It looks like it worked. Don't worry about those warnings. I'm going to try to restart computer #{}" .format(num)) output = ssh_connection.send_cmd("/sbin/shutdown -r now", sudo=True) utils.print_success("\nComplete\n\n") ssh_connection.close()
def remove_media(username=None, tv=None): ssh_connection = SSH(TV_FILE_SERVER, TV_FILE_SERVER_USER, TV_FILE_SERVER_PW) username = utils.input_plus("Enter username", default=username) if username == "q": return False while True: tv = get_tv_containing_student(username) if tv is None: utils.print_error("No art found for {}".format(username)) return False # get of list of the student's art and display the list filepath = "{}/tv{}/{}/".format(TV_ROOT, tv, username) command = 'ls {}'.format(filepath) dir_contents = ssh_connection.send_cmd(command, print_stdout=False).split() media_list = [ inquirer.List( 'art', message= "Which file do you want to delete? I'll display it first so you can confirm.", choices=dir_contents, ), ] art_file = inquirer.prompt(media_list)["art"] art_file_full_path = filepath + art_file # Show the image with Pillow # Transfer locally local_copy = "/tmp/" + art_file ssh_connection.get_file(art_file_full_path, local_copy) try: img = Image.open(local_copy) except IOError: utils.print_error("File not found") ssh_connection.close() return False w, h = img.size aspect_ratio = w / h thumb = img.resize((400, int(400 / aspect_ratio))) thumb.show() delete_file = utils.confirm( "Are you sure you want to delete {}? Hopefully it popped up for you" .format(art_file), yes_is_default=False) if delete_file: cmd = "rm {}".format(art_file_full_path) ssh_connection.send_cmd(cmd, print_stdout=True) # confirm it's gone: if ssh_connection.file_exists(art_file_full_path): utils.print_error( "\nNot sure what happened there, but the file didn't get deleted. Sorry!" ) else: utils.print_success("\nThe file was successfully deleted.") # Keep deleting files ina loop if they want to keep_going = utils.confirm("Remove another file for this student?") if not keep_going: ssh_connection.close() utils.print_warning( "\nDon't forget to refresh the user's video slideshow!\n") return True
def add_new_user(): created = False while not created: student_number = utils.input_styled("Enter Student Number: \n") password = getpass("Enter the admin password: "******"An account for {}, {}, already exists. Try resetting their password." .format(student_number, student)) else: first_name = utils.input_styled("First Name: \n").upper() last_name = utils.input_styled("Last Name: \n").upper() create = utils.input_styled( "Create account for {} {} {}? y/[n] \n".format( student_number, first_name, last_name)) if create == 'y': ssh_connection = SSH(hostname, username, password) main_command = 'bash hs-ldapadduser.sh "{}" "{}" "{}"'.format( student_number, first_name, last_name) command_response_list = [ ("cd hs-ldap/", ":~/hs-ldap$", None), (main_command, "[sudo] password for hackerspace_admin: ", None), (password, "Enter LDAP Password: "******"hackerspace_admin@tyrell's password: "******"[sudo] password for hackerspace_admin: ", None), (password, ":~/hs-ldap$", "Set owner on: /nfshome/{}".format(student_number)), ] success = ssh_connection.send_interactive_commands( command_response_list) ssh_connection.close() if success: utils.print_success( 'Successfully created account for {} {} {}'.format( student_number, first_name, last_name)) utils.print_success( 'Their default password will be "wolf"') created = True else: utils.print_error( "Something went wrong there, hopefully useful info is printed above...let's try again\n" ) else: print("Aborted that one. \n") if utils.input_styled("Try again? [y]/n: ") == 'n': return input("\nHit enter to continue...\n")
def add_new_title(): fullname, username = user_utils.get_and_confirm_user() fullname = fullname.title() # gets info of the student who made the art fullname_entered = utils.input_plus("Full name", fullname) if fullname_entered: fullname = fullname_entered grad_year = utils.input_styled("Grad Year: \n") last_name = username.split(".")[-1].title( ) # get the last word if the username tyere.couture will get couture # https://pypi.org/project/inquirer/ subject_list = [ inquirer.List( 'subject', message="What subject is the student in?", choices=[ 'Digital Art', 'Digital Photography', '3D Modelling & Animation', 'Custom subject:' ], ), ] choose_subject = inquirer.prompt(subject_list)["subject"] # gets user to input a custom subject if they so choose if choose_subject == "Custom subject:": custom_subject = utils.input_styled("Well then what are they in? \n") choose_subject = custom_subject default_tv = '1' if last_name.upper()[0] <= 'M' else '2' tv = utils.input_plus( "Which TV # are you sending this to (1 for lastname A-M, 2 for N-Z, 3 for Grads)?", default_tv) if not tv: tv = default_tv filename = username + ".a.title" template = "_template.svg" source_file = "scripts/TVs/{}".format(template) temp_filepath_svg = "{}{}.svg".format(temp_dir, filename) filename_png = filename + ".png" temp_filepath_png = temp_dir + filename_png # creates copy of template with the filename it will use os.system("cp {} {}".format(source_file, temp_filepath_svg)) # writes the student information into the copy of the svg template os.system('sed -i -e "s/FIRSTNAME LASTNAME/{}/g" {}'.format( fullname, temp_filepath_svg)) os.system('sed -i -e "s/YYYY/{}/g" {}'.format(grad_year, temp_filepath_svg)) # need to escape the ampersand character in "3D Modelling & Animation" os.system('sed -i -e "s/SUBJECT/{}/g" {}'.format( choose_subject.replace('&', '\&'), temp_filepath_svg)) # creates a png image from the svg os.system('inkscape -z -e {} -w 1920 -h 1080 {}'.format( temp_filepath_png, temp_filepath_svg)) server_filepath = "tv{}/{}/".format(tv, username) # setup a connect so we can makesure the directory exists ssh_connection = SSH(hostname, SERVER_USERNAME, pi.password) # make sure the directory exists, if not create it: if not ssh_connection.file_exists(server_filepath): ssh_connection.send_cmd('mkdir {}'.format(server_filepath)) # move image onto the server with scp (this will fail if they've never connected to hightower before, hence warning at bottom) command = 'sshpass -p "{}" scp {} {}@{}:{}'.format(pi.password, temp_filepath_png, SERVER_USERNAME, hostname, server_filepath) os.system(command) # removes all temp files we created os.system('rm {}'.format(temp_filepath_png)) os.system('rm {}'.format(temp_filepath_svg)) # Check if file now exists on the server title_exists = ssh_connection.file_exists(server_filepath, filename_png) if title_exists: utils.print_success( f"{filename_png} was successfully sent over to TV {tv}") add_images = utils.confirm( f"Would you like to add images to {fullname}'s new shrine?") if add_images: add_new_media(username, tv) else: gen_video = utils.confirm( "Would you like to regenerate the video file?") if gen_video: refresh_slideshow(username=username) else: utils.print_error( f"The title image '{filename_png}' was not added. Maybe inkscape isn't installed? Or it's possible you've never connected to this server before. \n\n" "Try connecting once first by typing `ssh hightower` into a terminal, then answering yes." )
def add_new_theme(): #gets and checks the url of the file mp3_url = True while mp3_url == True: have_good_input = False mp3_url = "" while not have_good_input: mp3_url = utils.input_styled( "Paste the url to the mp3 file you want to add. (q to quit): \n" ) if mp3_url == 'q': break #check content to ensure proper mp3 type mime_type_good = utils.verify_mimetype(mp3_url, "audio/mpeg") have_good_input = mime_type_good if have_good_input: #then get file number have_good_input = False while not have_good_input: filename = os.path.basename(urlparse(mp3_url).path) name, ext = os.path.splitext(filename) #check if filename is already a number, and offer to use it try: name = int(name) good_name_already = True except ValueError: good_name_already = False prompt = "What number (integers only) do you want to give it?" + ( " [Enter] = {}".format(name) if good_name_already else "") + "\n" mp3_number = utils.input_styled(prompt) try: if good_name_already and not mp3_number: mp3_number = name else: mp3_number = int(mp3_number) have_good_input = True except ValueError: utils.print_error("Dude, that wasn't an integer! ") have_good_input = False filename = "{}.mp3".format(mp3_number) # print("test: {}".format(filename)) print( "Sending {} to pi-themes to see if file exists already with that name." .format(filename)) command = "wget -O /media/THEMES/{} {} && exit".format( filename, mp3_url) filepath = "/media/THEMES/" ssh_connection = SSH(hostname, pi.username, pi.password) #checks if file exists, and if user wants to overwrite it already_exists = ssh_connection.file_exists(filepath, filename) # asks user if they want to overwrite https://www.quora.com/I%E2%80%99m-new-to-Python-how-can-I-write-a-yes-no-question if already_exists == True: overwrite = utils.input_styled( "There is a file that already exists with that name. Do you want to overwrite it? (y/[n]) \n", utils.ByteStyle.WARNING, ) if not overwrite or overwrite.lower()[0] == "n": mp3_url = True elif overwrite.lower()[0] == "y": already_exists = False pass else: utils.print_styled("(y/n)", color=utils.ByteStyle.Y_N) elif already_exists == False: pass else: utils.print_error( "Something went wrong. Expected true or false but got something else" ) #sends the command if already_exists == False: ssh_connection.send_cmd(command) another_code = utils.input_styled( "Would you like to add another code? ([y]/n) \n", color=utils.ByteStyle.Y_N) if not another_code or another_code.lower()[0] == "y": mp3_url = True pass elif another_code.lower()[0] == "n": mp3_url = False else: utils.print_styled( "(y/n)", utils.ByteStyle.Y_N, ) #closes ssh connection ssh_connection.close()
def add_new_media(username=None, tv=None): media_url = True while media_url: # gets and checks the url of the file media_url, name_without_ext, extension = get_media_url() if media_url is None: return # collects information to name the file, and as to which tv to send it to username_input = utils.input_styled( "Enter username (default = {}): \n".format(username)) if not username_input: pass else: username = username_input tv = guess_tv(username) tv_input = utils.input_styled( "What TV # are you sending this to? (default = {}): ".format(tv)) if not tv_input: pass else: tv = tv_input image_name = None name_good = utils.input_styled( "What is the name of this image? (default = {}): ".format( name_without_ext)) if not name_good: image_name = name_without_ext else: image_name = name_good filename = username + ".z." + image_name + extension # Save videos directly in the tv's rtoot directory. if is_video(extension.lower()): filepath = "{}/tv{}/".format(TV_ROOT, tv) # Save images into a subfolder, which will be used to generate a slideshow video else: filepath = "{}/tv{}/{}/".format(TV_ROOT, tv, username) utils.print_warning( "Sending {} to hightower to see if file exists already with that name." .format(filename)) # connects and checks to see if file with the same name already exisits ssh_connection = SSH(TV_FILE_SERVER, TV_FILE_SERVER_USER, TV_FILE_SERVER_PW) already_exists = ssh_connection.file_exists(filepath, filename) # if it does exist, asks user if they want to overwrite it while already_exists and not utils.confirm( "There is a file that already exists with that name. Do you want to overwrite it?", yes_is_default=False): # don't want to overwrite, so get a new name: image_name = utils.input_styled( "Provide a different name for the image: ") filename = username + ".z." + image_name + extension # check again already_exists = ssh_connection.file_exists(filepath, filename) command = "wget -O {}{} '{}' && exit".format(filepath, filename, media_url) # make sure the directory exists, if not create it: if not ssh_connection.file_exists(filepath): ssh_connection.send_cmd('mkdir {}'.format(filepath)) success = ssh_connection.send_cmd(command) if success: utils.print_success( "{} was succesfully sent over to pi-tv{}".format(filename, tv)) else: utils.print_error( "Something went wrong. Check the filename, is it wonky with weird characters?" ) # asks user if they want to add another image if utils.confirm("Would you like to add another image?"): media_url = True else: break ssh_connection.close() if utils.confirm( "Do you want to generate a new video slideshow of this student's art?" ): refresh_slideshow(username=username)
def change_username(current_username=None, new_username=None, auto=False, password=None): utils.print_warning( "\nMake sure the student is logged out before making this change!\n") if not current_username: fullname, current_username = user_utils.get_and_confirm_user() if not fullname: return False if not new_username: new_username = user_utils.get_new_username() if not new_username: return False if not auto: if not utils.confirm( f"Confirm you want to change {current_username} to {new_username}?", yes_is_default=False): print("Bailing...") return False if not password: password = getpass("Enter the admin password: "******"sudo ldaprenameuser {} {}".format(current_username, new_username) ssh_connection.send_cmd(command, sudo=True) ssh_connection.close() utils.print_warning( "Now gonna change the name of their home directory to match the new username" ) ssh_connection = SSH(file_hostname, username, password) command = "mv /nfshome/{} /nfshome/{}".format(current_username, new_username) ssh_connection.send_cmd(command, sudo=True) ssh_connection.close() utils.print_success("Done!") utils.print_warning("Now gonna tell LDAP where the new home directory is") user_utils.modify_user(new_username, {'homeDirectory': f'/home/{new_username}'}, password) return True
def clean_user_files(): who_to_clean = utils.input_styled("Enter a username or all? ") if who_to_clean == 'all': search_root = "/nfshome/*" else: fullname, username = user_utils.get_and_confirm_user( username=who_to_clean) if not fullname: return False # utils.print_warning("Make sure the student is logged out before running this repair.\n") search_root = f"/nfshome/{username}" ssh_connection = SSH(HOSTNAME, SERVER_USERNAME) print("Available space on the file server BEFORE:") print("Filesystem Size Used Avail Use% Mounted on") ssh_connection.send_cmd("df -h | grep nfshome") # empty Downloads directory location = f"{search_root}/Downloads/*" num = count_files(location, ssh_connection) if num > 0: utils.print_warning(f"Emptying Downloads directory: {location}") utils.input_styled("Enter to continue...") delete_files(location, ssh_connection) # remove .cache directory and contents location = f"{search_root}/.cache/*" num = count_files(location, ssh_connection) if num > 0: utils.print_warning(f"Emptying .cache directory: {location}") utils.input_styled("Enter to continue...") delete_files(location, ssh_connection) # empty trash location = f"{search_root}/.local/share/Trash/files/*" num = count_files(location, ssh_connection) if num > 0: utils.print_warning(f"Emptying Trash: {location}") utils.input_styled("Enter to continue...") delete_files(location, ssh_connection) # CR2 Files (raw images...massive sizes) location = f"{search_root}" file_glob = '*.CR2' # all files num = count_files(location, ssh_connection, file_glob) if num > 0: print( "Finding and deleting all CR2 files (raw images that are massive)..." ) # delete_files(location, file_glob, ssh_connection) # # delete any tmp directory contents # location = f"{search_root}" # num = count_files(location, ssh_connection) # if num > 0: # utils.print_warning(f"Emptying .cache directory: {location}") # utils.input_styled("Enter to continue...") # delete_files(location, ssh_connection) # large files location = f"{search_root}" size = '2G' utils.print_warning("This search can take a while, please be patient...") num = count_files(location, ssh_connection, size=size) if num > 0: utils.print_warning(f"Removing files larger than: {size}") utils.input_styled("Enter to continue...") delete_files(location, ssh_connection, size=size) print("Available space on the file server AFTER:") print("Filesystem Size Used Avail Use% Mounted on") ssh_connection.send_cmd("df -h | grep nfshome") ssh_connection.close()
def refresh_user(): utils.print_warning( "This will refresh a user's account by removing all their customizations and settings. However their files/documents will remain. This can be used if the user is experiences UI issues or having other weird problems with their account." ) password = getpass("Enter the admin password: "******"ENSURE THE USER IS LOGGED OUT BEFORE PERFORMING THIS ACTION!\n") fullname, username = user_utils.get_and_confirm_user() if not fullname: return False home_dir = f"/nfshome/{username}" # First, make sure their home drive exists. Sometimes home drive creation fails when # creating new users in bulk! if ssh_connection.dir_exists(home_dir): move = f"mv {home_dir} {home_dir}.bu" ssh_connection.send_cmd(move, sudo=True) utils.print_success(f"✓ Backing up home drive") skeleton = f"bash /nfshome/makehomedirs.sh {username}" ssh_connection.send_cmd(skeleton, sudo=True) utils.print_success(f"✓ Created skeleton") for dir in dirs: transfer_files(home_dir, dir, ssh_connection) if ssh_connection.dir_exists(home_dir): utils.print_success(f"✓ All files have been recovered") remove_backup = f"rm -rf {home_dir}.bu" ssh_connection.send_cmd(remove_backup, sudo=True) utils.print_success(f"✓ Removing old backup") change_ownership = f"chown -R '{username}:students' '{home_dir}'" ssh_connection.send_cmd(change_ownership, sudo=True) utils.print_success(f"✓ Changed ownership root → {username}") utils.print_success( "Operation complete, please have the user log back in.") else: utils.print_error( f"✗ New home directory does not exist, reverting to backup.") revert_to_backup = f"mv {home_dir}.bu {home_dir}" ssh_connection.send_cmd(revert_to_backup, sudo=True) if ssh_connection.dir_exists(home_dir): utils.print_error( "Reverted to backup successfully (No changes).") else: utils.print_error( "FATAL (PANIC): Error while creating new home directory, could not revert to backup. (No home directory exists)" ) panic = f"bash /nfshome/makehomedirs.sh {username}" ssh_connection.send_cmd(panic, sudo=True) if ssh_connection.dir_exists(home_dir): utils.print_success( "A New home directory was able to be made.") else: utils.print_error( "FATAL (PANIC): COULD NOT CREATE NEW HOME DIRECTORY FOR USER." ) else: # no home drive! Need to make it utils.print_warning( "No home drive detected, creating new home drive...") command = f"bash /nfshome/makehomedirs.sh {username}" ssh_connection.send_cmd(command, sudo=True) utils.print_success( "Operation complete, please have the user log back in.") ssh_connection.close()
def puppet_run(computer_number=None, password=None, auto_fix_certificates=False): if password is None: password = getpass("Enter the admin password: "******"\nComputer is online, but cant' connect. Maybe it's mining?\n") return False puppet_command = '/usr/bin/puppet agent -t' while not success: utils.print_warning( "\nRunning puppet on {}. This may take a while. The ouput will appear when it's done for you to inspect...\n" .format(computer_host)) output_puppet_run = ssh_connection.send_cmd(puppet_command, sudo=True) if "Error: Could not request certificate: The certificate retrieved from the master does not match the agent's private key." in output_puppet_run: pass elif "alert certificate unknown" in output_puppet_run: pass elif "unable to get local issuer certificate" in output_puppet_run: pass elif "Notice: Run of Puppet configuration client already in progress" in output_puppet_run: if remove_puppet_lock(ssh_connection, password): pass else: utils.print_warning( "\nIt appears that puppet is already running on {}. Give it a few minutes and try again.\n" .format(computer_host)) break elif "command not found" in output_puppet_run: utils.print_warning( "\nCouldn't find puppet.... why not? Try the other spot...") break else: utils.print_success("\n\nSeems like everything worked ok!\n\n") break # out of the while loop, all done # ## Handle certificate problem ### # Error: Could not request certificate: The certificate retrieved from the master does not match the agent's private key. # Certificate fingerprint: 26:DD:EC:AC:15:95:7C:4B:7C:DB:0C:C6:30:C8:1A:7D:FF:C1:7B:C8:A5:56:53:77:94:2A:C3:F2:98:B7:D6:6A # To fix this, remove the certificate from both the master and the agent and then start a puppet run, which will automatically regenerate a certificate. # On the master: # puppet cert clean tbl-hackerspace-2-s.hackerspace.tbl # On the agent: # 1a. On most platforms: find /etc/puppetlabs/puppet/ssl -name tbl-hackerspace-2-s.hackerspace.tbl.pem -delete # 1b. On Windows: del "\etc\puppetlabs\puppet\ssl\certs\tbl-hackerspace-2-s.hackerspace.tbl.pem" /f # 2. puppet agent -t # # Exiting; failed to retrieve certificate and waitforcert is disabled if not auto_fix_certificates: try_to_fix = utils.input_styled( "Looks like there was a certificate problem. Usually this happens when a computer is re-imaged. Want me to try to fix it? [y]/n " ) if try_to_fix == 'n': break # first, remove certificate from agent: if "find /etc/puppetlabs/puppet/ssl" in output_puppet_run: # old 16.04 installations remove_agent_cert_cmd = "find /etc/puppetlabs/puppet/ssl -name {}.hackerspace.tbl.pem -delete".format( computer_host) else: remove_agent_cert_cmd = "rm -rf /var/lib/puppet/ssl" # just delete them all ssh_connection.send_cmd(remove_agent_cert_cmd, sudo=True) # now remove certificate from puppet server: puppet_clear_certificates(computer_host, password) # command_response_list = [ # ("sudo passwd {}".format(student_number), "[sudo] password for {}:".format(username), None), # (password, "New password: "******"wolf", "Re-enter new password: "******"wolf", prompt_string, "password updated successfully"), # ] # success = ssh_connection.send_interactive_commands(command_response_list) ssh_connection.close()
def add_new_title(): #gets info of the student who made the art first_name = utils.input_styled("First name: \n") last_name = utils.input_styled("Last name: \n") grad_year = utils.input_styled("Grad Year: \n") student_number = utils.input_styled("Student number: \n") #https://pypi.org/project/inquirer/ subject_list = [ inquirer.List( 'subject', message="What subject is the student in?", choices=[ 'Digital Art', 'Digital Photography', '3D Modelling & Animation', 'Custom subject:' ], ), ] choose_subject = inquirer.prompt(subject_list)["subject"] #gets user to input a custom subject if they so choose if choose_subject == "Custom subject:": custom_subject = utils.input_styled("Well then what are they in? \n") choose_subject = custom_subject default_tv = '1' if last_name.upper()[0] <= 'M' else '2' tv = utils.input_styled( "Which TV # are you sending this to (1 for lastname A-M, 2 for N-Z)? [Enter] = {}: \n" .format(default_tv)) if not tv: tv = default_tv filename = student_number + ".a." + first_name + last_name template = "_template.svg" source_file = "scripts/TVs/{}".format(template) temp_filepath_svg = "{}{}.svg".format(temp_dir, filename) filename_png = filename + ".png" temp_filepath_png = temp_dir + filename_png #creates copy of template with the filename it will use os.system("cp {} {}".format(source_file, temp_filepath_svg)) # writes the student information into the copy of the svg template os.system('sed -i -e "s/FIRSTNAME LASTNAME/{} {}/g" {}'.format( first_name, last_name, temp_filepath_svg)) os.system('sed -i -e "s/YYYY/{}/g" {}'.format(grad_year, temp_filepath_svg)) os.system('sed -i -e "s/SUBJECT/{}/g" {}'.format(choose_subject, temp_filepath_svg)) # creates a png image from the svg os.system('inkscape -z -e {} -w 1920 -h 1080 {}'.format( temp_filepath_png, temp_filepath_svg)) filepath_pi = "/home/pi-slideshow/tv{}/{}/".format(tv, student_number) # make a folder for a new student when title card is made os.system('sshpass -p "{}" ssh {}@{} && mkdir {}'.format( pi.password, username, hostname, filepath_pi)) #scps into the tv photo directory command = 'sshpass -p "{}" scp {} {}@{}:{}'.format(pi.password, temp_filepath_png, username, hostname, filepath_pi) os.system(command) #removes all files it created os.system('rm {}'.format(temp_filepath_png)) os.system('rm {}'.format(temp_filepath_svg)) #os.system('rm {}.png'.format(filename)) ssh_connection = SSH(hostname, username, pi.password) title_exists = ssh_connection.file_exists(filepath_pi, filename_png) if title_exists: utils.print_success("{} was successfully sent over to TV {}".format( filename_png, tv)) add_images = utils.input_styled( utils.ByteStyle.Y_N, "Would you like to add images to {}'s new shrine? ([y]/n)\n". format(first_name)) if not add_images or add_images.lower()[0] == "y": add_new_media.add_new_media(student_number, tv) else: utils.print_error( "The title image '{}' was not added. Is sshpass installed?".format( filename_png))
def add_new_theme(): # gets and checks the url of the file mp3_url = True while mp3_url is True: have_good_input = False mp3_url = "" while not have_good_input: mp3_url = utils.input_styled("Paste the url to the mp3 file you want to add. (q to quit): \n") if mp3_url == 'q': break # check content to ensure proper mp3 type mime_type_good = utils.verify_mimetype(mp3_url, "audio/mpeg") have_good_input = mime_type_good if have_good_input: # then get file number have_good_input = False while not have_good_input: filename = os.path.basename(urlparse(mp3_url).path) name, ext = os.path.splitext(filename) # check if filename is already a number, and offer to use it try: name = int(name) good_name_already = True except ValueError: good_name_already = False prompt = "What code do you want to give it?" + (" [Enter] = {}".format(name) if good_name_already else "") + "\n" mp3_code = utils.input_styled(prompt) # try: if good_name_already and not mp3_code: mp3_code = name # else: # mp3_number = int(mp3_number) have_good_input = True # except ValueError: # utils.print_error("Dude, that wasn't an integer! ") # have_good_input = False filename = "{}.mp3".format(mp3_code) # print("test: {}".format(filename)) print("Sending {} to pi-themes to see if file exists already with that name.".format(filename)) command = "wget -O {}{} {} && exit".format(THEMES_PATH, filename, mp3_url) ssh_connection = SSH(hostname, pi.username, pi.password) # checks if file exists, and if user wants to overwrite it already_exists = ssh_connection.file_exists(THEMES_PATH, filename) # asks user if they want to overwrite https://www.quora.com/I%E2%80%99m-new-to-Python-how-can-I-write-a-yes-no-question if already_exists: overwrite = utils.confirm( "There is a file that already exists with that name. Do you want to overwrite it?", yes_is_default=False ) if not overwrite: mp3_url = True else: already_exists = False pass elif not already_exists: pass else: utils.print_error("Something went wrong. Expected true or false but got something else") # sends the command if not already_exists: ssh_connection.send_cmd(command) another_code = utils.confirm("Would you like to add another code?") if another_code: mp3_url = True pass else: mp3_url = False ssh_connection.close()