Example #1
0
    def set_shared(self, shared):
        """Set the shared status of the storage backend"""
        # Check permissions
        self._get_registered_object('auth').assert_permission(PERMISSIONS.MANAGE_STORAGE_BACKEND)

        ArgumentValidator.validate_boolean(shared)

        # Check if there's no change to configuration
        if self.shared == shared:
            raise NoConfigurationChangeError('Storage backend is already set to %s' % str(shared))

        if self.shared and self.in_use():
            raise CannotUnshareInUseStorageBackendError(
                'Storage backend is in use, so cannot unshare')

        def update_shared_config(config):
            """Set sared parameter to new value"""
            config['shared'] = shared
        self.update_config(update_shared_config, 'Update shared status to %s' % shared)

        if self._is_cluster_master:
            def update_shared_remote_nodes(connection):
                """Update shared status of remote nodes"""
                remote_storage_backend = self.get_remote_object(node_object=connection)
                remote_storage_backend.set_shared(shared)
            self._get_registered_object('cluster').run_remote_command(
                update_shared_remote_nodes)
Example #2
0
    def add_user_permission_group(self,
                                  permission_group,
                                  user_object,
                                  vm_object=None,
                                  ignore_duplicate=False):
        """Add a user to a permissions group on a VM object."""
        assert permission_group in PERMISSION_GROUPS.keys()
        assert isinstance(
            self._convert_remote_object(user_object),
            self._get_registered_object('user_factory').USER_CLASS)
        assert isinstance(
            self._convert_remote_object(vm_object),
            self._get_registered_object(
                'virtual_machine_factory').VIRTUAL_MACHINE_CLASS)
        ArgumentValidator.validate_boolean(ignore_duplicate)

        # Check if user running script is able to add users to permission group
        if not (self.is_superuser() or (vm_object and self.assert_permission(
                PERMISSIONS.MANAGE_VM_USERS, vm_object)
                                        and permission_group == 'user')):
            raise InsufficientPermissionsException(
                'VM owners cannot add manager other owners')

        user_object = self._convert_remote_object(user_object)
        vm_object = self._convert_remote_object(
            vm_object) if vm_object is not None else None
        username = user_object.get_username()

        # Check if user is already in the group
        if (vm_object):
            config_object = vm_object.get_config_object()
        else:
            config_object = MCVirtConfig()

        if (username not in self.get_users_in_permission_group(
                permission_group, vm_object)):

            # Add user to permission configuration for VM
            def add_user_to_config(config):
                config['permissions'][permission_group].append(username)

            config_object.update_config(
                add_user_to_config, 'Added user \'%s\' to group \'%s\'' %
                (username, permission_group))

            # @TODO FIX ME
            if self._is_cluster_master:
                cluster_object = self._get_registered_object('cluster')
                vm_name = vm_object.get_name() if vm_object else None
                cluster_object.run_remote_command(
                    'auth-add_user_permission_group', {
                        'permission_group': permission_group,
                        'username': username,
                        'vm_name': vm_name
                    })

        elif not ignore_duplicate:
            raise DuplicatePermissionException(
                'User \'%s\' already in group \'%s\'' %
                (username, permission_group))
Example #3
0
    def add_user(self, user, virtual_machine=None, ignore_duplicate=False):
        """Add uesr to group"""
        assert isinstance(self._convert_remote_object(user),
                          self._get_registered_object('user_factory').USER_CLASS)
        if virtual_machine:
            assert isinstance(self._convert_remote_object(virtual_machine),
                              self._get_registered_object(
                                  'virtual_machine_factory').VIRTUAL_MACHINE_CLASS)
        ArgumentValidator.validate_boolean(ignore_duplicate)

        if virtual_machine is not None:
            virtual_machine = self._convert_remote_object(virtual_machine)

        # Check if user running script is able to add users to permission group
        self._get_registered_object('auth').assert_permission(PERMISSIONS.MANAGE_GROUP_MEMBERS,
                                                              vm_object=virtual_machine)

        # Convert remote objects
        user = self._convert_remote_object(user)

        # Ensure that the user is not already in the group
        if (user in self.get_users(virtual_machine=virtual_machine) and
                not ignore_duplicate):
            raise DuplicatePermissionException('User %s already in group %s' %
                                               (user.get_username(), self.name))

        cluster = self._get_registered_object('cluster')
        if virtual_machine:
            # Convert remote objects
            self.add_user_to_vm_config(
                user, virtual_machine,
                nodes=cluster.get_nodes(include_local=True))
        else:
            self.add_user_to_config(user, nodes=cluster.get_nodes(include_local=True))
Example #4
0
    def getAllVmNames(self, node=None):
        """Returns a list of all VMs within the cluster or those registered on a specific node"""
        if node is not None:
            ArgumentValidator.validate_hostname(node)

        # If no node was defined, check the local configuration for all VMs
        if node is None:
            return [vm['name'] for vm in VirtualMachineConfig.get_global_config().values()]

        elif node == get_hostname():
            # @TODO - Why is this using libvirt?! Should use
            #         VM objects (i.e. config file to determine)
            #         and use a seperate function to get libvirt
            #         registered VMs
            # Obtain array of all domains from libvirt
            all_domains = self._get_registered_object(
                'libvirt_connector').get_connection().listAllDomains()
            return [vm.name() for vm in all_domains]

        else:
            # Return list of VMs registered on remote node
            cluster = self._get_registered_object('cluster')

            def remote_command(node_connection):
                """Get virtual machine names from remote node"""
                virtual_machine_factory = node_connection.get_connection('virtual_machine_factory')
                return virtual_machine_factory.getAllVmNames(node=node)
            return cluster.run_remote_command(callback_method=remote_command, nodes=[node])[node]
Example #5
0
    def set_autostart_interval(self, interval_time):
        """Update the autostart interval for the node"""
        self._get_registered_object('auth').assert_permission(PERMISSIONS.MANAGE_NODE)
        ArgumentValidator.validate_integer(interval_time)
        interval_time = int(interval_time)

        def update_config(config):
            config['autostart_interval'] = interval_time
        self._get_registered_object('mcvirt_config')().update_config(update_config,
                                                                     'Update autostart interval')

        if self._is_cluster_master:

            def remote_update(node):
                autostart_watchdog = node.get_connection('autostart_watchdog')
                autostart_watchdog.set_autostart_interval(interval_time)
            cluster = self._get_registered_object('cluster')
            cluster.run_remote_command(remote_update)

        # If the timer has been set to 0, disable the timer
        if interval_time == 0:
            self.repeat = False
            self.timer.cancel()
            self.timer = None
        else:
            # Otherwise update the running timer
            if self.timer is None:
                self.repeat = True
                self.repeat_run()
