Clone a new VM from an existing VM

    CLI Example:

    .. code-block:: bash

        salt 'hypervisor' vboxmanage.clonevm <name> <new_name>

def clonevm(name=None,
            uuid=None,
            new_name=None,
            snapshot_uuid=None,
            snapshot_name=None,
            mode='machine',
            options=None,
            basefolder=None,
            new_uuid=None,
            register=False,
            groups=None,
            **kwargs):
    '''
    Clone a new VM from an existing VM

    CLI Example:

    .. code-block:: bash

        salt 'hypervisor' vboxmanage.clonevm <name> <new_name>
    '''
    if (name and uuid) or (not name and not uuid):
        raise CommandExecutionError(
            'Either a name or a uuid must be specified, but not both.'
        )

    params = ''
    nodes_names = list_nodes_min()
    nodes_uuids = list_items('vms', True, 'UUID').keys()
    if name:
        if name not in nodes_names:
            raise CommandExecutionError(
                'The specified VM ({0}) is not registered.'.format(name)
            )
        params += ' ' + name
    elif uuid:
        if uuid not in nodes_uuids:
            raise CommandExecutionError(
                'The specified VM ({0}) is not registered.'.format(name)
            )
        params += ' ' + uuid

    if snapshot_name and snapshot_uuid:
        raise CommandExecutionError(
            'Either a snapshot_name or a snapshot_uuid may be specified, but not both'
        )

    if snapshot_name:
        if NAME_RE.search(snapshot_name):
            raise CommandExecutionError('Snapshot name contains invalid characters')
        params += ' --snapshot {0}'.format(snapshot_name)
    elif snapshot_uuid:
        if UUID_RE.search(snapshot_uuid):
            raise CommandExecutionError('Snapshot name contains invalid characters')
        params += ' --snapshot {0}'.format(snapshot_uuid)

    valid_modes = ('machine', 'machineandchildren', 'all')
    if mode and mode not in valid_modes:
        raise CommandExecutionError(
            'Mode must be one of: {0} (default "machine")'.format(', '.join(valid_modes))
        )
    else:
        params += ' --mode ' + mode

    valid_options = ('link', 'keepallmacs', 'keepnatmacs', 'keepdisknames')
    if options and options not in valid_options:
        raise CommandExecutionError(
            'If specified, options must be one of: {0}'.format(', '.join(valid_options))
        )
    else:
        params += ' --options ' + options

    if new_name:
        if NAME_RE.search(new_name):
            raise CommandExecutionError('New name contains invalid characters')
        params += ' --name {0}'.format(new_name)

    if groups:
        if isinstance(groups, six.string_types):
            groups = [groups]
        if isinstance(groups, list):
            params += ' --groups {0}'.format(','.join(groups))
        else:
            raise CommandExecutionError(
                'groups must be either a string or a list of strings'
            )

    if basefolder:
        if not os.path.exists(basefolder):
            raise CommandExecutionError('basefolder {0} was not found'.format(basefolder))
        params += ' --basefolder {0}'.format(basefolder)

    if new_uuid:
        if NAME_RE.search(new_uuid):
            raise CommandExecutionError('New UUID contains invalid characters')
        params += ' --uuid {0}'.format(new_uuid)

    if register is True:
        params += ' --register'

    cmd = '{0} clonevm {1}'.format(vboxcmd(), name)
    ret = salt.modules.cmdmod.run_all(cmd)
    if ret['retcode'] == 0:
        return True
    return ret['stderr']