Exemplo n.º 1
0
    def _platform_detach_volume(self, volume):
        """
        Detach a volume using the Google Cloud Platform API
        Some specific steps are performed here:
            - Check if the selected volume is a boot disk

        Args:
            volume (<volume>): The volume to detach

        Returns:
            bool: True if the volume is successfully detached, False otherwise
        """
        # Search for the instance the volume is attached to
        instance = self._get_instance_from_volume(volume)
        if instance is None:
            return False
        if not self._is_volume_removable(volume):
            SimpleTUI.msg_dialog(
                "Detaching status",
                "This volume is mounted as boot disk and cannot be detached until the VM is stopped!",
                SimpleTUI.DIALOG_ERROR)
            return
        result = self.gcp_client.detach_volume(volume, instance)
        if result:
            while True:
                # No direct way to refresh a Volume status, so we look if
                # it is still attached to its previous instance
                updated_volume = self.gcp_client.ex_get_volume(volume.name)
                if not self._platform_is_volume_attached(updated_volume):
                    break
                time.sleep(3)
        return result
Exemplo n.º 2
0
    def _platform_override_menu(self, menu, choice):
        """
        Override a menu voice

        Args:
            menu (str): a menu identifier
            choice (int): a menu entry index

        Returns:
            int: 0 for normal, 1 for going back to the main menu of EasyCloud,
                 2 for closing the whole application
        """
        if menu == "floating_ips":
            if choice == 5:  # Detach floating ip
                SimpleTUI.msg_dialog(
                    "Detach Floating IP",
                    "Detaching an IP address from an instance is not supported on GCP: \n"
                    +
                    "an instance must always have an IP associated while running.\n"
                    +
                    "However, you can assign another address to the desired instance to\n"
                    + "replace the current one.", SimpleTUI.DIALOG_INFO)
                return 0
            SimpleTUI.error("Unavailable choice!")
            SimpleTUI.pause()
            SimpleTUI.clear_console()
        pass
Exemplo n.º 3
0
 def load_all_modules(self, no_libs_check):
     """
     Loads all the Modules from the modules folder
     """
     _all_modules = list(iter_modules(modules.__path__))
     for _module in _all_modules:
         module_object = Module(_module[1])
         try:
             if no_libs_check or self.check_dependencies(module_object):
                 module_object.load_manager_class()
                 self.loaded_modules.append(module_object)
         except ImportError as e:
             SimpleTUI.msg_dialog("Missing packages", "There was an error while importing a package for the\n" +
                                  module_object.platform_name + " module: \n\n" + str(e) + "\n\n" +
                                  "This module won't be loaded.", SimpleTUI.DIALOG_ERROR)
Exemplo n.º 4
0
 def _platform_extra_menu(self):
     """
     Print the extra Functions Menu (specific for each platform)
     """
     while (True):
         menu_header = self.platform_name + " Extra Commands"
         menu_subheader = [
             "Region: \033[1;94m" + self._platform_get_region() + "\033[0m"
         ]
         menu_items = [
             "Promote ephimeral IP to static", "Demote a static IP",
             "List instances for all the regions",
             "List volumes for all the regions",
             "List floating ips for all the regions",
             "Back to the Main Menu"
         ]
         choice = SimpleTUI.print_menu(menu_header, menu_items,
                                       menu_subheader)
         if choice == 1:  # Promote IP
             self.promote_ephimeral_ip()
         elif choice == 2:  # Demote IP
             answer = SimpleTUI.yn_dialog(
                 "Demotion status",
                 "You can demote a static IP easily deleting it through \"Manage floating IPs\" > \"Release a reserved Floating IP\".\n"
                 +
                 "NOTE: the static IP won't be removed from the associated instance until the latter is stopped/rebooted/deleted.\n"
                 +
                 "For more infos about Ephimeral/Static IPs on GCP, please visit https://cloud.google.com/compute/docs/ip-addresses/.\n"
                 +
                 "Would you like to start the \"Release a reserved Floating IP\" wizard now?",
                 SimpleTUI.DIALOG_INFO)
             if answer:
                 self.release_floating_ip()
         elif choice == 3:  # List all the instances (Global)
             SimpleTUI.list_dialog("Instances available (Global view)",
                                   list_printer=self.print_global_instances)
         elif choice == 4:  # List all the volumes (Global)
             SimpleTUI.list_dialog("Volumes available (Global view)",
                                   list_printer=self.print_global_volumes)
         elif choice == 5:  # List all the floating ips (Global)
             SimpleTUI.list_dialog(
                 "Floating IPs available (Global view)",
                 list_printer=self.print_global_floating_ips)
         elif choice == 6:
             break
         else:
             SimpleTUI.msg_dialog("Error", "Unimplemented functionality",
                                  SimpleTUI.DIALOG_ERROR)