Example #6
0
    def check_exists(self, vm_name):
        """Determines if a VM exists, given a name"""
        try:
            ArgumentValidator.validate_hostname(vm_name)
        except (MCVirtTypeError, InvalidVirtualMachineNameException):
            return False

        return (vm_name in self.getAllVmNames())
Example #7
0
 def getVirtualMachineByName(self, vm_name):
     """Obtain a VM object, based on VM name"""
     ArgumentValidator.validate_hostname(vm_name)
     if vm_name not in Factory.CACHED_OBJECTS:
         vm_object = VirtualMachine(self, vm_name)
         self._register_object(vm_object)
         Factory.CACHED_OBJECTS[vm_name] = vm_object
     return Factory.CACHED_OBJECTS[vm_name]
Example #8
0
    def check_exists(self, id_):
        """Determines if a VM exists, given a name"""
        try:
            ArgumentValidator.validate_id(id_, VirtualMachine)
        except (MCVirtTypeError, InvalidVirtualMachineNameException):
            return False

        return id_ in self.get_all_vm_ids()
Example #9
0
 def getVirtualMachineByName(self, vm_name):
     """Obtain a VM object, based on VM name"""
     ArgumentValidator.validate_hostname(vm_name)
     if vm_name not in Factory.CACHED_OBJECTS:
         vm_object = VirtualMachine(self, vm_name)
         self._register_object(vm_object)
         Factory.CACHED_OBJECTS[vm_name] = vm_object
     return Factory.CACHED_OBJECTS[vm_name]
Example #10
0
    def check_exists_by_name(self, name):
        """Determines if a VM exists, given a name"""
        try:
            ArgumentValidator.validate_hostname(name)
        except (MCVirtTypeError, InvalidVirtualMachineNameException):
            return False

        return name in self.getAllVmNames()
Example #11
0
    def set_cluster_ip_address(self, ip_address):
        """Update the cluster IP address for the node."""
        self._get_registered_object('auth').assert_permission(PERMISSIONS.MANAGE_NODE)

        ArgumentValidator.validate_ip_address(ip_address)

        # Update global MCVirt configuration
        def update_config(config):
            config['cluster']['cluster_ip'] = ip_address
        mcvirt_config = MCVirtConfig()
        mcvirt_config.update_config(update_config, 'Set node cluster IP address to %s' %
                                                   ip_address)
Example #12
0
    def set_global_interval(self, interval):
        """Set global default watchdog check interval"""
        ArgumentValidator.validate_positive_integer(interval)

        # Check permissions
        self._get_registered_object('auth').assert_permission(
            PERMISSIONS.MANAGE_GLOBAL_WATCHDOG)

        self.update_watchdog_config(
            change_dict={'interval': interval},
            reason='Update global watchdog interval',
            nodes=self._get_registered_object('cluster').get_nodes(include_local=True))
Example #13
0
    def set_global_reset_fail_count(self, count):
        """Set global default watchdog reset fail count"""
        ArgumentValidator.validate_positive_integer(count)

        # Check permissions
        self._get_registered_object('auth').assert_permission(
            PERMISSIONS.MANAGE_GLOBAL_WATCHDOG)

        self.update_watchdog_config(
            change_dict={'reset_fail_count': count},
            reason='Update global watchdog reset fail count',
            nodes=self._get_registered_object('cluster').get_nodes(include_local=True))
Example #14
0
    def set_global_boot_wait(self, wait):
        """Set the global default boot wait period"""
        ArgumentValidator.validate_positive_integer(wait)

        # Check permissions
        self._get_registered_object('auth').assert_permission(
            PERMISSIONS.MANAGE_GLOBAL_WATCHDOG)

        self.update_watchdog_config(
            change_dict={'boot_wait': wait},
            reason='Update global watchdog boot wait period',
            nodes=self._get_registered_object('cluster').get_nodes(include_local=True))
Example #15
0
    def set_cluster_ip_address(self, ip_address):
        """Update the cluster IP address for the node."""
        self._get_registered_object('auth').assert_permission(PERMISSIONS.MANAGE_NODE)

        ArgumentValidator.validate_ip_address(ip_address)

        # Update global MCVirt configuration
        def update_config(config):
            config['cluster']['cluster_ip'] = ip_address
        mcvirt_config = MCVirtConfig()
        mcvirt_config.update_config(update_config, 'Set node cluster IP address to %s' %
                                                   ip_address)
Example #16
0
    def set_storage_volume_group(self, volume_group):
        """Update the MCVirt configuration to set the volume group for VM storage."""
        self._get_registered_object('auth').assert_permission(PERMISSIONS.MANAGE_NODE)

        ArgumentValidator.validate_vg_name(volume_group)

        # Update global MCVirt configuration
        def update_config(config):
            config['vm_storage_vg'] = volume_group
        mcvirt_config = MCVirtConfig()
        mcvirt_config.update_config(update_config,
                                    'Set virtual machine storage volume group to %s' %
                                    volume_group)
Example #17
0
    def get_virtual_machine_by_name(self, vm_name):
        """Obtain a VM object, based on VM name"""
        ArgumentValidator.validate_hostname(vm_name)
        name_id_dict = {
            val['name']: key
            for key, val in VirtualMachineConfig.get_global_config().items()
        }
        if vm_name not in name_id_dict:
            raise VirtualMachineDoesNotExistException(
                'Error: Virtual Machine does not exist: %s' % vm_name
            )

        return self.get_virtual_machine_by_id(name_id_dict[vm_name])
Example #18
0
    def set_storage_volume_group(self, volume_group):
        """Update the MCVirt configuration to set the volume group for VM storage."""
        self._get_registered_object('auth').assert_permission(PERMISSIONS.MANAGE_NODE)

        ArgumentValidator.validate_vg_name(volume_group)

        # Update global MCVirt configuration
        def update_config(config):
            config['vm_storage_vg'] = volume_group
        mcvirt_config = MCVirtConfig()
        mcvirt_config.update_config(update_config,
                                    'Set virtual machine storage volume group to %s' %
                                    volume_group)
