Example #1
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 #2
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 #3
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 #4
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 #5
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 #6
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 #7
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 #8
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 #9
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 #10
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 #11
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 #12
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 #13
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 #14
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 #15
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