Exemplo n.º 5
0
 def _platform_extra_menu(self):
     """
     Print the extra Functions Menu (specific for each platform)
     """
     while (True):
         menu_header = self.platform_name + " Extra Commands"
         menu_subheader = [
             "Region: \033[1;94m" + self._platform_get_region() + "\033[0m"
         ]
         menu_items = ["Back to the Main Menu"]
         choice = SimpleTUI.print_menu(menu_header, menu_items,
                                       menu_subheader)
         # if choice == 1 and self._is_barebone():  # Blazar menu
         if choice == 1:
             break
         else:
             SimpleTUI.msg_dialog("Error", "Unimplemented functionality",
                                  SimpleTUI.DIALOG_ERROR)
Exemplo n.º 6
0
    def _platform_delete_volume(self, volume):
        """
        Delete a volume using the Google Cloud Platform API
        Some specific steps are performed here:
            - Check if the selected volume is a boot disk

        Args:
            volume (<volume>): The volume to delete

        Returns:
            bool: True if the volume is successfully deleted, False otherwise
        """
        if not self._is_volume_removable(volume):
            SimpleTUI.msg_dialog(
                "Volume deletion",
                "This volume is mounted as boot disk and cannot be detached until the VM is stopped!",
                SimpleTUI.DIALOG_ERROR)
            return
        return self.gcp_client.destroy_volume(volume)
Exemplo n.º 7
0
 def promote_ephimeral_ip(self):
     """
     Promote an Ephimeral IP to a Static one
     For more infos about Ephimeral/Static IPs on GCP, please visit
     https://cloud.google.com/compute/docs/ip-addresses/
     """
     # Select an instance
     floating_ip = None
     while (True):
         instance_index = SimpleTUI.list_dialog(
             "Instances available",
             self.print_all_instances,
             question=
             "Select the instance which floating IP has to be promoted to \"static\""
         )
         if instance_index is None:
             return
         instance = self.instances[instance_index - 1]
         # Check if the instance has an IP assigned (e.g. no IP is assigned while stopped)
         if len(instance.public_ips) == 0 or None in instance.public_ips:
             SimpleTUI.msg_dialog(
                 "Promotion status",
                 "This instance has no available floating IPs to promote!",
                 SimpleTUI.DIALOG_ERROR)
         # Check if the instance has already a static IP assigned
         elif self._is_instance_floating_ip_static(instance):
             SimpleTUI.msg_dialog(
                 "Promotion status",
                 "This instance floating IP is already promoted to \"static\"!",
                 SimpleTUI.DIALOG_ERROR)
         # Continue the ephimeral to static conversion
         else:
             floating_ip = instance.public_ips[0]
             break
     # Specify address name
     address_name = SimpleTUI.input_dialog(
         "Static Floating IP Name",
         question="Specify a name for the new Static Floating IP",
         return_type=str,
         regex="^[a-zA-Z0-9-]+$")
     if address_name is None:
         return
     if self._promote_ephimeral_ip_to_static(floating_ip, address_name):
         SimpleTUI.msg_dialog("Static Floating IP Promotion",
                              "Floating IP promoted!",
                              SimpleTUI.DIALOG_SUCCESS)
     else:
         SimpleTUI.msg_dialog(
             "Static Floating IP Promotion",
             "There was an error while promoting this Floating IP!",
             SimpleTUI.DIALOG_ERROR)
Exemplo n.º 8
0
    def menu(self):
        """
        Prints the modules menu
        """
        global kill

        while True:
            # Header creation
            menu_header = "******************** EasyCloud ********************"
            # Subheader creation
            disclaimer = "\033[34;1mThis is a proof-of-concept build, not suitable\nfor production use.\033[0m\n"
            debug_status = None
            hffr_status = None
            if "LIBCLOUD_DEBUG" in environ:
                debug_status = "\033[93mLibcloud Debug Mode ON\033[0m"
            else:
                debug_status = "\033[90mLibcloud Debug Mode OFF\033[0m"
            if "LIBCLOUD_DEBUG_PRETTY_PRINT_RESPONSE" in environ and environ["LIBCLOUD_DEBUG_PRETTY_PRINT_RESPONSE"] == "1":
                hffr_status = "\033[93mLibcloud Human friendly formatted response ON\033[0m"
            else:
                hffr_status = "\033[90mLibcloud Human friendly formatted response OFF\033[0m"
            menu_subheader = [disclaimer, debug_status, hffr_status]
            # Menu items creation
            menu_items = []
            for module in self.loaded_modules:
                menu_items.append(module.platform_name)
            menu_items.append("Close application")
            # Menu print
            choice = SimpleTUI.print_menu(menu_header, menu_items,
                                          subheader_items=menu_subheader,
                                          custom_question="Select a platform")
            try:
                if(choice >= 1 and choice <= len(self.loaded_modules)):
                    return self.loaded_modules[choice - 1]  # Load a module
                elif(choice == len(self.loaded_modules) + 1):  # Close application
                    self.close(0)
                else:
                    SimpleTUI.msg_dialog("Error", "Unimplemented functionality", SimpleTUI.DIALOG_ERROR)
            except Exception as e:
                SimpleTUI.exception_dialog(e)