Example #19
0
    def add_user_permission_group(self, permission_group, user_object,
                                  vm_object=None, ignore_duplicate=False):
        """Add a user to a permissions group on a VM object."""
        assert permission_group in PERMISSION_GROUPS.keys()
        assert isinstance(self._convert_remote_object(user_object),
                          self._get_registered_object('user_factory').USER_CLASS)
        assert isinstance(self._convert_remote_object(vm_object),
                          self._get_registered_object(
                              'virtual_machine_factory').VIRTUAL_MACHINE_CLASS)
        ArgumentValidator.validate_boolean(ignore_duplicate)

        # Check if user running script is able to add users to permission group
        if not (self.is_superuser() or
                (vm_object and self.assert_permission(PERMISSIONS.MANAGE_VM_USERS,
                                                      vm_object) and
                 permission_group == 'user')):
            raise InsufficientPermissionsException('VM owners cannot add manager other owners')

        user_object = self._convert_remote_object(user_object)
        vm_object = self._convert_remote_object(vm_object) if vm_object is not None else None
        username = user_object.get_username()

        # Check if user is already in the group
        if (vm_object):
            config_object = vm_object.get_config_object()
        else:
            config_object = MCVirtConfig()

        if (username not in self.get_users_in_permission_group(permission_group, vm_object)):

            # Add user to permission configuration for VM
            def add_user_to_config(config):
                config['permissions'][permission_group].append(username)

            config_object.update_config(add_user_to_config, 'Added user \'%s\' to group \'%s\'' %
                                                            (username, permission_group))

            # @TODO FIX ME
            if self._is_cluster_master:
                cluster_object = self._get_registered_object('cluster')
                vm_name = vm_object.get_name() if vm_object else None
                cluster_object.run_remote_command('auth-add_user_permission_group',
                                                  {'permission_group': permission_group,
                                                   'username': username,
                                                   'vm_name': vm_name})

        elif not ignore_duplicate:
            raise DuplicatePermissionException(
                'User \'%s\' already in group \'%s\'' % (username, permission_group)
            )
Example #20
0
    def remove_permission(self, permission):
        """Remove a permission from the group"""
        self._get_registered_object('auth').assert_permission(PERMISSIONS.MANAGE_GROUPS)

        ArgumentValidator.validate_permission(permission)
        permission_enum = PERMISSIONS[permission]

        if permission_enum not in self.get_permissions():
            raise GroupDoesNotContainPermissionError(
                'Group \'%s\' does not contain permission \'%s\'' %
                (self.name, permission))

        cluster = self._get_registered_object('cluster')
        self.remove_permission_from_config(permission, nodes=cluster.get_nodes(include_local=True))
Example #21
0
    def checkName(self, name, ignore_exists=False):
        try:
            ArgumentValidator.validate_hostname(name)
        except MCVirtTypeError:
            raise InvalidVirtualMachineNameException(
                'Error: Invalid VM Name - VM Name can only contain 0-9 a-Z and dashes'
            )

        if len(name) < 3:
            raise InvalidVirtualMachineNameException('VM Name must be at least 3 characters long')

        if self.check_exists_by_name(name) and not ignore_exists:
            raise VmAlreadyExistsException('VM already exists')

        return True
Example #22
0
    def add_permission(self, permission):
        """Add a permission to the group"""
        self._get_registered_object('auth').assert_permission(PERMISSIONS.MANAGE_GROUPS)

        # Check that permission is valid
        ArgumentValidator.validate_permission(permission)

        permission_enum = PERMISSIONS[permission]
        if permission_enum in self.get_permissions():
            raise GroupAlreadyContainsPermissionError(
                'Group \'%s\' already contains permission \'%s\'' %
                (self.name, permission))

        cluster = self._get_registered_object('cluster')
        self.add_permission_to_config(permission, nodes=cluster.get_nodes(include_local=True))
Example #23
0
    def checkName(self, name, ignore_exists=False):
        try:
            ArgumentValidator.validate_hostname(name)
        except MCVirtTypeError:
            raise InvalidVirtualMachineNameException(
                'Error: Invalid VM Name - VM Name can only contain 0-9 a-Z and dashes'
            )

        if len(name) < 3:
            raise InvalidVirtualMachineNameException(
                'VM Name must be at least 3 characters long')

        if self.check_exists(name) and not ignore_exists:
            raise VmAlreadyExistsException('VM already exists')

        return True
Example #24
0
    def getAllVmNames(self, node=None):
        """Returns a list of all VMs within the cluster or those registered on a specific node"""
        if node is not None:
            ArgumentValidator.validate_hostname(node)
        # If no node was defined, check the local configuration for all VMs
        if (node is None):
            return MCVirtConfig().get_config()['virtual_machines']
        elif node == get_hostname():
            # Obtain array of all domains from libvirt
            all_domains = self._get_registered_object(
                'libvirt_connector').get_connection().listAllDomains()
            return [vm.name() for vm in all_domains]
        else:
            # Return list of VMs registered on remote node
            cluster = self._get_registered_object('cluster')

            def remote_command(node_connection):
                virtual_machine_factory = node_connection.get_connection('virtual_machine_factory')
                return virtual_machine_factory.getAllVmNames(node=node)
            return cluster.run_remote_command(callback_method=remote_command, nodes=[node])[node]
Example #25
0
    def add_superuser(self, user_object, ignore_duplicate=False):
        """Add a new superuser."""
        assert isinstance(
            self._convert_remote_object(user_object),
            self._get_registered_object('user_factory').USER_CLASS)
        ArgumentValidator.validate_boolean(ignore_duplicate)

        # Ensure the user is a superuser
        if not self.is_superuser():
            raise InsufficientPermissionsException(
                'User must be a superuser to manage superusers')
        user_object = self._convert_remote_object(user_object)
        username = user_object.get_username()

        mcvirt_config = MCVirtConfig()

        # Ensure user is not already a superuser
        if username not in self.get_superusers():

            def update_config(config):
                config['superusers'].append(username)

            mcvirt_config.update_config(update_config,
                                        'Added superuser \'%s\'' % username)

        elif not ignore_duplicate:
            raise DuplicatePermissionException(
                'User \'%s\' is already a superuser' % username)

        if self._is_cluster_master:

            def remote_command(connection):
                remote_user_factory = connection.get_connection('user_factory')
                remote_user = remote_user_factory.get_user_by_username(
                    user_object.get_username())
                remote_auth = connection.get_connection('auth')
                remote_auth.add_superuser(remote_user,
                                          ignore_duplicate=ignore_duplicate)

            cluster = self._get_registered_object('cluster')
            cluster.run_remote_command(remote_command)
