def cli_add_packages(): """Ask user for a list of packages""" printc('Give a list of packages separated by spaces.', Color.GREEN) printc('Exemple: \'package1 package2 package3 ...\' ', Color.GREEN) # Get packages package_list = input('-->: ').split() logging.debug('Checking that requested packages exists') # For each package for package_name in package_list: try: # Check packages availability logging.debug( 'Executing \'subprocess.check_output(\'dnf list \'' + package_name + ' | grep ' + package_name + ', shell=True)\'') subprocess.check_output('dnf list ' + package_name + ' | grep ' + package_name, shell=True) # If there is not running process for image creator instance pid except subprocess.CalledProcessError: raise UserWarning("Package \'" + package_name + '\' not available') # Return the list of packages return package_list
def cli_menu(): # Display main livenet menu printc('\n == Livenet image module == \n', Color.GREEN) print(' 1 - Generate a new livenet image') print(' 2 - Mount an existing livenet image') print(' 3 - Unount an existing livenet image') print(' 4 - Resize livenet image') # Answer and get the action to execute print('\n Select an action') main_action = input('-->: ') print('') # List available kernels if main_action == '1': cli_create_livenet_image() elif main_action == '2': cli_mount_livenet_image() elif main_action == '3': cli_unmount_livenet_image() elif main_action == '4': cli_resize_livenet_image() # Bad entry else: raise UserWarning( '\'' + main_action + '\' is not a valid entry. Please enter another value.')
def cli_use_modules(): """The method for using modules with cli interface""" # Get available modules modules = sorted(os.listdir(ImageManager.MODULES_PATH)) # Get only module name to display # We have to modif name because module naming convention is: # "<image_type>_module.py" module_names = [ module.replace('_module.py', '') for module in modules if 'base' not in module and 'module' in module ] # Select desired image type in the list printc('[+] Select the module you want to use:\n', Color.BLUE) selected_module_name = select_from_list(module_names) # Convert image type into it's corresponding module name selected_module = selected_module_name + '_module' # Import the module module = __import__(selected_module) # Launch module menu module.cli_menu()
def cli_menu(): # Display main menu printc('\n == NFS image module == \n', Color.GREEN) print(' 1 - Generate a new nfs staging image') print(' 2 - Generate a new nfs golden image from a staging image') print(' 3 - Manage nodes of a golden image') # Answer and get the action to execute print('\n Select an action') main_action = input('-->: ') print('') if main_action == '1': cli_create_staging_image() elif main_action == '2': cli_create_golden_image() elif main_action == '3': cli_manage_nodes() # Bad entry else: raise UserWarning( '\'' + main_action + '\' is not a valid entry. Please enter another value.')
def generate_initramfs(kernel): """Generate an initramfs from a kernel. The new initramfs will be generated in KernelManager.KERNELS_PATH. :param kernel: A kernel in KernelManager.KERNELS_PATH :type kernel: str """ logging.info('Start generating initramfs for kernel \'' + kernel + '\'') # Create a generation path for the initramfs kernel_version = kernel.replace('vmlinuz-', '') generation_path = KernelManager.KERNELS_PATH + '/initramfs-kernel-' + kernel_version printc('[INFO] Now generating initramfs... May take some time', Color.BLUE) # Generate the new initramfs file with dracut command on the kernel logging.info( 'Executing \'dracut --xz -v -m "network base nfs" --add "ifcfg livenet systemd systemd-initrd dracut-systemd" --add-drivers xfs --no-hostonly --nolvmconf --force ' + generation_path + ' --kver ' + kernel_version + '\'') os.system( 'dracut --xz -v -m "network base nfs" --add "ifcfg livenet systemd systemd-initrd dracut-systemd" --add-drivers xfs --no-hostonly --nolvmconf --force ' + generation_path + ' --kver ' + kernel_version) # Change the permisssions on the generated file logging.info('Changing permission to 0o644 on ' + generation_path) os.chmod(generation_path, 0o644)
def cli_create_golden_image(): # Get all staging images staging_images = NfsStagingImage.get_images() # Check if there are staging images if not staging_images: raise UserWarning( 'No nfs staging images. Golden image creation require an nfs staging image.' ) # Get staging images names staging_images_names = [ staging_image.name for staging_image in staging_images ] # Select a staging image for golden image creation printc('[+] Select the nfs image to use for golden image creation:', Color.GREEN) staging_image_name = select_from_list(staging_images_names) staging_image = ImageManager.get_created_image(staging_image_name) # Condition to test if image name is compliant while True: printc('\n[+] Give a name for your image', Color.GREEN) # Get new image name selected_image_name = input('-->: ').replace(" ", "") if selected_image_name == '': raise UserWarning('Image name cannot be empty !') if not ImageManager.is_image(selected_image_name): break # Else print('Image ' + selected_image_name + ' already exist, use another image name.') # Confirm image creation printc( '\n[+] Would you like to create a new nfs golden image with the following attributes: (yes/no)', Color.GREEN) print(' ├── Image name: \t\t' + selected_image_name) print(' └── Staging image from: \t' + staging_image.name) confirmation = input('-->: ').replace(" ", "") if confirmation == 'yes': # Create the image object NfsGoldenImage(selected_image_name, staging_image) printc('\n[OK] Done.', Color.GREEN) elif confirmation == 'no': printc('\nImage creation cancelled, return to main menu.', Color.YELLOW) return else: raise UserWarning('\nInvalid confirmation !')
def cli_resize_livenet_image(): # Get list of livenet images livenet_images = LivenetImage.get_images() # Check if there are livenet images if not livenet_images: raise UserWarning('No livenet images.') # Get livenet images names unmounted_images_names = [ livenet_image.name for livenet_image in livenet_images if livenet_image.is_mounted is False ] # Check if there are unmounted images # An image must be unmounted to be resized if not unmounted_images_names: raise UserWarning('No unmounted livenet images.') # Select a livenet to mount printc('[+] Select the livenet image to mount:', Color.GREEN) unmounted_image_name = select_from_list(unmounted_images_names) unmounted_image = ImageManager.get_created_image(unmounted_image_name) # Enter new size printc( 'Please enter your new image size:\n(supported units: M=1024*1024, G=1024*1024*1024)\n(Examples: 5120M or 5G)', Color.GREEN) selected_size = input('-->: ') # Check and convert the size image_size = cli_get_size(selected_size) # Check size compliance with livenet image expected size limits if int(image_size) < (LivenetImage.MIN_LIVENET_SIZE) or int(image_size) > ( LivenetImage.MAX_LIVENET_SIZE): raise UserWarning('\nSize out of limits !') # Confirm image resizing printc( '\n[+] Are you sure you want to resize image \'' + unmounted_image.name + '\' with the following size: (yes/no)', Color.GREEN) print(' └── Image size: ' + selected_size) confirmation = input('-->: ').replace(" ", "") if confirmation == 'yes': # Create the image object unmounted_image.resize(image_size) printc('\n[OK] Done.', Color.GREEN) elif confirmation == 'no': printc('\n[+] Image resizing cancelled, return to main menu.', Color.YELLOW) return
def cli_select_created_image(): """Select an image from the list of created images""" # Get created images images_list = ImageManager.get_created_images() if images_list: # Get created images names images_names_list = [image.name for image in images_list] # If there are images if images_names_list: printc('[+] Select the image:\n', Color.BLUE) # Allow the user to select an image name from the list return select_from_list(images_names_list) raise UserWarning('No image to select.')
def cli_unmount_livenet_image(): livenet_images = LivenetImage.get_images() # Check if there are staging images if not livenet_images: raise UserWarning('No livenet images.') # Get staging images names mounted_images_names = [livenet_image.name for livenet_image in livenet_images if livenet_image.is_mounted is True] # Check if there unmounted images if not mounted_images_names: raise UserWarning('No mounted livenet images.') # Select a staging image for golden image creation printc('[+] Select the livenet image to unmount:', Color.GREEN) mounted_image_name = select_from_list(mounted_images_names) mounted_image = ImageManager.get_created_image(mounted_image_name) mounted_image.unmount()
def cli_display_images(): """Display informations about all images""" # Get list of image names image_names = ImageManager.get_image_names() # If there are images if image_names: # For each image name for image_name in image_names: # Get the status of image image_status = ImageManager.get_image_status(image_name) if image_status == ImageManager.ImageStatus.CREATED: printc(' [CREATED]', Color.GREEN) image = ImageManager.get_created_image(image_name) image.cli_display_info() elif image_status == ImageManager.ImageStatus.IN_CREATION: printc(' [IN_CREATION]', Color.ORANGE_BLINK) pid = ImageManager.get_installation_pid(image_name) print(' • Image name: ' + image_name + '\n Installation pid: ' + str(pid)) elif image_status == ImageManager.ImageStatus.CORRUPTED: printc(' [CORRUPTED]', Color.RED) print(' • Image name: ' + image_name) print('') else: raise UserWarning('No images.')
def cli_menu(): """This method is needed for all diskless module to be available by cli interface.""" printc('\n == Welcome to demo image module == \n', Color.GREEN) print('1 - Create my demo image') print('\n Select an action') main_action = input('-->: ') print('') if main_action == '1': # Condition to test if image name is compliant while True: printc('[+] Give a name for your demo image', Color.GREEN) # Get new image name selected_image_name = input('-->: ').replace(" ", "") if selected_image_name == '': raise UserWarning('Image name cannot be empty !') if not ImageManager.is_image(selected_image_name): break # Else print('Image ' + selected_image_name + ' already exist, use another image name.') printc('\nGive a message for your demo image:', Color.GREEN) demo_message = input('-->: ') # Create a DemoImage image DemoImage(selected_image_name, demo_message) # Bad entry else: raise UserWarning( '\'' + main_action + '\' is not a valid entry. Please enter another value.')
def cli_create_livenet_image(): # Get available kernels kernel_list = KernelManager.get_available_kernels() # If there are no kernels aise an exception if not kernel_list: raise UserWarning('No kernel available') # Condition to test if image name is compliant while True: printc('[+] Give a name for your image', Color.GREEN) # Get new image name selected_image_name = input('-->: ').replace(" ", "") if selected_image_name == '': raise UserWarning('Image name cannot be empty !') if not ImageManager.is_image(selected_image_name): break # Else print('Image ' + selected_image_name + ' already exist, use another image name.') # Select the kernel to use printc('\n[+] Select your kernel:', Color.GREEN) selected_kernel = select_from_list(kernel_list) # Manage password printc('\n[+] Give a password for your image', Color.GREEN) selected_password = input( 'Enter clear root password of the new image: ').replace(" ", "") # Select livenet type types_list = [ 'Standard: core (~1.3Gb)', 'Small: openssh, dnf and NetworkManager (~300Mb)', 'Minimal: openssh only (~270Mb)' ] get_type = select_from_list(types_list) if get_type == 'Standard: core (~1.3Gb)': selected_type = LivenetImage.Type.STANDARD elif get_type == 'Small: openssh, dnf and NetworkManager (~300Mb)': selected_type = LivenetImage.Type.SMALL elif get_type == 'Minimal: openssh only (~270Mb)': selected_type = LivenetImage.Type.CORE else: raise UserWarning('Not a valid choice !') # Select livenet size printc( '\nPlease choose image size:\n(supported units: M=1024*1024, G=1024*1024*1024)\n(Examples: 5120M or 5G)', Color.GREEN) selected_size = input('-->: ') # Check and convert the size image_size = cli_get_size(selected_size) # Check size compliance with livenet image expected size limits if int(image_size) < (LivenetImage.MIN_LIVENET_SIZE) or int(image_size) > ( LivenetImage.MAX_LIVENET_SIZE): raise UserWarning('\nSize out of limits !') # Inject ssh key or not printc( '\nEnter path to SSH public key (left empty to disable key injection)', Color.GREEN) selected_ssh_pub_key = input('-->: ') if selected_ssh_pub_key != '' and not os.path.exists(selected_ssh_pub_key): raise UserWarning('\nSSH public key not found ' + selected_ssh_pub_key) if selected_ssh_pub_key == '': selected_ssh_pub_key = None # Activate SELinux or not printc('\nActivate SELinux inside the image (yes/no) ?', Color.GREEN) answer_selinux = input('-->: ') if answer_selinux == 'yes': selinux = True elif answer_selinux == 'no': selinux = False else: raise UserWarning('\nInvalid input !') # Propose to user to install additional packages printc( '\nDo you want to customize your image with additional packages (yes/no) ? ', Color.GREEN) choice = input('-->: ') # Install additional packages if choice == 'yes': # Get package list from user additional_packages = Image.cli_add_packages() # Don't install additional packages elif choice == 'no': additional_packages = None else: raise UserWarning('\nInvalid entry !') # Propose to user to specify a release version printc( '\nSpecify a release version for installation (left empty to not use the --relasever option)', Color.GREEN) release_version = input('-->: ') if release_version == '': release_version = None # Propose to optimize image packages printc( '\nDo you wish tool try to optimize image by using aggressive packages dependencies parameters ? ', Color.GREEN) printc( 'Note that this may collide with additional packages if asked for. (yes/no) ? ', Color.GREEN) answer_optimize = input('-->: ') if answer_optimize == 'yes': optimize = True elif answer_optimize == 'no': optimize = False else: raise UserWarning('\nInvalid input !') # Confirm image creation printc( '\n[+] Would you like to create a new livenet image with the following attributes: (yes/no)', Color.GREEN) print(' ├── Image name: \t\t' + selected_image_name) print(' ├── Image password: \t\t' + selected_password) print(' ├── Image kernel: \t\t' + selected_kernel) print(' ├── Image type: \t\t' + get_type) print(' ├── Image size: \t\t' + selected_size) print(' ├── Optimize packages: \t' + str(optimize)) # Print ssh pub key packages if there is one if selected_ssh_pub_key is not None: print(' ├── SSH pubkey: \t\t' + selected_ssh_pub_key) # Print additional packages if there is if additional_packages is not None: print(' ├── Additional packages: \t' + str(additional_packages)) # Print release version if there is one if release_version is not None: print(' ├── Release version: \t\t' + release_version) print(' └── Enable SELinux: \t\t' + str(selinux)) confirmation = input('-->: ').replace(" ", "") if confirmation == 'yes': # Create the image object LivenetImage(selected_image_name, selected_password, selected_kernel, selected_type, image_size, additional_packages, selected_ssh_pub_key, selinux, release_version, optimize) printc('\n[OK] Done.', Color.GREEN) elif confirmation == 'no': printc('\n[+] Image creation cancelled, return to main menu.', Color.YELLOW) return else: raise UserWarning('\nInvalid confirmation !')
# Just change the value of the level on the line bellow. logging.basicConfig(format='%(levelname)s:%(message)s', level=logging.DEBUG) # Set script banner BANNER = """\n ██████╗ ██╗███████╗██╗ ██╗██╗ ███████╗███████╗███████╗ ██╔══██╗██║██╔════╝██║ ██╔╝██║ ██╔════╝██╔════╝██╔════╝ ██║ ██║██║███████╗█████╔╝ ██║ █████╗ ███████╗███████╗ ██║ ██║██║╚════██║██╔═██╗ ██║ ██╔══╝ ╚════██║╚════██║ ██████╔╝██║███████║██║ ██╗███████╗███████╗███████║███████║ ╚═════╝ ╚═╝╚══════╝╚═╝ ╚═╝╚══════╝╚══════╝╚══════╝╚══════╝ """ # Print script banner printc(BANNER + '\n Entering BlueBanquise diskless manager', Color.BLUE) # Create a main_action variable main_action = '' # Stay on main program after a main action executed by the user while True: # The try/catch manage KeyboardInterrupt and UserWarning program exceptions try: # When we are in the main menu in_main_menu = True # Display main menu options # There is two parts in this menu
def create_new_image(self, my_message, useless_argument): super().create_new_image() # Create the 'my_message attribute' self.my_message = my_message self.generate_files() printc("Image created ! Check images list to look at it.", Color.RED)
def cli_manage_nodes(): # Get all golden images golden_images = NfsGoldenImage.get_images() if not golden_images: raise UserWarning('No nfs golden image to manage.') # Get golden images names golden_images_names = [golden_image.name for golden_image in golden_images] # Select the golden image to manage from list printc('\n[+] Select the golden image to manage:', Color.GREEN) golden_image_name = select_from_list(golden_images_names) golden_image = ImageManager.get_created_image(golden_image_name) # Choose an action for nodes management printc('\n[+] Manages nodes of image ' + golden_image_name, Color.GREEN) print(' 1 - List nodes with the image') print(' 2 - Add nodes with the image') print(' 3 - Remove nodes with the image') action = input('-->: ') # Print golden image nodes if action == '1': nodeset = golden_image.get_nodes() print(nodeset) printc('\n[OK] Done.', Color.GREEN) # Add some nodes to the image elif action == '2': printc('\n[+] Actual image NodeSet is: ' + str(golden_image.nodes), Color.GREEN) printc('[+] Please enter nodes range to add:', Color.GREEN) nodes_range = input('-->: ').replace(" ", "") # Test if nodes_range is a valid range try: golden_image.add_nodes(nodes_range) printc('\n[OK] Done.', Color.GREEN) except KeyError: raise UserWarning('The Node you have entered is not compliant.') # Delete nodes from image elif action == '3': printc('\n[+] Please enter nodes range to remove:', Color.GREEN) nodes_range = input('-->: ').replace(" ", "") # Test if nodes_range is a valid range try: golden_image.remove_nodes(nodes_range) printc('\n[OK] Done.', Color.GREEN) except KeyError: raise UserWarning('The Node you have entered is not compliant.') else: raise UserWarning('Not a valid entry')
def cli_create_staging_image(): # Get available kernels kernel_list = KernelManager.get_available_kernels() # If there are no kernels aise an exception if not kernel_list: raise UserWarning('No kernel available') # Condition to test if image name is compliant while True: printc('[+] Give a name for your image', Color.GREEN) # Get new image name selected_image_name = input('-->: ').replace(" ", "") if selected_image_name == '': raise UserWarning('Image name cannot be empty !') if not ImageManager.is_image(selected_image_name): break # Else print('Image ' + selected_image_name + ' already exist, use another image name.') # Select the kernel to use printc('\n[+] Select your kernel:', Color.GREEN) selected_kernel = select_from_list(kernel_list) # Manage password printc('\n[+] Give a password for your image', Color.GREEN) selected_password = input( 'Please enter clear root password of the new image: ').replace( " ", "") # Propose to user to install additional packages printc( '\nDo you want to customize your image with additional packages? (yes/no)', Color.GREEN) choice = input('-->: ') # Install addictional packages if choice == 'yes': # Get package list from user additional_packages = Image.cli_add_packages() # Don't install additional packages elif choice == 'no': additional_packages = None else: raise UserWarning('\nInvalid entry !') # Propose to user to specify a release version printc( '\nSpecify a release version for installation (left empty to not use the --relasever option)', Color.GREEN) release_version = input('-->: ') if release_version == '': release_version = None # Confirm image creation printc( '\n[+] Would you like to create a new nfs staging image with the following attributes: (yes/no)', Color.GREEN) print(' ├── Image name: \t\t' + selected_image_name) print(' ├── Image password : \t\t' + selected_password) # Print additional packages if there is if additional_packages is not None: print(' ├── Additional packages: \t' + str(additional_packages)) # Print release version if there is one if release_version is not None: print(' ├── Release version: \t\t' + release_version) print(' └── Image kernel: \t\t' + selected_kernel) confirmation = input('-->: ').replace(" ", "") if confirmation == 'yes': # Create the image object NfsStagingImage(selected_image_name, selected_password, selected_kernel, additional_packages, release_version) printc('\n[OK] Done.', Color.GREEN) elif confirmation == 'no': printc('\n[+] Image creation cancelled, return to main menu.', Color.YELLOW) return else: raise UserWarning('\nInvalid confirmation !')