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']))
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']) ))
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