Example #26
0
    def get_logs(self, start_log=None, back=0, newer=False):
        """Return a dict containing log information"""
        if start_log is not None:
            ArgumentValidator.validate_integer(start_log)
        ArgumentValidator.validate_integer(back)
        ArgumentValidator.validate_boolean(newer)

        if start_log is None:
            start_log = len(Logger.LOGS) - 1

        if start_log < 0:
            start_log = 0
        if start_log > (len(Logger.LOGS) - 1):
            start_log = len(Logger.LOGS) - 1

        if back:
            start = 0 if (start_log - back) < 0 else (len(Logger.LOGS) - back)
            finish = start_log + 1
        elif newer:
            start = start_log + 1
            # Length would provide an indicy out of the range,
            # since len(['a']) = 1, but ['a'][1] == error
            # However, this is made up for the fact that range(0, 2) = [0, 1]
            finish = len(Logger.LOGS)
        else:
            # Start at the current log, to return it
            # Finish at current log + 1 as range(1, 2) = [1]
            start = start_log
            finish = start_log + 1

        return_logs = {}
        for itx in range(start, finish):
            if itx < 0:
                continue
            if len(Logger.LOGS) < itx:
                break
            log = Logger.LOGS[itx]
            return_logs[itx] = {
                'start_date':
                str(log.start_time),
                'status':
                log.status['status'],
                'status_name':
                log.status['name'],
                'user':
                log.user,
                'method':
                log.method_name,
                'object_name':
                log.object_name,
                'object_type':
                log.object_type,
                'description':
                '%s %s %s' % (log.method_name.capitalize(), log.object_name,
                              log.object_type),
                'exception_message':
                log.exception_message
            }
        return return_logs
Example #27
0
    def get_virtual_machine_by_id(self, vm_id):
        """Obtain a VM object, based on VM name"""
        # Validate VM ID
        ArgumentValidator.validate_id(vm_id, VirtualMachine)

        # Check that the domain exists
        if not self.check_exists(vm_id):
            raise VirtualMachineDoesNotExistException(
                'Error: Virtual Machine does not exist: %s' % vm_id
            )

        # Determine if VM object has been cached
        if vm_id not in Factory.CACHED_OBJECTS:
            # If not, create object, register with pyro
            # and store in cached object dict
            vm_object = VirtualMachine(vm_id)
            self._register_object(vm_object)
            vm_object.initialise()
            Factory.CACHED_OBJECTS[vm_id] = vm_object

        # Return the cached object
        return Factory.CACHED_OBJECTS[vm_id]
Example #28
0
    def getAllVmNames(self, node=None):
        """Returns a list of all VMs within the cluster or those registered on a specific node"""
        if node is not None:
            ArgumentValidator.validate_hostname(node)
        # If no node was defined, check the local configuration for all VMs
        if (node is None):
            return MCVirtConfig().get_config()['virtual_machines']
        elif node == get_hostname():
            # Obtain array of all domains from libvirt
            all_domains = self._get_registered_object(
                'libvirt_connector').get_connection().listAllDomains()
            return [vm.name() for vm in all_domains]
        else:
            # Return list of VMs registered on remote node
            cluster = self._get_registered_object('cluster')

            def remote_command(node_connection):
                virtual_machine_factory = node_connection.get_connection(
                    'virtual_machine_factory')
                return virtual_machine_factory.getAllVmNames(node=node)

            return cluster.run_remote_command(callback_method=remote_command,
                                              nodes=[node])[node]
Example #29
0
    def add_superuser(self, user_object, ignore_duplicate=False):
        """Add a new superuser."""
        assert isinstance(self._convert_remote_object(user_object),
                          self._get_registered_object('user_factory').USER_CLASS)
        ArgumentValidator.validate_boolean(ignore_duplicate)

        # Ensure the user is a superuser
        if not self.is_superuser():
            raise InsufficientPermissionsException(
                'User must be a superuser to manage superusers'
            )
        user_object = self._convert_remote_object(user_object)
        username = user_object.get_username()

        mcvirt_config = MCVirtConfig()

        # Ensure user is not already a superuser
        if username not in self.get_superusers():
            def update_config(config):
                config['superusers'].append(username)
            mcvirt_config.update_config(update_config, 'Added superuser \'%s\'' % username)

        elif not ignore_duplicate:
            raise DuplicatePermissionException(
                'User \'%s\' is already a superuser' % username
            )

        if self._is_cluster_master:
            def remote_command(connection):
                remote_user_factory = connection.get_connection('user_factory')
                remote_user = remote_user_factory.get_user_by_username(user_object.get_username())
                remote_auth = connection.get_connection('auth')
                remote_auth.add_superuser(remote_user, ignore_duplicate=ignore_duplicate)

            cluster = self._get_registered_object('cluster')
            cluster.run_remote_command(remote_command)
Example #30
0
    def get_logs(self, start_log=None, back=0, newer=False):
        """Return a dict containing log information"""
        if start_log is not None:
            ArgumentValidator.validate_integer(start_log)
        ArgumentValidator.validate_integer(back)
        ArgumentValidator.validate_boolean(newer)

        if start_log is None:
            start_log = len(Logger.LOGS) - 1

        if start_log < 0:
            start_log = 0
        if start_log > (len(Logger.LOGS) - 1):
            start_log = len(Logger.LOGS) - 1

        if back:
            start = 0 if (start_log - back) < 0 else (len(Logger.LOGS) - back)
            finish = start_log + 1
        elif newer:
            start = start_log + 1
            # Length would provide an indicy out of the range,
            # since len(['a']) = 1, but ['a'][1] == error
            # However, this is made up for the fact that range(0, 2) = [0, 1]
            finish = len(Logger.LOGS)
        else:
            # Start at the current log, to return it
            # Finish at current log + 1 as range(1, 2) = [1]
            start = start_log
            finish = start_log + 1

        return_logs = {}
        for itx in range(start, finish):
            if itx < 0:
                continue
            if len(Logger.LOGS) < itx:
                break
            log = Logger.LOGS[itx]
            return_logs[itx] = {
                'start_date': str(log.start_time),
                'status': log.status['status'],
                'status_name': log.status['name'],
                'user': log.user,
                'method': log.method_name,
                'object_name': log.object_name,
                'object_type': log.object_type,
                'description': '%s %s %s' % (log.method_name.capitalize(),
                                             log.object_name,
                                             log.object_type),
                'exception_message': log.exception_message
            }
        return return_logs
