Example #1
0
    def test_vm_directory_already_exists(self):
        """Attempt to create a VM whilst the directory for the VM already exists"""
        # Create the directory for the VM
        os.makedirs(VirtualMachine.get_vm_dir(self.test_vms['TEST_VM_1']['name']))

        try:
            # Attempt to create VM, expecting an exception for the directory already existing
            with self.assertRaises(VmDirectoryAlreadyExistsException):
                self.parser.parse_arguments('create %s' % self.test_vms['TEST_VM_1']['name'] +
                                            ' --cpu-count %s --disk-size %s --memory %s' %
                                            (self.test_vms['TEST_VM_1']['cpu_count'],
                                             self.test_vms['TEST_VM_1']['disk_size'][0],
                                             self.test_vms['TEST_VM_1']['memory_allocation']) +
                                            ' --network %s --storage-type %s' %
                                            (self.test_vms['TEST_VM_1']['networks'][0],
                                             'Local'))

            # Ensure the VM has not been created
            self.assertFalse(self.vm_factory.check_exists_by_name(
                self.test_vms['TEST_VM_1']['name']))

        finally:
            # Remove directory
            shutil.rmtree(VirtualMachine.get_vm_dir(self.test_vms['TEST_VM_1']['name']))
Example #2
0
    def test_delete(self, storage_type):
        """Test the deletion of a VM through the argument parser"""
        # Create Virtual machine
        self.create_vm('TEST_VM_1', storage_type)

        # Remove VM using parser
        self.parser.parse_arguments('delete %s' % self.test_vms['TEST_VM_1']['name'])

        # Ensure VM has been deleted
        self.assertFalse(self.vm_factory.check_exists_by_name(self.test_vms['TEST_VM_1']['name']))

        # Ensure that VM directory does not exist
        self.assertFalse(os.path.exists(
            VirtualMachine.get_vm_dir(self.test_vms['TEST_VM_1']['name'])
        ))
Example #3
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