Exemplo n.º 9
0
    def check_dependencies(self, module):
        """
        Check if all the dependencies (pip packages) are satisfied for
        a certain module, and can install them if the user approves

        Args:
            module (Module): a module object (no manager class must be loaded
                             through load_manager_class method of this object)

        Returns:
            bool: the result of the check
        """
        required_packages = getattr(module, "dependencies")
        installed_packages = subprocess.check_output(['pip3', 'list', '--format=json'], stderr=subprocess.STDOUT).decode()
        missing_packages_names = []  # package names displayed to the user
        missing_packages_commands = []  # packages names/urls passed to pip3
        for required_package in required_packages:
            # Format: pip-package-name:package-url|package-git (the latter is optional)
            #
            # Symbolic: pip package name (the one you see with "pip3 list")
            # Package URL (optional): package url from where pip3 will download the library
            # Package Git (optional): package git url in the form git+git://github.com/my_user/my_project.git(@branch)
            #
            # e.g. libcloud:apache-libcloud
            required_package_data = required_package.split(":", 1)
            if required_package_data[0] not in installed_packages:
                missing_packages_names.append(required_package_data[0])
                if len(required_package_data) == 2:
                    missing_packages_commands.append(required_package_data[1])
                else:
                    missing_packages_commands.append(required_package_data[0])
        if len(missing_packages_names) > 0:
            packages_list = ""
            for missing_package_name in missing_packages_names:
                packages_list += "- " + missing_package_name + "\n"
            choice = SimpleTUI.yn_dialog("Missing packages", "The following packages are required by the " + module.platform_name + " module:\n" +
                                         "\n" + packages_list + "\nIf these packages are not installed, this module won't be loaded.\n" +
                                         "Do you want to install them through pip?", warning=True)
            if choice:
                SimpleTUI.msg_dialog("Library installer", "Installing the required libraries, this can take a bit...",
                                     SimpleTUI.DIALOG_INFO, pause_on_exit=False, clear_on_exit=False)
                if self.install_libraries(missing_packages_commands):
                    SimpleTUI.msg_dialog("Library installer", "All the packages for " + module.platform_name + "\n" +
                                         "were successfully installed!\n\n" + packages_list, SimpleTUI.DIALOG_SUCCESS)
                    return True
                else:
                    SimpleTUI.msg_dialog("Library installer", "There was an error while installing the missing packages\n" +
                                         "for " + module.platform_name + ".\n"
                                         "Please check logs" + sep + "installer.log in the main directory for details.", SimpleTUI.DIALOG_ERROR)
                    return False
            return False
        return True
Exemplo n.º 10
0
    def _platform_associate_floating_ip(self, floating_ip, instance):
        """
        Associate a floating IP to an instance using the Google Cloud Platform API
        Some specific steps are performed here:
            - NIC (Network interface controller) selection
            - Access config name

        Args:
            floating_ip (GCEAddress): The floating IP to attach
            instance (Node): The instance where the floating IP is to be assigned

        Returns:
            bool: True if the floating IP is successfully associated, False otherwise
        """
        # Set an instance, as required by print_all_nics()
        self.current_instance = instance
        nic_index = SimpleTUI.list_dialog(
            "NICs available",
            self.print_all_nics,
            question="Select the VM NIC to assign this IP")
        if nic_index is None:
            return
        nic = instance.extra["networkInterfaces"][
            nic_index - 1]  # serve nome per rimuovere
        # Check if there's already an active Access Configuration and ask the user for confirm
        remove_old_access_config = False
        if self._nic_has_access_config(nic):
            choice = SimpleTUI.yn_dialog(
                "Access Configuration Overwrite",
                "Warning: there's already an access configuration associated to this NIC.\n"
                +
                "Do you really want to continue (the current access configuration will be overwritten)?",
                warning=True)
            if not choice:
                return
            remove_old_access_config = True
        # Access Configuration name
        access_config_name = SimpleTUI.input_dialog(
            "Access configuration",
            question="Specify an access configuration name",
            return_type=str,
            regex="^[a-zA-Z0-9-]+$")
        if access_config_name is None:
            return
        # Remove the old access configuration if it's already existing
        if remove_old_access_config:
            SimpleTUI.msg_dialog("Access Configuration Overwrite",
                                 "Removing old access configuration...",
                                 SimpleTUI.DIALOG_INFO,
                                 pause_on_exit=False,
                                 clear_on_exit=False)
            if not self._delete_access_config(instance, nic):
                SimpleTUI.msg_dialog(
                    "Access Configuration Overwrite",
                    "There was an error while removing the current access configuration!",
                    SimpleTUI.DIALOG_ERROR)
                return
        # Associate the Access Configuration to the NIC
        if self.gcp_client.ex_add_access_config(node=instance,
                                                name=access_config_name,
                                                nic=nic,
                                                nat_ip=floating_ip.address,
                                                config_type="ONE_TO_ONE_NAT"):
            return True
        return False