Example #31
0
 def validate_location_name(cls, location):
     """Ensure volume group name is valid"""
     ArgumentValidator.validate_directory(location)
Example #32
0
 def _validate_name(self):
     """Ensurue name of object is valid"""
     ArgumentValidator.validate_file_name(self.name)
Example #33
0
    def create(self, name, physical_interface):
        """Create a network on the node"""
        # Ensure user has permission to manage networks
        self._get_registered_object('auth').assert_permission(PERMISSIONS.MANAGE_HOST_NETWORKS)

        # Validate name
        ArgumentValidator.validate_network_name(name)

        # Ensure network does not already exist
        if self.check_exists(name):
            raise NetworkAlreadyExistsException('Network already exists: %s' % name)

        # Ensure that the physical interface eixsts
        if not self._interface_exists(physical_interface):
            raise InterfaceDoesNotExist(
                'Physical interface %s does not exist' % physical_interface
            )

        # Create XML for network
        network_xml = ET.Element('network')
        network_xml.set('ipv6', 'no')
        network_name_xml = ET.SubElement(network_xml, 'name')
        network_name_xml.text = name

        # Create 'forward'
        network_forward_xml = ET.SubElement(network_xml, 'forward')
        network_forward_xml.set('mode', 'bridge')

        # Set interface bridge
        network_bridge_xml = ET.SubElement(network_xml, 'bridge')
        network_bridge_xml.set('name', physical_interface)

        # Convert XML object to string
        network_xml_string = ET.tostring(network_xml, encoding='utf8', method='xml')

        # Attempt to register network with LibVirt
        try:
            self._get_registered_object('libvirt_connector').get_connection(
            ).networkDefineXML(network_xml_string)
        except:
            raise LibvirtException('An error occurred whilst registering network with LibVirt')

        # Update MCVirt config
        def update_config(config):
            config['networks'][name] = physical_interface
        from mcvirt.mcvirt_config import MCVirtConfig
        MCVirtConfig().update_config(update_config, 'Created network \'%s\'' % name)

        # Obtain instance of the network object
        network_instance = self.get_network_by_name(name)

        # Start network
        network_instance._get_libvirt_object().create()

        # Set network to autostart
        network_instance._get_libvirt_object().setAutostart(True)

        if self._is_cluster_master:
            def remote_add(node):
                network_factory = node.get_connection('network_factory')
                network_factory.create(name, physical_interface)
            cluster = self._get_registered_object('cluster')
            cluster.run_remote_command(remote_add)

        return network_instance
Example #34
0
    def _create(self, name, cpu_cores, memory_allocation, hard_drives=[],
                network_interfaces=[], node=None, available_nodes=[], storage_type=None,
                hard_drive_driver=None):
        """Creates a VM and returns the virtual_machine object for it"""
        self.checkName(name)
        ArgumentValidator.validate_positive_integer(cpu_cores)
        ArgumentValidator.validate_positive_integer(memory_allocation)
        for hard_drive in hard_drives:
            ArgumentValidator.validate_positive_integer(hard_drive)
        if network_interfaces:
            for network_interface in network_interfaces:
                ArgumentValidator.validate_network_name(network_interface)
        if node is not None:
            ArgumentValidator.validate_hostname(node)
        for available_node in available_nodes:
            ArgumentValidator.validate_hostname(available_node)
        assert storage_type in [None] + [
            storage_type_itx.__name__ for storage_type_itx in self._get_registered_object(
                'hard_drive_factory').STORAGE_TYPES
        ]
        if hard_drive_driver is not None:
            HardDriveDriver[hard_drive_driver]

        # Ensure the cluster has not been ignored, as VMs cannot be created with MCVirt running
        # in this state
        if self._cluster_disabled:
            raise ClusterNotInitialisedException('VM cannot be created whilst the cluster' +
                                                 ' is not initialised')

        # Determine if VM already exists
        if self.check_exists(name):
            raise VmAlreadyExistsException('Error: VM already exists')

        # If a node has not been specified, assume the local node
        if node is None:
            node = get_hostname()

        # If Drbd has been chosen as a storage type, ensure it is enabled on the node
        node_drbd = self._get_registered_object('node_drbd')
        if storage_type == 'Drbd' and not node_drbd.is_enabled():
            raise DrbdNotEnabledOnNode('Drbd is not enabled on this node')

        # Create directory for VM on the local and remote nodes
        if os_path_exists(VirtualMachine._get_vm_dir(name)):
            raise VmDirectoryAlreadyExistsException('Error: VM directory already exists')

        # If available nodes has not been passed, assume the local machine is the only
        # available node if local storage is being used. Use the machines in the cluster
        # if Drbd is being used
        cluster_object = self._get_registered_object('cluster')
        all_nodes = cluster_object.get_nodes(return_all=True)
        all_nodes.append(get_hostname())

        if len(available_nodes) == 0:
            if storage_type == 'Drbd':
                # If the available nodes are not specified, use the
                # nodes in the cluster
                available_nodes = all_nodes
            else:
                # For local VMs, only use the local node as the available nodes
                available_nodes = [get_hostname()]

        # If there are more than the maximum number of Drbd machines in the cluster,
        # add an option that forces the user to specify the nodes for the Drbd VM
        # to be added to
        if storage_type == 'Drbd' and len(available_nodes) != node_drbd.CLUSTER_SIZE:
            raise InvalidNodesException('Exactly two nodes must be specified')

        for check_node in available_nodes:
            if check_node not in all_nodes:
                raise NodeDoesNotExistException('Node \'%s\' does not exist' % check_node)

        if get_hostname() not in available_nodes and self._is_cluster_master:
            raise InvalidNodesException('One of the nodes must be the local node')

        # Create directory for VM
        makedirs(VirtualMachine._get_vm_dir(name))

        # Add VM to MCVirt configuration
        def updateMCVirtConfig(config):
            config['virtual_machines'].append(name)
        MCVirtConfig().update_config(
            updateMCVirtConfig,
            'Adding new VM \'%s\' to global MCVirt configuration' %
            name)

        # Create VM configuration file
        VirtualMachineConfig.create(name, available_nodes, cpu_cores, memory_allocation)

        # Add VM to remote nodes
        if self._is_cluster_master:
            def remote_command(remote_connection):
                virtual_machine_factory = remote_connection.get_connection(
                    'virtual_machine_factory'
                )
                virtual_machine_factory.create(
                    name=name, memory_allocation=memory_allocation, cpu_cores=cpu_cores,
                    node=node, available_nodes=available_nodes
                )
            cluster_object.run_remote_command(callback_method=remote_command)

        # Obtain an object for the new VM, to use to create disks/network interfaces
        vm_object = self.getVirtualMachineByName(name)
        vm_object.get_config_object().gitAdd('Created VM \'%s\'' % vm_object.get_name())

        if node == get_hostname():
            # Register VM with LibVirt. If MCVirt has not been initialised on this node,
            # do not set the node in the VM configuration, as the change can't be
            # replicated to remote nodes
            vm_object._register(set_node=self._is_cluster_master)
        elif self._is_cluster_master:
            # If MCVirt has been initialised on this node and the local machine is
            # not the node that the VM will be registered on, set the node on the VM
            vm_object._setNode(node)

        if self._is_cluster_master:
            # Create disk images
            hard_drive_factory = self._get_registered_object('hard_drive_factory')
            for hard_drive_size in hard_drives:
                hard_drive_factory.create(vm_object=vm_object, size=hard_drive_size,
                                          storage_type=storage_type, driver=hard_drive_driver)

            # If any have been specified, add a network configuration for each of the
            # network interfaces to the domain XML
            network_adapter_factory = self._get_registered_object('network_adapter_factory')
            network_factory = self._get_registered_object('network_factory')
            if network_interfaces is not None:
                for network in network_interfaces:
                    network_object = network_factory.get_network_by_name(network)
                    network_adapter_factory.create(vm_object, network_object)

        return vm_object
