# -*- coding: utf-8 -*-
#
# Copyright (c) 2018 German Mendez Bravo (Kronuz)
# Copyright (c) 2020 Mike Kinney
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.
#
"""VMrun class"""

from __future__ import absolute_import

import os
import sys
import logging
import subprocess
import tempfile

from .compat import b2s
from . import utils


LOGGER = logging.getLogger(__name__)


class VMrun():  # pylint: disable=too-many-public-methods
    """Interface class for the 'vmrun' command.
       The 'vmrun' command is used to interact with VMware.
       To add/update vmware functionality, run the 'vmrun' command with '--help'.
    """

    def __init__(self, vmx_file=None,  # pylint: disable=too-many-arguments
                 user=None, password=None, executable=None, provider=None,
                 test_mode=False):
        """Constructor - set sane defaults."""
        self.vmx_file = vmx_file
        self.user = user
        self.password = password
        self.executable = executable
        self.provider = provider

        if self.executable is None:
            if sys.platform == 'darwin':
                self.executable = utils.get_darwin_executable()
            elif sys.platform == 'win32':
                self.executable = utils.get_win32_executable()
            else:
                self.executable = utils.get_fallback_executable()
        if self.provider is None:
            if self.executable is not None:
                self.provider = utils.get_provider(self.executable)
                LOGGER.debug('self.executable:%s self.provider:%s',
                             self.executable, self.provider)
        # If test_mode is True, then do not perform the action
        # just return the command info
        self.test_mode = test_mode

    def installed(self):
        """Returns True if vmware is installed (based on whether we
           could find the vmrun command."""
        if self.executable is not None and os.path.exists(self.executable):
            return True
        else:
            return False

    def vmrun(self, cmd, *args, **kwargs):
        """Execute a 'vmrun' command."""
        quiet = kwargs.pop('quiet', False)
        arguments = kwargs.pop('arguments', ())

        cmds = [self.executable]
        cmds.append('-T')
        cmds.append(self.provider)
        if self.user:
            cmds.append('-gu')
            cmds.append(self.user)
        if self.password:
            cmds.append('-gp')
            cmds.append(self.password)
        cmds.append(cmd)
        cmds.extend(filter(None, args))
        cmds.extend(filter(None, arguments))

        LOGGER.debug(
            " ".join(
                "'{}'".format(
                    c.replace(
                        "'",
                        "\\'")) if ' ' in c else c for c in cmds))

        if self.test_mode:
            return cmds

        startupinfo = None
        if os.name == "nt":
            startupinfo = subprocess.STARTUPINFO()
            startupinfo.dwFlags |= subprocess.SW_HIDE | subprocess.STARTF_USESHOWWINDOW
        proc = subprocess.Popen(
            cmds,
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
            startupinfo=startupinfo)
        stdoutdata, stderrdata = map(b2s, proc.communicate())

        if stderrdata and not quiet:
            LOGGER.error(stderrdata.strip())
        LOGGER.debug("(⏎ %s)", proc.returncode)

        if not proc.returncode:
            stdoutdata = stdoutdata.strip()
            LOGGER.debug(repr(stdoutdata))
            return stdoutdata

        if stdoutdata and not quiet:
            LOGGER.error(stdoutdata.strip())

    ############################################################################
    # POWER COMMANDS           PARAMETERS           DESCRIPTION
    # --------------           ----------           -----------
    # start                    Path to vmx file     Start a VM or Team
    #                          [gui|nogui]
    #
    # stop                     Path to vmx file     Stop a VM or Team
    #                          [hard|soft]
    #
    # reset                    Path to vmx file     Reset a VM or Team
    #                          [hard|soft]
    #
    # suspend                  Path to vmx file     Suspend a VM or Team
    #                          [hard|soft]
    #
    # pause                    Path to vmx file     Pause a VM
    #
    # unpause                  Path to vmx file     Unpause a VM
    #

    def start(self, gui=False, quiet=False):
        '''Start a VM or Team'''
        return self.vmrun('start', self.vmx_file, 'gui' if gui else 'nogui', quiet=quiet)

    def stop(self, mode='soft', quiet=False):
        '''Stop a VM or Team'''
        return self.vmrun('stop', self.vmx_file, mode, quiet=quiet)

    def reset(self, mode='soft', quiet=False):
        '''Reset a VM or Team'''
        return self.vmrun('reset', self.vmx_file, mode, quiet=quiet)

    def suspend(self, mode='soft', quiet=False):
        '''Suspend a VM or Team'''
        return self.vmrun('suspend', self.vmx_file, mode, quiet=quiet)

    def pause(self, quiet=False):
        '''Pause a VM'''
        return self.vmrun('pause', self.vmx_file, quiet=quiet)

    def unpause(self, quiet=False):
        '''Unpause a VM'''
        return self.vmrun('unpause', self.vmx_file, quiet=quiet)

    ############################################################################
    # SNAPSHOT COMMANDS        PARAMETERS           DESCRIPTION
    # -----------------        ----------           -----------
    # listSnapshots            Path to vmx file     List all snapshots in a VM
    #                          [showTree]
    #
    # snapshot                 Path to vmx file     Create a snapshot of a VM
    #                          Snapshot name
    #
    # deleteSnapshot           Path to vmx file     Remove a snapshot from a VM
    #                          Snapshot name
    #                          [andDeleteChildren]
    #
    # revertToSnapshot         Path to vmx file     Set VM state to a snapshot
    #                          Snapshot name
    #

    def list_snapshots(self, show_tree=False, quiet=False):
        '''List all snapshots in a VM'''
        return self.vmrun(
            'listSnapshots',
            self.vmx_file,
            'showTree' if show_tree else None,
            quiet=quiet)

    def snapshot(self, snap_name, quiet=False):
        '''Create a snapshot of a VM'''
        return self.vmrun('snapshot', self.vmx_file, snap_name, quiet=quiet)

    def delete_snapshot(self, snap_name, and_delete_children=False, quiet=False):
        '''Remove a snapshot from a VM'''
        return self.vmrun(
            'deleteSnapshot',
            self.vmx_file,
            snap_name,
            'andDeleteChildren' if and_delete_children else None,
            quiet=quiet)

    def revert_to_snapshot(self, snap_name, quiet=False):
        '''Set VM state to a snapshot'''
        return self.vmrun('revertToSnapshot', self.vmx_file, snap_name, quiet=quiet)

    ############################################################################
    # NETWORKADAPTER COMMANDS  PARAMETERS           DESCRIPTION
    # -----------------------  ----------           -----------
    # listNetworkAdapters      Path to vmx file     List all network adapters in a VM
    #
    #
    # addNetworkAdapter        Path to vmx file     Add a network adapter on a VM
    #                          Network adapter type
    #                          [Host nework]
    #
    #
    # setNetworkAdapter        Path to vmx file     Update a network adapter on a VM
    #                          Network adapter index
    #                          Network adapter type
    #                          [Host network]
    #
    #
    # deleteNetworkAdapter     Path to vmx file     Remove a network adapter on a VM
    #                          Network adapter index

    def list_network_adapters(self, quiet=False):
        '''List all network adapters in a VM'''
        return self.vmrun('listNetworkAdapters', self.vmx_file, quiet=quiet)

    def add_network_adapter(self, adapter_type, host_network=None, quiet=False):
        '''Add a network adapter on a VM'''
        return self.vmrun(
            'addNetworkAdapter',
            self.vmx_file,
            adapter_type,
            host_network,
            quiet=quiet)

    def set_network_adapter(self, adapter_index, adapter_type, host_network=None, quiet=False):
        '''Update a network adapter on a VM'''
        return self.vmrun(
            'setNetworkAdapter',
            self.vmx_file,
            adapter_index,
            adapter_type,
            host_network,
            quiet=quiet)

    def delete_network_adapter(self, adapter_index, quiet=False):
        '''Remove a network adapter on a VM'''
        return self.vmrun('deleteNetworkAdapter', self.vmx_file, adapter_index, quiet=quiet)

    ############################################################################
    # HOST NETWORK COMMANDS    PARAMETERS           DESCRIPTION
    # ---------------------    ----------           -----------
    # listHostNetworks                              List all networks in the host
    #
    # listPortForwardings      Host network name    List all available port
    #                                               forwardings on a host network
    #
    #
    # setPortForwarding        Host network name    Add or update a port
    #                                               forwarding on a host network
    #                          Protocol
    #                          Host port
    #                          Guest ip
    #                          Guest port
    #                          [Description]
    #
    # deletePortForwarding     Host network name    Delete a port forwarding on a host network
    #                          Protocol
    #                          Host port

    def list_host_networks(self, quiet=False):
        '''List all networks in the host.
           Note: Not available on linux.
        '''
        return self.vmrun('listHostNetworks', quiet=quiet)

    def list_port_forwardings(self, host_network, quiet=False):
        '''List all available port forwardings on a host network'''
        return self.vmrun('listPortForwardings', host_network, quiet=quiet)

    def set_port_forwarding(  # pylint: disable=too-many-arguments
            self,
            host_network,
            protocol,
            host_port,
            guest_ip,
            guest_port,
            description=None,
            quiet=False):
        '''Add or update a port forwarding on a host network'''
        return self.vmrun(
            'setPortForwarding',
            host_network,
            protocol,
            host_port,
            guest_ip,
            guest_port,
            description,
            quiet=quiet)

    def delete_port_forwarding(self, host_network, protocol, host_port,
                               quiet=False):  # pylint: disable=too-many-arguments
        '''Delete a port forwarding on a host network'''
        return self.vmrun('deletePortForwarding', host_network, protocol, host_port, quiet=quiet)

    ############################################################################
    # GUEST OS COMMANDS        PARAMETERS           DESCRIPTION
    # -----------------        ----------           -----------
    # runProgramInGuest        Path to vmx file     Run a program in Guest OS
    #                          [-noWait]
    #                          [-activeWindow]
    #                          [-interactive]
    #                          Complete-Path-To-Program
    #                          [Program arguments]
    #
    # fileExistsInGuest        Path to vmx file     Check if a file exists in Guest OS
    #                          Path to file in guest
    #
    # directoryExistsInGuest   Path to vmx file     Check if a directory exists in Guest OS
    #                          Path to directory in guest
    #
    # setSharedFolderState     Path to vmx file     Modify a Host-Guest shared folder
    #                          Share name
    #                          Host path
    #                          writable | readonly
    #
    # addSharedFolder          Path to vmx file     Add a Host-Guest shared folder
    #                          Share name
    #                          New host path
    #
    # removeSharedFolder       Path to vmx file     Remove a Host-Guest shared folder
    #                          Share name
    #
    # enableSharedFolders      Path to vmx file     Enable shared folders in Guest
    #                          [runtime]
    #
    # disableSharedFolders     Path to vmx file     Disable shared folders in Guest
    #                          [runtime]
    #
    # listProcessesInGuest     Path to vmx file     List running processes in Guest OS
    #
    # killProcessInGuest       Path to vmx file     Kill a process in Guest OS
    #                          process id
    #
    # runScriptInGuest         Path to vmx file     Run a script in Guest OS
    #                          [-noWait]
    #                          [-activeWindow]
    #                          [-interactive]
    #                          Interpreter path
    #                          Script text
    #
    # deleteFileInGuest        Path to vmx file     Delete a file in Guest OS
    #                          Path in guest
    #
    # createDirectoryInGuest   Path to vmx file     Create a directory in Guest OS
    #                          Directory path in guest
    #
    # deleteDirectoryInGuest   Path to vmx file     Delete a directory in Guest OS
    #                          Directory path in guest
    #
    # createTempfileInGuest    Path to vmx file     Create a temporary file in Guest OS
    #
    # listDirectoryInGuest     Path to vmx file     List a directory in Guest OS
    #                          Directory path in guest
    #
    # copyFileFromHostToGuest  Path to vmx file     Copy a file from host OS to guest OS
    #                          Path on host
    #                          Path in guest
    #
    # copyFileFromGuestToHost  Path to vmx file     Copy a file from guest OS to host OS
    #                          Path in guest
    #                          Path on host
    #
    # renameFileInGuest        Path to vmx file     Rename a file in Guest OS
    #                          Original name
    #                          New name
    #
    # typeKeystrokesInGuest    Path to vmx file     Type Keystrokes in Guest OS
    #                          keystroke string
    #
    # connectNamedDevice       Path to vmx file     Connect the named device in the Guest OS
    #                          device name
    #
    # disconnectNamedDevice    Path to vmx file     Disconnect the named device in the Guest OS
    #                          device name
    #
    # captureScreen            Path to vmx file     Capture the screen of the VM to a local file
    #                          Path on host
    #
    # writeVariable            Path to vmx file     Write a variable in the VM state
    #                          [runtimeConfig|guestEnv|guestVar]
    #                          variable name
    #                          variable value
    #
    # readVariable             Path to vmx file     Read a variable in the VM state
    #                          [runtimeConfig|guestEnv|guestVar]
    #                          variable name
    #
    # getGuestIPAddress        Path to vmx file     Gets the IP address of the guest
    #                          [-wait]
    #

    def run_program_in_guest(  # pylint: disable=too-many-arguments
            self,
            program_path,
            program_arguments=None,
            wait=True,
            activate_window=False,
            interactive=False,
            quiet=False):
        """Run a program in the guest vm."""
        if program_arguments is None:
            program_arguments = []
        return self.vmrun(
            'runProgramInGuest',
            self.vmx_file,
            None if wait else '-noWait',
            '-activateWindow' if activate_window else None,
            '-interactive' if interactive else None,
            program_path,
            arguments=program_arguments,
            quiet=quiet)

    def set_shared_folder_state(self, share_name, new_path, mode='readonly', quiet=False):
        '''Modify a Host-Guest shared folder'''
        return self.vmrun(
            'setSharedFolderState',
            self.vmx_file,
            share_name,
            new_path,
            mode,
            quiet=quiet)

    def add_shared_folder(self, share_name, host_path, quiet=False):
        '''Add a Host-Guest shared folder'''
        return self.vmrun('addSharedFolder', self.vmx_file, share_name, host_path, quiet=quiet)

    def remove_shared_folder(self, share_name, quiet=False):
        '''Remove a Host-Guest shared folder'''
        return self.vmrun('removeSharedFolder', self.vmx_file, share_name, quiet=quiet)

    def enable_shared_folders(self, runtime=None, quiet=False):
        '''Enable shared folders.'''
        return self.vmrun('enableSharedFolders', self.vmx_file, runtime, quiet=quiet)

    def disable_shared_folders(self, runtime=None, quiet=False):
        '''Disable shared folders in Guest'''
        return self.vmrun('disableSharedFolders', self.vmx_file, runtime, quiet=quiet)

    def list_processes_in_guest(self, quiet=False):
        '''List running processes in Guest OS'''
        return self.vmrun('listProcessesInGuest', self.vmx_file, quiet=quiet)

    def kill_process_in_guest(self, pid, quiet=False):
        '''Kill a process in Guest OS'''
        return self.vmrun('killProcessInGuest', self.vmx_file, pid, quiet=quiet)

    def run_script_in_guest(  # pylint: disable=too-many-arguments
            self,
            interpreter_path,
            script,
            wait=True,
            activate_window=False,
            interactive=False,
            quiet=False):
        '''Run a script in Guest OS'''
        return self.vmrun(
            'runScriptInGuest',
            self.vmx_file,
            interpreter_path,
            script,
            None if wait else '-noWait',
            '-activateWindow' if activate_window else None,
            '-interactive' if interactive else None,
            quiet=quiet)

    def delete_file_in_guest(self, filename, quiet=False):
        '''Delete a file in Guest OS'''
        return self.vmrun('deleteFileInGuest', self.vmx_file, filename, quiet=quiet)

    def create_directory_in_guest(self, path, quiet=False):
        '''Create a directory in Guest OS'''
        return self.vmrun('createDirectoryInGuest', self.vmx_file, path, quiet=quiet)

    def delete_directory_in_guest(self, path, quiet=False):
        '''Delete a directory in Guest OS'''
        return self.vmrun('deleteDirectoryInGuest', self.vmx_file, path, quiet=quiet)

    def create_tempfile_in_guest(self, quiet=False):
        '''Create a temporary file in Guest OS'''
        return self.vmrun('createTempfileInGuest', self.vmx_file, quiet=quiet)

    def list_directory_in_guest(self, path, quiet=False):
        '''List a directory in Guest OS'''
        return self.vmrun('listDirectoryInGuest', self.vmx_file, path, quiet=quiet)

    def copy_file_from_host_to_guest(self, host_path, guest_path, quiet=False):
        '''Copy a file from host OS to guest OS'''
        return self.vmrun(
            'copyFileFromHostToGuest',
            self.vmx_file,
            host_path,
            guest_path,
            quiet=quiet)

    def copy_file_from_guest_to_host(self, guest_path, host_path, quiet=False):
        '''Copy a file from guest OS to host OS'''
        return self.vmrun(
            'copyFileFromGuestToHost',
            self.vmx_file,
            guest_path,
            host_path,
            quiet=quiet)

    def rename_file_in_guest(self, original_name, new_name, quiet=False):
        '''Rename a file in Guest OS'''
        return self.vmrun('renameFileInGuest', self.vmx_file, original_name, new_name, quiet=quiet)

    def type_keystrokes_in_guest(self, keystroke, quiet=False):
        '''Type Keystrokes in Guest OS'''
        return self.vmrun('typeKeystrokesInGuest', self.vmx_file, keystroke, quiet=quiet)

    def connect_named_device(self, device_name, quiet=False):
        '''Connect the named device in the Guest OS'''
        return self.vmrun('connectNamedDevice', self.vmx_file, device_name, quiet=quiet)

    def disconnect_named_device(self, device_name, quiet=False):
        '''Disconnect the named device in the Guest OS'''
        return self.vmrun('disconnectNamedDevice', self.vmx_file, device_name, quiet=quiet)

    def capture_screen(self, path_on_host, quiet=False):
        '''Capture the screen of the VM to a local file'''
        return self.vmrun('captureScreen', self.vmx_file, path_on_host, quiet=quiet)

    def write_variable(self, var_name, var_value, mode=None, quiet=False):
        '''Write a variable in the VM state'''
        return self.vmrun('writeVariable', self.vmx_file, mode, var_name, var_value, quiet=quiet)

    def read_variable(self, var_name, mode=None, quiet=False):
        '''Read a variable in the VM state'''
        return self.vmrun('readVariable', self.vmx_file, mode, var_name, quiet=quiet)

    def get_guest_ip_address(self, wait=True, quiet=False, lookup=False):
        '''Gets the IP address of the guest'''
        if lookup is True:
            guest_tmp_filename = '/tmp/.ip_address'
            cmd = "ifconfig | grep -Eo 'inet (addr:)?([0-9]*\\.){3}[0-9]*'"
            cmd += "| grep -Eo '([0-9]*\\.){3}[0-9]*' | grep -v '127.0.0.1' > " + guest_tmp_filename
            LOGGER.debug("cmd:%s", cmd)
            self.run_script_in_guest('/bin/sh', cmd, quiet=quiet)
            temp_file = tempfile.NamedTemporaryFile(delete=False)
            try:
                temp_file.close()
                self.copy_file_from_guest_to_host(guest_tmp_filename, temp_file.name, quiet=quiet)
                ip_addresses = open(temp_file.name).read().split()
                # clean up the guest tmp file
                self.run_script_in_guest(
                    '/bin/sh',
                    "rm {}".format(guest_tmp_filename),
                    quiet=False)
                if ip_addresses:
                    return ip_addresses[0]
                else:
                    return None
            finally:
                os.unlink(temp_file.name)
        else:
            ip_address = self.vmrun('getGuestIPAddress', self.vmx_file,
                                    '-wait' if wait else None, quiet=quiet)
            if ip_address == 'unknown':
                ip_address = ''
        return ip_address

    ############################################################################
    # GENERAL COMMANDS         PARAMETERS           DESCRIPTION
    # ----------------         ----------           -----------
    # list                                          List all running VMs
    #
    # upgradevm                Path to vmx file     Upgrade VM file format, virtual hw
    #
    # installTools             Path to vmx file     Install Tools in Guest
    #
    # checkToolsState          Path to vmx file     Check the current Tools state
    #
    # deleteVM                 Path to vmx file     Delete a VM
    #
    # clone                    Path to vmx file     Create a copy of the VM
    #                          Path to destination vmx file
    #                          full|linked
    #                          [-snapshot=Snapshot Name]
    #                          [-cloneName=Name]

    def list(self, quiet=False):
        '''List all running VMs'''
        return self.vmrun('list', self.vmx_file, quiet=quiet)

    def upgradevm(self, quiet=False):
        '''Upgrade VM file format, virtual hw.
           Note: The vm must be stopped before running this command.
        '''
        return self.vmrun('upgradevm', self.vmx_file, quiet=quiet)

    def install_tools(self, quiet=False):
        '''Install Tools in Guest OS'''
        return self.vmrun('installTools', self.vmx_file, quiet=quiet)

    def check_tools_state(self, quiet=False):
        '''Check the current Tools state'''
        return self.vmrun('checkToolsState', self.vmx_file, quiet=quiet)

    def register(self, quiet=False):
        # unavailable in VMware Fusion 10 (OS X)?
        '''Register a VM'''
        return self.vmrun('register', self.vmx_file, quiet=quiet)

    def unregister(self, quiet=False):
        # unavailable in VMware Fusion 10 (OS X)?
        '''Unregister a VM'''
        return self.vmrun('unregister', self.vmx_file, quiet=quiet)

    def list_registered_vm(self, quiet=False):
        # unavailable in VMware Fusion 10 (OS X)?
        '''List registered VMs'''
        return self.vmrun('listRegisteredVM', self.vmx_file, quiet=quiet)

    def delete_vm(self, quiet=False):
        '''Delete a VM'''
        return self.vmrun('deleteVM', self.vmx_file, quiet=quiet)

    def clone(self, dest_vmx, mode, snap_name=None, quiet=False):
        '''Create a copy of the VM'''
        return self.vmrun('clone', self.vmx_file, dest_vmx, mode, snap_name, quiet=quiet)

    ############################################################################
    # RECORD/REPLAY COMMANDS   PARAMETERS           DESCRIPTION
    # ----------------------   ----------           -----------
    # beginRecording           Path to vmx file     Begin recording a VM
    #                          Snapshot name
    #
    # endRecording             Path to vmx file     End recording a VM
    #
    # beginReplay              Path to vmx file     Begin replaying a VM
    #                          Snapshot name
    #
    # endReplay                Path to vmx file     End replaying a VM

    def begin_recording(self, snap_name, quiet=False):
        # unavailable in VMware Fusion 10 (OS X)?
        '''Begin recording a VM'''
        return self.vmrun('beginRecording', self.vmx_file, snap_name, quiet=quiet)

    def end_recording(self, quiet=False):
        # unavailable in VMware Fusion 10 (OS X)?
        '''End recording a VM'''
        return self.vmrun('endRecording', self.vmx_file, quiet=quiet)

    def begin_replay(self, snap_name, quiet=False):
        # unavailable in VMware Fusion 10 (OS X)?
        '''Begin replaying a VM'''
        return self.vmrun('beginReplay', self.vmx_file, snap_name, quiet=quiet)

    def end_replay(self, quiet=False):
        # unavailable in VMware Fusion 10 (OS X)?
        '''End replaying a VM'''
        return self.vmrun('endReplay', self.vmx_file, quiet=quiet)

    ############################################################################
    # VPROBE COMMANDS          PARAMETERS           DESCRIPTION
    # ---------------          ----------           -----------
    # vprobeVersion            Path to vmx file     List VP version
    #
    # vprobeLoad               Path to vmx file     Load VP script
    #                          'VP script text'
    #
    # vprobeLoadFile           Path to vmx file     Load VP file
    #                          Path to VP file
    #
    # vprobeReset              Path to vmx file     Disable all vprobes
    #
    # vprobeListProbes         Path to vmx file     List probes
    #
    # vprobeListGlobals        Path to vmx file     List global variables

    def vprobe_version(self, quiet=False):
        # unavailable in VMware Fusion 10 (OS X)?
        '''List VP version'''
        return self.vmrun('vprobeVersion', self.vmx_file, quiet=quiet)

    def vprobe_load(self, script, quiet=False):
        # unavailable in VMware Fusion 10 (OS X)?
        '''Load VP script'''
        return self.vmrun('vprobeLoad', self.vmx_file, script, quiet=quiet)

    def vprobe_load_file(self, vprobe, quiet=False):
        # unavailable in VMware Fusion 10 (OS X)?
        '''Load VP file'''
        return self.vmrun('vprobeLoadFile', self.vmx_file, vprobe, quiet=quiet)

    def vprobe_reset(self, quiet=False):
        # unavailable in VMware Fusion 10 (OS X)?
        '''Disable all vprobes'''
        return self.vmrun('vprobeReset', self.vmx_file, quiet=quiet)

    def vprobe_list_probes(self, quiet=False):
        # unavailable in VMware Fusion 10 (OS X)?
        '''List probes'''
        return self.vmrun('vprobeListProbes', self.vmx_file, quiet=quiet)

    def vprobe_list_globals(self, quiet=False):
        # unavailable in VMware Fusion 10 (OS X)?
        '''List global variables'''
        return self.vmrun('vprobeListGlobals', self.vmx_file, quiet=quiet)

    ############################################################################

    def installed_tools(self, quiet=False):
        '''Return True if VMware tools is in either 'installed' or 'running',
           otherwise, return False.
        '''
        state = self.check_tools_state(quiet=quiet)
        return state in ('installed', 'running')