Example #35
0
 def getVirtualMachineByName(self, vm_name):
     """Obtain a VM object, based on VM name"""
     ArgumentValidator.validate_hostname(vm_name)
     vm_object = VirtualMachine(self, vm_name)
     self._register_object(vm_object)
     return vm_object
Example #36
0
 def validate_location_name(cls, location):
     """Ensure directory is a valid name"""
     ArgumentValidator.validate_vg_name(location)
Example #37
0
 def _validate_name(self):
     """Ensurue name of object is valid"""
     ArgumentValidator.validate_logical_volume_name(self.name)
Example #38
0
    def _create(self,
                name,
                cpu_cores,
                memory_allocation,
                hard_drives=None,
                network_interfaces=None,
                node=None,
                available_nodes=None,
                storage_type=None,
                hard_drive_driver=None,
                graphics_driver=None,
                modification_flags=None):
        """Create a VM and returns the virtual_machine object for it"""
        network_interfaces = [] if network_interfaces is None else network_interfaces
        hard_drives = [] if hard_drives is None else hard_drives
        available_nodes = [] if available_nodes is None else available_nodes
        modification_flags = [] if modification_flags is None else modification_flags

        self.checkName(name)
        ArgumentValidator.validate_positive_integer(cpu_cores)
        ArgumentValidator.validate_positive_integer(memory_allocation)
        for hard_drive in hard_drives:
            ArgumentValidator.validate_positive_integer(hard_drive)
        if network_interfaces:
            for network_interface in network_interfaces:
                ArgumentValidator.validate_network_name(network_interface)
        if node is not None:
            ArgumentValidator.validate_hostname(node)
        for available_node in available_nodes:
            ArgumentValidator.validate_hostname(available_node)
        assert storage_type in [None] + [
            storage_type_itx.__name__ for storage_type_itx in
            self._get_registered_object('hard_drive_factory').STORAGE_TYPES
        ]
        if hard_drive_driver is not None:
            HardDriveDriver[hard_drive_driver]

        # If no graphics driver has been specified, set it to the default
        if graphics_driver is None:
            graphics_driver = self.DEFAULT_GRAPHICS_DRIVER

        # Check the driver name is valid
        self.check_graphics_driver(graphics_driver)

        # Ensure the cluster has not been ignored, as VMs cannot be created with MCVirt running
        # in this state
        if self._cluster_disabled:
            raise ClusterNotInitialisedException(
                'VM cannot be created whilst the cluster' +
                ' is not initialised')

        # Determine if VM already exists
        if self.check_exists(name):
            raise VmAlreadyExistsException('Error: VM already exists')

        # If a node has not been specified, assume the local node
        if node is None:
            node = get_hostname()

        # If Drbd has been chosen as a storage type, ensure it is enabled on the node
        node_drbd = self._get_registered_object('node_drbd')
        if storage_type == 'Drbd' and not node_drbd.is_enabled():
            raise DrbdNotEnabledOnNode('Drbd is not enabled on this node')

        # Create directory for VM on the local and remote nodes
        if os_path_exists(VirtualMachine._get_vm_dir(name)):
            raise VmDirectoryAlreadyExistsException(
                'Error: VM directory already exists')

        # If available nodes has not been passed, assume the local machine is the only
        # available node if local storage is being used. Use the machines in the cluster
        # if Drbd is being used
        cluster_object = self._get_registered_object('cluster')
        all_nodes = cluster_object.get_nodes(return_all=True)
        all_nodes.append(get_hostname())

        if len(available_nodes) == 0:
            if storage_type == 'Drbd':
                # If the available nodes are not specified, use the
                # nodes in the cluster
                available_nodes = all_nodes
            else:
                # For local VMs, only use the local node as the available nodes
                available_nodes = [get_hostname()]

        # If there are more than the maximum number of Drbd machines in the cluster,
        # add an option that forces the user to specify the nodes for the Drbd VM
        # to be added to
        if storage_type == 'Drbd' and len(
                available_nodes) != node_drbd.CLUSTER_SIZE:
            raise InvalidNodesException('Exactly %i nodes must be specified' %
                                        node_drbd.CLUSTER_SIZE)

        for check_node in available_nodes:
            if check_node not in all_nodes:
                raise NodeDoesNotExistException('Node \'%s\' does not exist' %
                                                check_node)

        if get_hostname() not in available_nodes and self._is_cluster_master:
            raise InvalidNodesException(
                'One of the nodes must be the local node')

        # Check whether the hard drives can be created.
        if self._is_cluster_master:
            hard_drive_factory = self._get_registered_object(
                'hard_drive_factory')
            for hard_drive_size in hard_drives:
                hard_drive_factory.ensure_hdd_valid(
                    hard_drive_size, storage_type, [
                        node_itx for node_itx in available_nodes
                        if node_itx != get_hostname()
                    ])

        # Create directory for VM
        makedirs(VirtualMachine._get_vm_dir(name))

        # Add VM to MCVirt configuration
        def updateMCVirtConfig(config):
            config['virtual_machines'].append(name)

        MCVirtConfig().update_config(
            updateMCVirtConfig,
            'Adding new VM \'%s\' to global MCVirt configuration' % name)

        # Create VM configuration file
        VirtualMachineConfig.create(name, available_nodes, cpu_cores,
                                    memory_allocation, graphics_driver)

        # Add VM to remote nodes
        if self._is_cluster_master:

            def remote_command(remote_connection):
                virtual_machine_factory = remote_connection.get_connection(
                    'virtual_machine_factory')
                virtual_machine_factory.create(
                    name=name,
                    memory_allocation=memory_allocation,
                    cpu_cores=cpu_cores,
                    node=node,
                    available_nodes=available_nodes,
                    modification_flags=modification_flags)

            cluster_object.run_remote_command(callback_method=remote_command)

        # Obtain an object for the new VM, to use to create disks/network interfaces
        vm_object = self.getVirtualMachineByName(name)
        vm_object.get_config_object().gitAdd('Created VM \'%s\'' %
                                             vm_object.get_name())

        if node == get_hostname():
            # Register VM with LibVirt. If MCVirt has not been initialised on this node,
            # do not set the node in the VM configuration, as the change can't be
            # replicated to remote nodes
            vm_object._register(set_node=self._is_cluster_master)
        elif self._is_cluster_master:
            # If MCVirt has been initialised on this node and the local machine is
            # not the node that the VM will be registered on, set the node on the VM
            vm_object._setNode(node)

        if self._is_cluster_master:
            # Create disk images
            hard_drive_factory = self._get_registered_object(
                'hard_drive_factory')
            for hard_drive_size in hard_drives:
                hard_drive_factory.create(vm_object=vm_object,
                                          size=hard_drive_size,
                                          storage_type=storage_type,
                                          driver=hard_drive_driver)

            # If any have been specified, add a network configuration for each of the
            # network interfaces to the domain XML
            network_adapter_factory = self._get_registered_object(
                'network_adapter_factory')
            network_factory = self._get_registered_object('network_factory')
            if network_interfaces is not None:
                for network in network_interfaces:
                    network_object = network_factory.get_network_by_name(
                        network)
                    network_adapter_factory.create(vm_object, network_object)

            # Add modification flags
            vm_object._update_modification_flags(add_flags=modification_flags)

        return vm_object
Example #39
0
 def getVirtualMachineByName(self, vm_name):
     """Obtain a VM object, based on VM name"""
     ArgumentValidator.validate_hostname(vm_name)
     vm_object = VirtualMachine(self, vm_name)
     self._register_object(vm_object)
     return vm_object
Example #40
0
    def _create(self,
                name, cpu_cores, memory_allocation,  # Basic details, name etc.
                hard_drives=None,  # List of hard drive sizes to be created
                network_interfaces=None,  # List of networks to create network interfaces
                                          # to attach to
                node=None,  # The node to initially register the VM on
                available_nodes=None,  # List of nodes that the VM will be availble to.
                                       # For DRBD, this will be the two nodes
                                       # that DRBD is setup on. For other storage types,
                                       # it will be the nodes that the VM 'MUST' be
                                       # compatible with, i.e. storage backend must span
                                       # across them and networks exist on all nodes.
                storage_type=None,  # Storage type (string)
                hard_drive_driver=None, graphics_driver=None, modification_flags=None,
                storage_backend=None,   # Storage backend to be used. If not specified,
                                        # will default to an available storage backend,
                                        # if only 1 is avaiallbe.
                is_static=None):  # Manually override whether the VM is marked as static
        """Create a VM and returns the virtual_machine object for it"""
        # @TODO: Does this method need to do EVERYTHING?
        #       Maybe it should create the BARE MINIMUM required for a VM
        #       and leave it up to the parser to create everything else.
        #       The benefit to doing it in one function is to be able to
        #       validate that everything will work before-hand.

        # Set iterative items to empty array if not specified.
        # Can't set these to empty arrays by default, as if we attempt to append to them,
        # it will alter the default array (since it will be a reference)!
        network_interfaces = [] if network_interfaces is None else network_interfaces
        hard_drives = [] if hard_drives is None else hard_drives
        nodes_predefined = available_nodes is not None
        available_nodes = [] if available_nodes is None else available_nodes
        modification_flags = [] if modification_flags is None else modification_flags

        # Convert memory and disk sizes to bytes
        hard_drives = [hdd_size
                       if isinstance(hdd_size, int) else
                       SizeConverter.from_string(hdd_size, storage=True).to_bytes()
                       for hdd_size in hard_drives]
        memory_allocation = (memory_allocation
                             if memory_allocation is isinstance(memory_allocation, int) else
                             SizeConverter.from_string(memory_allocation).to_bytes())

        if storage_backend:
            storage_backend = self._convert_remote_object(storage_backend)

        # Ensure name is valid, as well as other attributes
        self.checkName(name)
        ArgumentValidator.validate_positive_integer(cpu_cores)
        ArgumentValidator.validate_positive_integer(memory_allocation)
        for hard_drive in hard_drives:
            ArgumentValidator.validate_positive_integer(hard_drive)
        if network_interfaces:
            for network_interface in network_interfaces:
                ArgumentValidator.validate_network_name(network_interface)
        if node is not None:
            ArgumentValidator.validate_hostname(node)
        for available_node in available_nodes:
            ArgumentValidator.validate_hostname(available_node)

        cluster_object = self._get_registered_object('cluster')
        local_hostname = get_hostname()

        if node and available_nodes and node not in available_nodes:
            raise InvalidNodesException('Node must be in available nodes')

        total_storage_size = sum(hard_drives) if hard_drives else None
        available_nodes, storage_backend, storage_type = self._pre_create_checks(
            required_storage_size=total_storage_size,
            networks=network_interfaces,
            storage_type=storage_type,
            nodes=available_nodes,
            storage_backend=storage_backend
        )

        # If a node has not been specified, assume the local node
        if node is None:
            node = local_hostname

        # Ensure that the local node is included in the list of available nodes
        if self._is_cluster_master and local_hostname not in available_nodes:
            raise InvalidNodesException('Local node must included in available nodes')

        # Ensure storage_type is a valid type, if specified
        hard_drive_factory = self._get_registered_object('hard_drive_factory')
        assert storage_type in [None] + [
            storage_type_itx.__name__ for storage_type_itx in self._get_registered_object(
                'hard_drive_factory').get_all_storage_types()
        ]

        # Obtain the hard drive driver enum from the name
        if hard_drive_driver is not None:
            HardDriveDriver[hard_drive_driver]

        # If no graphics driver has been specified, set it to the default
        if graphics_driver is None:
            graphics_driver = self.DEFAULT_GRAPHICS_DRIVER

        # Check the driver name is valid
        self.ensure_graphics_driver_valid(graphics_driver)

        # Ensure the cluster has not been ignored, as VMs cannot be created with MCVirt running
        # in this state
        if self._cluster_disabled:
            raise ClusterNotInitialisedException('VM cannot be created whilst the cluster' +
                                                 ' is not initialised')

        # Determine if VM already exists
        if self.check_exists_by_name(name):
            raise VmAlreadyExistsException('Error: VM already exists')

        # Create directory for VM on the local and remote nodes
        if os_path_exists(VirtualMachine.get_vm_dir(name)):
            raise VmDirectoryAlreadyExistsException('Error: VM directory already exists')

        if local_hostname not in available_nodes and self._is_cluster_master:
            raise InvalidNodesException('One of the nodes must be the local node')

        # Create VM configuration file
        # This is hard coded method of determining is_static, as seen in hard drive object
        # @TODO Refactor into method that's shared with is_static
        config_nodes = (None
                        if ((storage_backend and storage_backend.shared and
                             storage_type == 'Local') or
                            (is_static is not None and not is_static))
                        else available_nodes)

        id_ = VirtualMachine.generate_id(name)

        # Start transaction
        t = Transaction()

        vm_object = self.create_config(
            id_, name, config_nodes, cpu_cores, memory_allocation, graphics_driver,
            nodes=self._get_registered_object('cluster').get_nodes(include_local=True))

        if node == get_hostname():
            # Register VM with LibVirt. If MCVirt has not been initialised on this node,
            # do not set the node in the VM configuration, as the change can't be
            # replicated to remote nodes
            vm_object._register(set_node=self._is_cluster_master)
        elif self._is_cluster_master:
            # If MCVirt has been initialised on this node and the local machine is
            # not the node that the VM will be registered on, set the node on the VM
            vm_object._setNode(node)

        if self._is_cluster_master:
            # Create disk images
            hard_drive_factory = self._get_registered_object('hard_drive_factory')
            for hard_drive_size in hard_drives:
                hard_drive_factory.create(vm_object=vm_object, size=hard_drive_size,
                                          storage_type=storage_type, driver=hard_drive_driver,
                                          storage_backend=storage_backend,
                                          nodes=available_nodes)

            # If any have been specified, add a network configuration for each of the
            # network interfaces to the domain XML
            network_adapter_factory = self._get_registered_object('network_adapter_factory')
            network_factory = self._get_registered_object('network_factory')
            if network_interfaces is not None:
                for network in network_interfaces:
                    network_object = network_factory.get_network_by_name(network)
                    network_adapter_factory.create(vm_object, network_object)

            # Add modification flags
            vm_object._update_modification_flags(add_flags=modification_flags)

        t.finish()

        return vm_object
Example #41
0
    def create(self, name, storage_type, location, shared=False, id_=None,
               node_config={}):
        """Create storage backend"""
        # Check permissions
        self._get_registered_object('auth').assert_permission(PERMISSIONS.MANAGE_STORAGE_BACKEND)

        # Ensure storage backend does not already exist with same name
        if self.get_id_by_name(name):
            raise StorageBackendAlreadyExistsError('Storage backend already exists: %s' % name)

        t = Transaction()

        # Ensure that nodes are valid
        cluster = self._get_registered_object('cluster')

        for node in node_config:
            cluster.ensure_node_exists(node, include_local=True)

        # Ensure that either:
        # a default location is defined
        # all nodes provide an override location
        if (not location and
                (None in [node_config[node]['location']
                          if 'location' in node_config[node] else None
                          for node in node_config] or
                 not node_config)):
            raise InvalidStorageConfiguration(('A default location has not been set and '
                                               'some nodes do not have an override set'))

        storage_class = self.get_class(storage_type)

        # Generate ID for the storage backend
        id_ = storage_class.generate_id(name)

        # Ensure name is valid
        ArgumentValidator.validate_storage_name(name)

        # Get all locations and verify that the names are valid
        # @TODO - Refactor this to be more readable
        for location_itx in [] if not location else [location] + \
                [node_config[node]['location']
                 if 'location' in node_config[node]
                 else None
                 for node in node_config]:
            if location_itx is not None:
                storage_class.validate_location_name(location_itx)

        # If no nodes have been specified, get all nodes in cluster
        if not node_config:
            cluster = self._get_registered_object('cluster')
            node_config = {
                node: {'location': None}
                for node in cluster.get_nodes(return_all=True, include_local=True)
            }

        # Create config
        config = {'name': name,
                  'type': storage_type,
                  'shared': shared,
                  'nodes': node_config,
                  'location': location}

        # Ensure that config requirements and system requirements
        # are as expected for the type of storage backend
        # Only required on cluster master, as this checks all nodes in the cluster
        self.validate_config(
            storage_type=storage_type,
            config=config
        )

        # Ensure pre-requisites for storage backend pass on each node
        for node in node_config:
            node_location = (node_config[node]['location']
                             if 'location' in node_config[node] and
                             node_config[node]['location'] is not None else location)

            self.node_pre_check(location=node_location, storage_type=storage_type,
                                nodes=[node])

        self.create_config(id_, config, nodes=cluster.get_nodes(include_local=True))

        storage_object = self.get_object(id_)

        # Create ID volume
        storage_object.create_id_volume()

        t.finish()

        return storage_object