VMware

VMware vCenter server is a centralized management application that lets you manage virtual machines and ESXi hosts centrally.

IT Services · VMware

Details

IDVMware
ProviderBroadcom
CategoryIT Services
From Version5.0.0
Docker Imagedemisto/vmware:2.0.0.10133006
Supported ModulesAgentix XSIAM

README

VMware vCenter server is a centralized management application that lets you manage virtual machines and ESXi hosts centrally.
This integration was integrated and tested with version 7.03 of VMware

Configure VMware in Cortex

Parameter Description Required
Server URL (i.e., 192.168.0.1:30022) The server URL of the VCenter. True
Credentials Username and password used to login into the system. True
insecure Trust any certificate (not secure). True
proxy Use system proxy settings. False

Use Cases

  • Create and revert to snapshot.
  • Get information regarding virtual machines.
  • Power-on, power-off, suspend, reboot, clone, create, delete, relocate, resigster and unregister virtual machines.

Commands

You can execute these commands from the CLI, as part of an automation, or in a playbook.
After you successfully execute a command, a DBot message appears in the War Room with the command details.

vmware-get-vms


Returns all virtual machines on a system.

Base Command

vmware-get-vms

Input

Argument Name Description Required
ip List of IPs to filter VMs by. Optional
hostname Hostname to filter VMs by. Optional
name List of VM names to filter VMs by. Optional
uuid List of UUIDs to filter VMs by. Optional

Context Output

Path Type Description
VMWare.Name String VM name.
VMWare.Template bool true if template, else false.
VMWare.Path String Path to VM.
VMWare.Guest String Guest full name.
VMWare.UUID String VM instance UUID.
VMWare.IP String VM IP address.
VMWare.State String VM state (i.e., poweredOn, poweredOff, suspended, HardRebooted).
VMWare.HostName String Host name of VM.
VMWare.MACAddress String MAC address of VM.
VMWare.SnapshotCreateDate String Create date of the last snapshot of the VM.
VMWare.SnapshotUUID String UUID of the last snapshot of the VM.
VMWare.Deleted Boolean If set to true, the VM was deleted.

Command Example

!vmware-get-vms

Context Example

{
 "VMWare":[
   {
       "Guest": "Ubuntu Linux (64-bit)",
       "HostName": "ubuntu",
       "IP": "192.168.100.1",
       "MACAddress": "00:50:56:bc:86:ec",
       "Name": "UbuntuTest",
       "Path": "[datastore1] UbuntuTest/UbuntuTest.vmx",
       "State": "poweredOn",
       "Template": false,
       "UUID": "503ca58b-0821-cf21-fb56-459e55df6d19"
   }
 ]
}

Human Readable Output

Name Template Path Guest UUID IP State HostName MACAddress SnapshotCreateDate SnapshotUUID Deleted
VMware_vCenter_7_Integration_Test false [datastore1] VMware_vCenter_7_Integration_Test/VMware_vCenter_7_Integration_Test.vmx Other 3.x or later Linux (64-bit) 52535506-77f9-ac98-77d3-63bb537ad7d2 192.168.1.141 poweredOn localhost 00:0c:29:d4:ca:14     false
VMware_enhancement_test_vm false [datastore1] enhancement_test_3/enhancement_test_3.vmx Other (32-bit) 503d608e-92a1-358a-9674-2806326527f5   poweredOn         false
CentOS7_VMware_Integration_Test false [datastore1] CentOS7_VMware_Integration_Test/CentOS7_VMware_Integration_Test.vmx CentOS 7 (64-bit) 503dd190-3c64-493b-38ff-37db4e4ba2ab 192.168.1.142 poweredOn localhost.localdomain 00:50:56:bd:25:c4 2021-09-22 12:09:57.989388+00:00 423da02f-c7f4-3cda-a33e-1c85c10e048d false
TetsVM1 false [datastore1] TetsVM1/TetsVM1.vmx Other (32-bit) 503dae8b-afc2-d253-40d5-7e25e05d86f4   poweredOn         false
enhancement test 2 false [datastore1] enhancement test 2/enhancement test 2.vmx Other (32-bit) 503d4b98-8a62-c31e-239a-fc9480f55d30   poweredOff         false

vmware-poweron


Powers on a powered-off or suspended virtual machine.

Base Command

vmware-poweron

Input

Argument Name Description Required
vm-uuid VM UUID of virtual machine to be powered on. Required

Context Output

Path Type Description
VMWare.UUID String VM instance UUID.
VMWare.State String VM state (i.e., poweredOn, poweredOff, suspended, HardRebooted).

Command Example

!vmware-poweron vm-uuid="503ca58b-0821-cf21-fb56-459e55df6d19"

Context Example

{
 "VMWare": {
     "State": "poweredOn",
     "UUID": "503ca58b-0821-cf21-fb56-459e55df6d19"
   }
}

Human Readable Output

Virtual Machine was powered on successfully.

vmware-poweroff


Powers off a powered-on or suspended virtual machine.

Base Command

vmware-poweroff

Input

Argument Name Description Required
vm-uuid VM UUID of virtual machine to be powered on. Required

Context Output

Path Type Description
VMWare.UUID String VM instance UUID.
VMWare.State String VM state (i.e., poweredOn, poweredOff, suspended, HardRebooted).

Command Example

!vmware-poweroff vm-uuid="503ca58b-0821-cf21-fb56-459e55df6d19"

Context Example

{
 "VMWare": {
     "State": "poweredOff",
     "UUID": "503ca58b-0821-cf21-fb56-459e55df6d19"
   }
}

Human Readable Output

Virtual Machine was powered off successfully.

vmware-hard-reboot


Reboots a powered-on virtual machine.

Base Command

vmware-hard-reboot

Input

Argument Name Description Required
vm-uuid VM UUID of virtual machine to reboot. Required

Context Output

Path Type Description
VMWare.UUID String VM instance UUID.
VMWare.State String VM state (i.e., poweredOn, poweredOff, suspended, HardRebooted).

Command Example

!vmware-hard-reboot vm-uuid="503ca58b-0821-cf21-fb56-459e55df6d19"

Context Example

{
 "VMWare": {
     "State": "HardRebooted",
     "UUID": "503ca58b-0821-cf21-fb56-459e55df6d19"
   }
}

Human Readable Output

Virtual Machine was rebooted successfully.

vmware-suspend


Suspends a powered-on virtual machine.

Base Command

vmware-suspend

Input

Argument Name Description Required
vm-uuid VM UUID of virtual machine to be suspended. Required

Context Output

Path Type Description
VMWare.UUID String VM instance UUID.
VMWare.State String VM state (i.e., poweredOn, poweredOff, suspended, HardRebooted).

Command Example

!vmware-suspend vm-uuid="503ca58b-0821-cf21-fb56-459e55df6d19"

Context Example

{
 "VMWare": {
     "State": "suspended",
     "UUID": "503ca58b-0821-cf21-fb56-459e55df6d19"
   }
}

Human Readable Output

Virtual Machine was suspended successfully.

vmware-soft-reboot


Issues a command to the guest operating system asking it to perform a reboot.

Base Command

vmware-soft-reboot

Input

Argument Name Description Required
vm-uuid VM UUID of virtual machine to reboot. Required

Context Output

There is no context output for this command.

Command Example

!vmware-soft-reboot vm-uuid="503ca58b-0821-cf21-fb56-459e55df6d19"

Human Readable Output

A request to reboot the guest has been sent.

vmware-create-snapshot


Creates a VM snapshot.

Base Command

vmware-create-snapshot

Input

Argument Name Description Required
vm-uuid VM UUID of virtual machine to take snapshot of. Required
name Snapshot name. Optional
description Snapshot description. Optional
memory Snapshot the virtual machine’s memory. Possible values are: true, false. Default is True. Optional
quiesce Quiesce guest file system (needs VMWare Tools installed). Possible values are: true, false. Default is False. Optional

Context Output

There is no context output for this command.

Command Example

!vmware-create-snapshot vm-uuid="503ca58b-0821-cf21-fb56-459e55df6d19" name="SnapShotName" description="A daily snapshot of VM" memory=true quiesce=false

Human Readable Output

Snapshot SnapShotName completed.

vmware-revert-snapshot


Reverts VM to snapshot.

Base Command

vmware-revert-snapshot

Input

Argument Name Description Required
snapshot-name Snapshot name to revert to. Required
vm-uuid VM UUID of virtual machine to revert snapshot. Required

Context Output

Path Type Description
VMWare.UUID String VM instance UUID.
VMWare.Snapshot String Name of the snapshot reverted to.

Command Example

!vmware-revert-snapshot vm-uuid="503ca58b-0821-cf21-fb56-459e55df6d19" snapshot-name="SnapShotName"

Context Example

{
 "VMWare": {
     "Snapshot": "Reverted to SnapShotName",
     "UUID": "503ca58b-0821-cf21-fb56-459e55df6d19"
   }
}

Human Readable Output

Reverted to snapshot SnapShotName successfully.

vmware-get-events


Gets events of a VM.

Base Command

vmware-get-events

Input

Argument Name Description Required
vm-uuid VM UUID of virtual machine to get events of. Required
event-type Type of events to get, given in CSV (i.e., VmGuestRebootEvent,VmGuestShutdownEvent). Default is VmGuestRebootEvent,VmGuestShutdownEvent,VmPoweredOnEvent,VmPoweredOffEvent,VmSuspendedEvent. Optional
start-date Event’s start date. Optional
end-date Event’s end date. Optional
user User name. Optional
limit Number of events to return. Default is 50. Optional

Context Output

Path Type Description
VMWareEvents.id String The id of the event.
VMWareEvents.Event String Description of the event.
VMWareEvents.CreatedTime String Creation time of the event.
VMWareEvents.UserName Date The user name of the user who triggered the event.

Command Example

!vmware-get-events vm-uuid=525306-77f9-ac98-77d3-63bb537ad7d2 start-date="2021-12-14T00:00:00" end-date="2021-12-16T00:00:00" user="VSPHERE.TEST"

Context Example

{
  "VMWareEvenet": [
        {
            "CreatedTime": "2021-12-15 09:38:46", 
            "UserName": "VSPHERE.TEST", 
            "Event": "Guest OS reboot for Datacenter", 
            "id": 99973
        }
    ]
}

Human Readable Output

CreatedTime Event UserName id
2021-12-15 09:38:46 Guest OS reboot for Datacenter VSPHERE.TEST 999

vmware-change-nic-state


Changes the state of a VM NIC.

Base Command

vmware-change-nic-state

Input

Argument Name Description Required
vm-uuid VM UUID of virtual machine to change NIC state. Required
nic-state New state of the NIC to be changed. Possible values are: connect, disconnect, delete. Required
nic-number Number of the NIC to be changed. Required

Context Output

Path Type Description
VMWare.UUID String VM instance UUID.
VMWare.NICState String VM NIC state (i.e., connected, disconnected, delete).

Command Example

!vmware-change-nic-state vm-uuid="503ca58b-0821-cf21-fb56-459e55df6d19" nic-state="disconnected" nic-number=1

Context Example

{
 "VMWare": {
     "NICState": "disconnected",
     "UUID": "503ca58b-0821-cf21-fb56-459e55df6d19"
   }
}

Human Readable Output

Virtual Machine’s NIC was disconnected successfully.

vmware-list-vms-by-tag


Lists all virtual storage objects attached to the tag.

Base Command

vmware-list-vms-by-tag

Input

Argument Name Description Required
category The category to which the tag belongs. Required
tag The tag to be queried. Required

Context Output

Path Type Description
VMWareTag.TagName String The tag that was queried.
VMwareTag.Category String The category to which the tag belongs.
VMwareTag.VM String VM name which the tag attached to.

Command Example

!vmware-list-vms-by-tag category="Test Category" tag=test

Context Example

{
  "VMWareTag": [
        {
            "Category": "Test Category", 
            "VM": "CentOS7_VMware_Integration_Test", 
            "TagName": "test"
        }, 
        {
            "Category": "Test Category", 
            "VM": "enhancement test 2", 
            "TagName": "test"
        }, 
        {
            "Category": "Test Category", 
            "VM": "VMware_enhancement_test_vm", 
            "TagName": "test"
        }
    ]}

Human Readable Output

Category TagName VM
Test Category test Integration_Test
Test Category test enhancement test 2
Test Category test VMware_enhancement_test_vm

vmware-create-vm


Creates a new virtual machine in the current folder and attaches it to the specified resource pool. This operation creates a virtual machine, instead of cloning a virtual machine from an existing one.

Base Command

vmware-create-vm

Input

Argument Name Description Required
name Display name of the virtual machine. Required
cpu-num Number of virtual processors in a virtual machine. Required
cpu-allocation Resource limits for CPU. Required
memory Resource limits for memory. Required
virtual-memory Size of a virtual machine’s memory, in MB. Required
guestld Short guest operating system identifier. Optional
guest-os-familiy description. Required
guest-os-version description. Required
host The target host on which the virtual machine will run. Required
folder The target folder in which the virtual machine will be located. Required
pool The resource pool to which the virtual machine will be attached. Optional

Context Output

Path Type Description
VMWare.vName String VM name.
VMWare.Template bool true if template, else false.
VMWare.Path String Path to VM.
VMWare.Guest String Guest full name.
VMWare.UUID String VM instance UUID.
VMWare.IP String VM IP address.
VMWare.State String VM state (i.e., poweredOn, poweredOff, suspended, HardRebooted).
VMWare.HostName String Host name of VM.
VMWare.MACAddress String MAC address of VM.
VMWare.SnapshotCreateDate String Create date of the last snapshot of the VM.
VMWare.SnapshotUUID String UUID of the last snapshot of the VM.
VMWare.Deleted Boolean If set to true, the VM was deleted.

Command Example

!vmware-create-vm cpu-allocation=1 cpu-num=1 guest-os-familiy=Windows guest-os-version="Microsoft Windows Server 2019 (64-bit)" host=11.11.1.111 memory=32 name="test_vm_ui" virtual-memory=32 folder="vm"

Context Example

{
  "VMWare": [
        {
           "MACAddress": "", 
            "Name": "test_vm_ui", 
            "Deleted": false, 
            "IP": " ", 
            "HostName": " ", 
            "SnapshotCreateDate": "", 
            "UUID": "503d-11bc-834e-51a8-51b19a1b6924", 
            "State": "poweredOff", 
            "Snapshot": " ", 
            "Template": false, 
            "SnapshotUUID": "", 
            "Path": "[datastore1] test_vm_ui/test_vm_ui.vmx", 
            "Guest": "Other (32-bit)"
        }
    ]
}

Human Readable Output

Name Template Path Guest UUID State Deleted
test_vm_ui false [datastore1] test_vm_ui/test_vm_ui.vmx Other (32-bit) 503d9bc9-5c5a-603e-65d9-0fea7b29b9a7 poweredOff false

vmware-clone-vm


Creates a clone of this virtual machine. If the virtual machine is used as a template, this method corresponds to the deploy command.

Base Command

vmware-clone-vm

Input

Argument Name Description Required
uuid The UUID of the VM to clone. Required
name The name of the new virtual machine. Required
folder The location of the new virtual machine. Required
template Specifies whether or not the new virtual machine should be marked as a template. Optional
powerOn Specifies whether or not the new VirtualMachine should be powered on after creation. Possible values are: true, false. Default is False. Required
datastore The datastore where the virtual machine should be located. Optional
host The target host for the virtual machine. Optional
pool The resource pool to which this virtual machine should be attached. Optional

Context Output

Path Type Description
VMWare.Name String VM name.
VMWare.Template bool true if template, else false.
VMWare.Path String Path to VM.
VMWare.Guest String Guest full name.
VMWare.UUID String VM instance UUID.
VMWare.IP String VM IP address.
VMWare.State String VM state (i.e., poweredOn, poweredOff, suspended, HardRebooted).
VMWare.HostName String Host name of VM.
VMWare.MACAddress String MAC address of VM.
VMWare.SnapshotCreateDate String Create date of the last snapshot of the VM.
VMWare.SnapshotUUID String UUID of the last snapshot of the VM.
VMWare.Deleted Boolean If set to true, the VM was deleted.

Command Example

!vmware-clone-vm folder=vm name=cloned_vm powerOn=false uuid=603e-65d9-0fea7b29b9a7

Context Example

{
  "VMWare": [
        {
            "MACAddress": "", 
            "Name": "cloned_vm", 
            "Deleted": false, 
            "IP": " ", 
            "HostName": " ", 
            "SnapshotCreateDate": "", 
            "UUID": "e5aa-8fe8-a3faf1191395", 
            "State": "poweredOff", 
            "Template": false, 
            "SnapshotUUID": "", 
            "Path": "[datastore1] cloned_vm/cloned_vm.vmx", 
            "Guest": "Other (32-bit)"
        }
    ]
}

Human Readable Output

Name Template Path Guest UUID State Deleted
cloned_vm false [datastore1] cloned_vm/cloned_vm.vmx Other (32-bit) e5aa-8fe8-a3faf1191395 poweredOff false

vmware-relocate-vm


Relocates a virtual machine to a specified location.

Base Command

vmware-relocate-vm

Input

Argument Name Description Required
datastore The datastore where the virtual machine should be located. If not specified, the current datastore is used. Optional
folder The folder where the virtual machine should be located. Required
host The target host for the virtual machine. Optional
pool The resource pool to which this virtual machine should be attached. Optional
service The service endpoint of vCenter where the virtual machine should be located. If not specified, the current vCenter service is used. Optional
profile Storage profile requirement for Virtual Machine’s home directory. Optional
priority The task priority. Possible values are: defaultPriority, highPriority, lowPriority. Required
uuid The UUID of the VM to relocate. Required

Context Output

There is no context output for this command.

Command Example

!vmware-relocate-vm folder=enhancement_check priority=defaultPriority uuid=e5aa-8fe8-a3faf1191395

Human Readable Output

Virtual Machine was relocated successfully.

vmware-delete-vm


Destroys this object, deleting its contents and removing it from its parent folder (if any).

Base Command

vmware-delete-vm

Input

Argument Name Description Required
uuid The UUID of the VM to delete. Required

Context Output

Path Type Description
VMWare.UUID String VM instance UUID.
VMWare.Deleted String If set to true, the VM was deleted.

Command Example

!vmware-delete-vm uuid=503d537f-a8d0-e5aa-8fe8-a3faf1191395

Human Readable Output

Virtual Machine was deleted successfully.

vmware-register-vm


Adds an existing virtual machine to the folder.

Base Command

vmware-register-vm

Input

Argument Name Description Required
path A datastore path to the virtual machine. Required
name The name to be assigned to the virtual machine. Required
host The target host on which the virtual machine will run. Required
asTemplate Flag to specify whether or not the virtual machine should be marked as a template. Possible values are: true, false. Default is False. Optional
folder Folder to register the VM to. Required

Context Output

There is no context output for this command.

Command Example

!vmware-register-vm path="[datastore1] test_vm_ui/test_vm_ui.vmx" folder=vm host=192.168.1.140 name=rgistered_vm asTemplate=false

Human Readable Output

Virtual Machine was registered successfully.

vmware-unregister-vm


emoves this virtual machine from the inventory without removing any of the virtual machine’s files on disk.

Base Command

vmware-unregister-vm

Input

Argument Name Description Required
uuid The UUID of the VM to remove. Required

Context Output

There is no context output for this command.

Command Example

!vmware-unregister-vm uuid=503d9bc9-5c5a-603e-65d9-0fea7b29b9a7

Human Readable Output

Virtual Machine was unregistered successfully.

Configuration parameters

  • url — Server URL (i.e., 192.168.0.1:30022) (required)
  • credentials — Credentials (required)
  • redirect_std_out — Redirect stdout
  • insecure — Trust any certificate (not secure)
  • proxy — Use system proxy settings

Commands (17)

  • vmware-change-nic-state

    Changes the state of a VM NIC.

  • vmware-clone-vm

    Creates a clone of this virtual machine. If the virtual machine is used as a template, this method corresponds to the deploy command.

  • vmware-create-snapshot

    Creates VM snapshot.

  • vmware-create-vm

    Creates a new virtual machine in the current folder and attaches it to the specified resource pool. This operation creates a virtual machine, rather than cloning an existing one.

  • vmware-delete-vm

    Destroys this object, deleting its contents and removing it from its parent folder (if any).

  • vmware-get-events

    Gets events of VM.

  • vmware-get-vms

    Returns all virtual machines on a system.

  • vmware-hard-reboot

    Reboots a powered-on virtual machine.

  • vmware-list-vms-by-tag

    Lists all virtual storage objects attached to the tag.

  • vmware-poweroff

    Powers off a powered-on or suspended virtual machine.

  • vmware-poweron

    Powers on a powered-off or suspended virtual machine.

  • vmware-register-vm

    Adds an existing virtual machine to the folder.

  • vmware-relocate-vm

    Relocates a virtual machine to a specified location.

  • vmware-revert-snapshot

    Reverts VM to snapshot.

  • vmware-soft-reboot

    Issues a command to the guest operating system asking it to perform a reboot.

  • vmware-suspend

    Suspends a powered-on virtual machine.

  • vmware-unregister-vm

    Removes this virtual machine from the inventory without removing any of the virtual machine's files on disk.

from collections import namedtuple
from datetime import datetime

import pytest
import pyVim.task
import VMware
from pyVmomi import vim

# testing classes

device_info = namedtuple("device_info", ["label", "key", "macAddress", "backing", "wakeOnLanEnabled"])


CLIENT_FULL_URL = "vcenter.example.com:443"
CLIENT_USER_NAME = "test_user"
CLIENT_PASSWORD = "test_pass"
CLIENT_SESSION_ID = "test-session-id"


class Runtime:
    powerState = None

    def __init__(self, powerState):
        self.powerState = powerState


class DeviceInfo:
    deviceInfo = device_info("Network adapter 123", "test key", "test mac", "backing", True)


class Hardware:
    device_obj = vim.vm.device.VirtualEthernetCard()  # type: ignore
    device_obj.deviceInfo = vim.Description()  # type: ignore
    device_obj.deviceInfo.label = "Network adapter 123"
    device_obj.macAddress = "mac test"
    device_obj.backing = vim.vm.device.VirtualDevice.BackingInfo()  # type: ignore
    device_obj.wakeOnLanEnabled = True
    device = [device_obj]


class Config:
    template = None
    vmPathName = None
    guestFullName = None
    instanceUuid = None
    powerState = None
    name = None
    uuid = None
    hardware = Hardware()

    def __init__(self, name, instanceUuid):
        self.name = name
        self.instanceUuid = instanceUuid


class Guest:
    ipAddress = None
    hostName = None

    def __init__(self, ipAddress, hostName):
        self.ipAddress = ipAddress
        self.hostName = hostName


class Summary:
    guest = None
    runtime = None
    config = None

    def __init__(self, ipAddress=None, hostName=None, name="test_name", instanceUuid="12345"):
        self.config = Config(name, instanceUuid)
        self.guest = Guest(ipAddress, hostName)
        self.runtime = Runtime("poweredOff")


class VM:
    runtime = None
    summary = None
    config = None

    def __init__(self, powerState="poweredOn"):
        self.runtime = Runtime(powerState)
        self.summary = Summary(name="test_vm_name")
        self.config = Config("test", "12345")

    def RelocateVM_Task(self):
        pass

    def Destroy_Task(self):
        pass

    def UnregisterVM(self):
        pass

    def CloneVM_Task(self):
        pass

    def list(self):
        pass

    def FilterSpec(self):
        pass

    def PowerOn(self):
        pass

    def PowerOff(self):
        pass

    def Suspend(self):
        pass

    def ResetVM_Task(self):
        pass

    def RebootGuest(self):
        pass

    def CreateSnapshot(self):
        pass

    def ReconfigVM_Task(self):
        pass


class ResourcePool:
    resourcePool = None


class Folder:
    parent = ResourcePool()

    def RegisterVM_Task(self):
        pass

    def CreateVM_Task(self):
        pass


class Category:
    def __init__(self):
        pass

    def list(self):
        pass

    def get(self):
        pass


class Tag:
    def list_tags_for_category(self):
        pass

    def get(self):
        pass


class TagAssociation:
    def attach(self):
        pass

    def list_attached_objects(self):
        pass


class Tagging:
    Category = Category()
    Tag = Tag()
    TagAssociation = TagAssociation()


class Vcenter:
    VM = VM()


class VsphereClient:
    tagging = Tagging()
    vcenter = Vcenter()


class Si:
    def RetrieveContent(self):
        pass

    def RetrieveServiceContent(self):
        pass


class VirtualMachineRelocateSpec:
    folder = None
    host = None
    pool = None
    datastore = None
    disks = None


class CloneSpec:
    location = None
    template = False
    powerOn = False


class Result:
    summary = Summary()
    snapshot = None


class Info:
    state = "success"
    result = Result()


class Task:
    info = Info()


class Child:
    summary = Summary()
    snapshot = None

    def __init__(self, summary):
        self.summary = summary


class ViewManager:
    view = None

    def __init__(self, children):
        self.view = children

    def CreateContainerView(self):
        pass


class EventManager:
    def QueryEvents(self):
        pass


class Content:
    viewManager = ViewManager({})
    eventManager = EventManager()
    rootFolder = None


class Snapshot:
    name = None
    childSnapshotList = None

    def __init__(self, name, childSnapshotList):
        self.name = name
        self.childSnapshotList = childSnapshotList


class Datastore:
    name = None

    def __init__(self, name):
        self.name = name


class Host:
    datastore = []  # type: ignore

    def __init__(self, names):
        for name in names:
            self.datastore.append(Datastore(name))


class ConfigSpec:
    name = None
    numCPUs = None
    cpuAllocation = None
    memoryAllocation = None
    memoryMB = None
    files = None
    guestId = None


class FileInfo:
    vmPathName = None


class ResourceAllocationInfo:
    limit = None


class ByTime:
    beginTime = None
    endTime = None


class ByUserName:
    userList = None


class FilterSpec:
    eventTypeId = None
    entity = None
    time = None
    userName = None
    maxCount = None
    ByTime = ByTime()
    ByUserName = ByUserName()

    def ByEntity(self):
        pass


class Event:
    key = None
    fullFormattedMessage = None
    createdTime = None
    userName = None
    EventFilterSpec = FilterSpec()

    def __init__(self, key=None, message=None, user_name=None, created_time=None):
        self.key = key
        self.fullFormattedMessage = message
        self.userName = user_name
        self.createdTime = created_time


class Vim:
    event = Event()


# testing

category = namedtuple("category", ["name", "id"])
tag = namedtuple("tag", ["name", "id"])
obj = namedtuple("obj", ["name", "id", "type"])

PARAMS_GET_VM_FILTERS = [
    (
        {"ip": "1111", "vm_name": "test_vm", "uuid": "12345", "hostname": "test_host"},
        {"ipAddress": "1111", "name": "test_vm", "uuid": "12345", "hostname": "test_host"},
        True,
    ),
    (
        {"ip": "1111", "vm_name": None, "uuid": "12345", "hostname": "test_host"},
        {"ipAddress": "1111", "name": "test_vm", "uuid": "12345", "hostname": "test_host"},
        True,
    ),
    (
        {"ip": "1111", "vm_name": "test_vm", "uuid": None, "hostname": "test_host"},
        {"ipAddress": "1111", "name": "test_vm", "uuid": "12345", "hostname": "test_host"},
        True,
    ),
    (
        {"ip": None, "vm_name": "test_vm", "uuid": "12345", "hostname": "test_host"},
        {"ipAddress": "1111", "name": "test_vm", "uuid": "12345", "hostname": "test_host"},
        True,
    ),
    (
        {"ip": "1111", "vm_name": "test_vm", "uuid": "12345", "hostname": None},
        {"ipAddress": "1111", "name": "test_vm", "uuid": "12345", "hostname": "test_host"},
        True,
    ),
    (
        {"ip": None, "vm_name": "test_vm", "uuid": "12345", "hostname": None},
        {"ipAddress": "1111", "name": "test_vm", "uuid": "1234", "hostname": "test_host"},
        False,
    ),
    (
        {"ip": "1111", "vm_name": "test_vm", "uuid": None, "hostname": None},
        {"ipAddress": "1111", "name": "tet_vm", "uuid": "12345", "hostname": "test_host"},
        False,
    ),
    (
        {"ip": "1111", "vm_name": "test_vm", "uuid": None, "hostname": None},
        {"ipAddress": "111", "name": "test_vm", "uuid": "12345", "hostname": "test_host"},
        False,
    ),
]

PARAMS_GET_VMS = [
    ({"ip": "1111", "name": "test_vm1", "uuid": "12341", "hostname": "test_host1"}),
    ({"ip": "2222", "name": "test_vm2", "uuid": "12342", "hostname": "test_host2"}),
    ({"ip": "3333", "name": "test_vm3", "uuid": "12343", "hostname": "test_host3"}),
]

PARAMS_CREATE_SNAPSHOT = [
    ({"vm-uuid": "12345", "memory": "True", "quiesce": "True"}),
    {"vm-uuid": "12345", "memory": "False", "quiesce": "False"},
]

PARAMS_GET_SNAPSHOTS = [
    ([Snapshot("test1", [Snapshot("test3", [])]), Snapshot("test2", [])], "test2", [Snapshot("test2", [])]),
    ([Snapshot("test1", [Snapshot("test3", [])]), Snapshot("test2", [])], "test3", [Snapshot("test3", [])]),
    ([Snapshot("test1", [Snapshot("test3", [])]), Snapshot("test2", [])], "test1", [Snapshot("test1", [Snapshot("test3", [])])]),
    ([Snapshot("test1", [Snapshot("test3", [])]), Snapshot("test2", [])], "test4", []),
]

EVENTS = [
    {"key": "1", "message": "reboot VM", "user_name": "test_user", "created_time": datetime(2021, 12, 16, 10, 10, 10)},
    {"key": "2", "message": "shutdown VM", "user_name": "test_user2", "created_time": datetime(2021, 12, 15, 10, 10, 10)},
    {"key": "3", "message": "hard reboot VM", "user_name": "test_user", "created_time": datetime(2021, 12, 13, 10, 10, 10)},
]

PARAMS_GET_EVENTS = [
    (
        {
            "vm-uuid": "123",
            "user": "test_user,test_user2",
            "start_date": "2019-10-23T00:00:00",
            "end_date": "2021-12-16T12:00:00",
            "event-type": "",
            "limit": "50",
        },
        EVENTS,
        3,
    ),
    (
        {
            "vm-uuid": "123",
            "user": "test_user",
            "start_date": "2019-10-23T00:00:00",
            "end_date": "2021-12-16T12:00:00",
            "event-type": "",
            "limit": "50",
        },
        [EVENTS[0], EVENTS[2]],
        2,
    ),
    (
        {
            "vm-uuid": "123",
            "user": "test_user2",
            "start_date": "2019-10-23T00:00:00",
            "end_date": "2021-12-16T12:00:00",
            "event-type": "reboot VM",
            "limit": "50",
        },
        [EVENTS[1]],
        1,
    ),
    (
        {
            "vm-uuid": "123",
            "user": "",
            "start_date": "2019-10-23T00:00:00",
            "end_date": "2021-12-16T12:00:00",
            "event-type": "reboot VM",
            "limit": "50",
        },
        [EVENTS[1]],
        1,
    ),
]

PARAMS_GET_PRIORITY = [
    ("highPriority", vim.VirtualMachine.MovePriority().highPriority),
    ("lowPriority", vim.VirtualMachine.MovePriority().lowPriority),
    ("defualt", vim.VirtualMachine.MovePriority().defaultPriority),
]

ARG_LIST = [
    ({"limit": "2", "page_size": "3"}, 2, False, 3),
    ({"page_size": "3", "page": "4"}, 12, True, 3),
    ({}, 50, False, None),
]

PARAMS_PARSE = [
    (
        {"url": "test.com:443", "credentials": {"identifier": "test", "password": "testpass"}},
        "test.com:443",
        "test.com",
        "443",
        "test",
        "testpass",
    ),
    (
        {"url": "https://test.com:443", "credentials": {"identifier": "test", "password": "testpass"}},
        "https://test.com:443",
        "https://test.com",
        "443",
        "test",
        "testpass",
    ),
]


def create_children():
    return [Child(Summary(args.get("ip"), args.get("hostname"), args.get("name"), args.get("uuid"))) for args in PARAMS_GET_VMS]


def create_events(events_list):
    return [Event(args.get("key"), args.get("message"), args.get("user_name"), args.get("created_time")) for args in events_list]


@pytest.mark.parametrize("params, full_url, url, port, username, password", PARAMS_PARSE)
def test_parse_params(params, full_url, url, port, username, password):
    """
    Given:
        - Instance parameters.

    When:
        - Connecting to vcenter.

    Then:
        - Make sure that parameters parsed correctly.
    """
    full_url_from_func, url_from_func, port_from_func, user_name_from_func, password_from_func = VMware.parse_params(params)
    assert full_url_from_func == full_url
    assert url_from_func == url
    assert port_from_func == port
    assert user_name_from_func == username
    assert password_from_func == password


@pytest.mark.parametrize("args, limit, is_manual, page_size", ARG_LIST)
def test_get_limit(args, limit, is_manual, page_size):
    """
    Given:
        - pagination arguments.

    When:
        - Running a list command.

    Then:
        - Make sure that the correct amount of results to display is returned.
    """
    res_limit, res_is_manual, res_page_size = VMware.get_limit(args)

    assert res_limit == limit
    assert res_is_manual == is_manual
    assert res_page_size == page_size


@pytest.mark.parametrize("input_val, output", PARAMS_GET_PRIORITY)
def test_get_priority(input_val, output):
    """
    Given:
        - Priority string.

    When:
        - Running a relocate command

    Then:
        - Make sure a correct vmware priority object is returned.
    """
    assert VMware.get_priority(input_val) == output


@pytest.mark.parametrize("args, params, res", PARAMS_GET_VM_FILTERS)
def test_apply_get_vms_filters(args, params, res):
    """
    Given:
        - Filter argumnets.

    When:
        - Running a get-vms command

    Then:
        - Make sure only vms containing filter values returned.
    """
    summary = Summary(params.get("ipAddress"), params.get("hostname"), params.get("name"), params.get("uuid"))
    assert VMware.apply_get_vms_filters(args, summary) == res


def test_create_vm_config_creator(monkeypatch):
    """
    Given:
        - Create VM argumnets.

    When:
        - Running a create-vm command

    Then:
        - Make sure a correct vmware create_vm config object is returned.
    """
    monkeypatch.setattr(vim.vm, "ConfigSpec", lambda: ConfigSpec())
    monkeypatch.setattr(vim.vm, "FileInfo", lambda: FileInfo())
    monkeypatch.setattr(vim, "ResourceAllocationInfo", lambda: ResourceAllocationInfo())

    args = {"name": "test1", "cpu-allocation": "2", "memory": "32", "cpu-num": "4", "virtual-memory": "32", "": "1"}
    res = VMware.create_vm_config_creator(Host(["test1", "test2"]), args)

    assert res.name == args.get("name")
    assert res.numCPUs == int(args.get("cpu-num"))
    assert res.cpuAllocation.limit == int(args.get("cpu-allocation"))
    assert res.memoryAllocation.limit == int(args.get("memory"))
    assert res.memoryMB == int(args.get("virtual-memory"))
    assert res.files.vmPathName == "[test1]test1"
    assert res.guestId == args.get("guest-id")


def test_create_vm(monkeypatch):
    """
    Given:
        - Create vm arguments.

    When:
        - Running a create-vm command

    Then:
        - Make sure a vm is created and the correct arguments are returned.
    """
    si = Si()
    monkeypatch.setattr(si, "RetrieveContent", dict)
    monkeypatch.setattr(VMware, "wait_for_tasks", lambda si_obj, tasks: None)
    monkeypatch.setattr(VMware, "create_vm_config_creator", lambda host, args: {})
    monkeypatch.setattr(VMware, "search_for_obj", lambda content, type_obj, obj: Folder())
    monkeypatch.setattr(Folder, "CreateVM_Task", lambda this, config, pool, host: Task())

    res = VMware.create_vm(si, {"folder": "test_folder", "host": "test_host", "pool": "test_pool"})

    data = res.get("Contents")
    assert data.get("Name") == "test_name"
    assert not data.get("Deleted")
    assert "Virtual Machine" in res.get("HumanReadable")


def test_get_vms(monkeypatch):
    """
    Given:
        -

    When:
        - Running a get-vms command.

    Then:
        - Make sure a correct list of vms are returned .
    """
    si = Si()
    monkeypatch.setattr(si, "RetrieveContent", lambda: Content())
    monkeypatch.setattr(
        ViewManager, "CreateContainerView", lambda this, container, view_type, recursive: ViewManager(create_children())
    )
    monkeypatch.setattr(VMware, "apply_get_vms_filters", lambda args, summary: True)

    res = VMware.get_vms(si, {})

    data = res.get("Contents")
    for i in range(len(PARAMS_GET_VMS)):
        args = PARAMS_GET_VMS[i]
        assert data[i].get("Name") == args.get("name")
        assert data[i].get("IP") == args.get("ip")
        assert data[i].get("HostName") == args.get("hostname")
        assert data[i].get("UUID") == args.get("uuid")
        assert not data[i].get("Deleted")
    assert "Virtual Machines" in res.get("HumanReadable")


def test_clone_vm(monkeypatch):
    """
    Given:
        - Clone vm arguments.

    When:
        - Running a clone-vm command

    Then:
        - Make sure the correct results are returned.
    """
    si = Si()
    monkeypatch.setattr(si, "RetrieveContent", dict)
    monkeypatch.setattr(vim.vm, "CloneSpec", lambda: CloneSpec())
    monkeypatch.setattr(vim.vm, "RelocateSpec", lambda: VirtualMachineRelocateSpec())
    monkeypatch.setattr(VMware, "wait_for_tasks", lambda si_obj, tasks: None)
    monkeypatch.setattr(VMware, "get_vm", lambda v_client, uuid: VM())
    monkeypatch.setattr(VMware, "search_for_obj", lambda content, type_obj, obj: obj)
    monkeypatch.setattr(VM, "CloneVM_Task", lambda this, folder, name, spec: Task())

    res = VMware.clone_vm(
        si,
        {
            "folder": "test_folder",
            "host": "test_host",
            "pool": "test_pool",
            "datastore": "test_datastore",
            "template": False,
            "powerOn": False,
            "uuid": "12345",
        },
    )
    data = res.get("Contents")
    assert data.get("Name") == "test_name"
    assert not data.get("Deleted")
    assert "Virtual Machine" in res.get("HumanReadable")


def test_relocate_vm(monkeypatch):
    """
    Given:
        - Relocate vm arguments.

    When:
        - Running a relocate-vm command

    Then:
        - Make sure the correct results are returned.
    """
    si = Si()
    monkeypatch.setattr(si, "RetrieveContent", dict)
    monkeypatch.setattr(vim, "VirtualMachineRelocateSpec", lambda: VirtualMachineRelocateSpec())
    monkeypatch.setattr(VMware, "wait_for_tasks", lambda si_obj, tasks: None)
    monkeypatch.setattr(VMware, "get_vm", lambda v_client, uuid: VM())
    monkeypatch.setattr(VMware, "search_for_obj", lambda content, type_obj, obj: obj)
    monkeypatch.setattr(VM, "RelocateVM_Task", lambda this, spec, priority: Task())

    res = VMware.relocate_vm(si, {"folder": "test_folder", "host": "test_host", "pool": "test_pool", "datastore": None})
    assert res.get("HumanReadable") == "Virtual Machine was relocated successfully."


def test_delete_vm(monkeypatch):
    """
    Given:
        - Delete vm UUID.

    When:
        - Running a delete-vm command

    Then:
        - Make sure the correct results are returned.
    """
    si = Si()
    monkeypatch.setattr(VMware, "wait_for_tasks", lambda si_obj, tasks: None)
    monkeypatch.setattr(VMware, "get_vm", lambda v_client, uuid: VM("poweredOff"))
    monkeypatch.setattr(VM, "Destroy_Task", lambda this: Task())

    res = VMware.delete_vm(si, {"uuid": "12345"})
    assert res.get("HumanReadable") == "Virtual Machine was deleted successfully."
    assert {"UUID": "12345", "Deleted": True} in list(res.get("EntryContext").values())


def test_register_vm(monkeypatch):
    """
    Given:
        - Register vm arguments.

    When:
        - Running a register-vm command

    Then:
        - Make sure the correct results are returned.
    """
    si = Si()
    monkeypatch.setattr(si, "RetrieveContent", dict)
    monkeypatch.setattr(vim, "VirtualMachineRelocateSpec", lambda: VirtualMachineRelocateSpec())
    monkeypatch.setattr(VMware, "wait_for_tasks", lambda si_obj, tasks: None)
    monkeypatch.setattr(VMware, "search_for_obj", lambda content, type_obj, obj: Folder())
    monkeypatch.setattr(Folder, "RegisterVM_Task", lambda this, path, name, asTemplate, pool, host: Task())

    res = VMware.register_vm(
        si, {"folder": "test_folder", "host": "test_host", "pool": "test_pool", "path": None, "as_template": False}
    )
    assert res.get("HumanReadable") == "Virtual Machine was registered successfully."


def test_unregister_vm(monkeypatch):
    """
    Given:
        - VM UUID to unregister.

    When:
        - Running a unregister-vm command

    Then:
        - Make sure the correct results are returned.
    """
    si = Si()
    monkeypatch.setattr(VMware, "get_vm", lambda v_client, uuid: VM())
    monkeypatch.setattr(VM, "UnregisterVM", lambda this: None)

    res = VMware.unregister_vm(si, {"uuid": "12345"})
    assert res.get("HumanReadable") == "Virtual Machine was unregistered successfully."


def test_power_on(monkeypatch):
    """
    Given:
        - VM UUID to power on.

    When:
        - Running a poweron-vm command

    Then:
        - Make sure the correct results are returned.
    """
    si = Si()
    monkeypatch.setattr(VMware, "get_vm", lambda v_client, uuid: VM("powerOff"))
    monkeypatch.setattr(VM, "PowerOn", lambda this: Task())

    res = VMware.power_on(si, {"uuid": "12345"})

    assert list(res.get("EntryContext").values())[0].get("State") == "poweredOn"
    assert res.get("HumanReadable") == "Virtual Machine was powered on successfully."


def test_power_off(monkeypatch):
    """
    Given:
        - VM UUID to power off.

    When:
        - Running a poweroff-vm command

    Then:
        - Make sure the correct results are returned.
    """
    si = Si()
    monkeypatch.setattr(VMware, "get_vm", lambda v_client, uuid: VM("powerOn"))
    monkeypatch.setattr(VM, "PowerOff", lambda this: Task())

    res = VMware.power_off(si, {"uuid": "12345"})

    assert list(res.get("EntryContext").values())[0].get("State") == "poweredOff"
    assert res.get("HumanReadable") == "Virtual Machine was powered off successfully."


def test_suspend(monkeypatch):
    """
    Given:
        - VM UUID to suspend.

    When:
        - Running a suspend-vm command

    Then:
        - Make sure the correct results are returned.
    """
    si = Si()
    monkeypatch.setattr(VMware, "get_vm", lambda v_client, uuid: VM("powerOn"))
    monkeypatch.setattr(VM, "Suspend", lambda this: Task())

    res = VMware.suspend(si, {"uuid": "12345"})

    assert list(res.get("EntryContext").values())[0].get("State") == "suspended"
    assert res.get("HumanReadable") == "Virtual Machine was suspended successfully."


def test_hard_reboot(monkeypatch):
    """
    Given:
        - VM UUID to hard reboot.

    When:
        - Running a hard-reboot-vm command

    Then:
        - Make sure the correct results are returned.
    """
    si = Si()
    monkeypatch.setattr(VMware, "get_vm", lambda v_client, uuid: VM())
    monkeypatch.setattr(VM, "ResetVM_Task", lambda this: Task())
    monkeypatch.setattr(VMware, "wait_for_tasks", lambda si_obj, tasks: None)

    res = VMware.hard_reboot(si, {"uuid": "12345"})

    assert list(res.get("EntryContext").values())[0].get("State") == "HardRebooted"
    assert res.get("HumanReadable") == "Virtual Machine was rebooted successfully."


def test_soft_reboot(monkeypatch):
    """
    Given:
        - VM UUID to soft reboot.

    When:
        - Running a sot-reboot-vm command

    Then:
        - Make sure the correct results are returned.
    """
    si = Si()
    monkeypatch.setattr(VMware, "get_vm", lambda v_client, uuid: VM())
    monkeypatch.setattr(VM, "RebootGuest", lambda this: None)

    res = VMware.soft_reboot(si, {"uuid": "12345"})

    assert res == "A request to reboot the guest has been sent."


@pytest.mark.parametrize("args", PARAMS_CREATE_SNAPSHOT)
def test_create_snapshot(monkeypatch, args):
    """
    Given:
        - VM UUID to create snapshot for.

    When:
        - Running a create-snapshot command

    Then:
        - Make sure the correct results are returned.
    """
    si = Si()
    monkeypatch.setattr(VMware, "get_vm", lambda v_client, uuid: VM())
    monkeypatch.setattr(VM, "CreateSnapshot", lambda this, name, description, memory, quiesce: Task())
    monkeypatch.setattr(pyVim.task, "WaitForTask", lambda task: None)

    res = VMware.create_snapshot(si, args)

    assert "Snapshot 12345" in res


@pytest.mark.parametrize("snapshots, snapname, res", PARAMS_GET_SNAPSHOTS)
def test_get_snapshots(monkeypatch, snapshots, snapname, res):
    """
    Given:
        - VM arguments to get snapshots for.

    When:
        - Running a get-snapshots-vm command

    Then:
        - Make sure the correct results are returned.
    """
    result = VMware.get_snapshots(snapshots, snapname)
    if len(result) > 0:
        assert result[0].name == res[0].name
        assert len(result[0].childSnapshotList) == len(res[0].childSnapshotList)
    else:
        assert len(res) == 0


@pytest.mark.parametrize("args, event_list, res_len", PARAMS_GET_EVENTS)
def test_get_events(monkeypatch, args, event_list, res_len):
    """
    Given:
        - Get events arguments.

    When:
        - Running a get-events command

    Then:
        - Make sure the correct results are returned.
    """
    si = Si()
    monkeypatch.setattr(si, "RetrieveServiceContent", lambda: Content())
    monkeypatch.setattr(VMware, "get_vm", lambda v_client, uuid: VM())
    monkeypatch.setattr(vim.event.EventFilterSpec.ByEntity, "__init__", lambda this, entity, recursion: None)
    monkeypatch.setattr(EventManager, "QueryEvents", lambda this, filter_spec: create_events(event_list))

    res = VMware.get_events(si, args)

    assert len(res.get("Contents")) == res_len
    assert "VM test_vm_name Events" in res.get("HumanReadable")


def test_change_nic_state(monkeypatch):
    """
    Given:
        - VM UUID to change nic for.

    When:
        - Running a change-nic-vm command

    Then:
        - Make sure the correct results are returned.
    """
    si = Si()
    monkeypatch.setattr(VMware, "get_vm", lambda v_client, uuid: VM())
    # monkeypatch.setattr(builtins, 'isinstance', lambda dev, dev_type: True)
    monkeypatch.setattr(VMware, "wait_for_tasks", lambda si_obj, tasks: None)
    monkeypatch.setattr(VM, "ReconfigVM_Task", lambda this, spec: Task())

    res = VMware.change_nic_state(si, {"vm-uuid": "1234", "nic-state": "connect", "nic-number": "123"})

    assert list(res.get("Contents").values())[0].get("UUID") == "1234"
    assert list(res.get("Contents").values())[0].get("NICState") == "connected"
    assert "Virtual Machine's NIC was connected successfully" in res.get("HumanReadable")


class TestClient:
    """Tests for the Client class."""

    def test_init(self, mocker):
        """
        Given:
            - Client initialization parameters.

        When:
            - Creating a new Client instance.

        Then:
            - Ensure the client is initialized correctly with session ID.
        """
        mock_http_request = mocker.patch.object(VMware.Client, "_http_request", return_value=f'"{CLIENT_SESSION_ID}"')

        client = VMware.Client(full_url=CLIENT_FULL_URL, user_name=CLIENT_USER_NAME, password=CLIENT_PASSWORD)

        assert client.user_name == CLIENT_USER_NAME
        assert client.password == CLIENT_PASSWORD
        assert client.session_id == CLIENT_SESSION_ID
        assert client._headers == {"vmware-api-session-id": CLIENT_SESSION_ID, "Content-Type": "application/json"}
        assert mock_http_request.call_args.kwargs == {
            "method": "POST",
            "url_suffix": "/api/session",
            "auth": (CLIENT_USER_NAME, CLIENT_PASSWORD),
            "resp_type": "text",
        }

    def test_get_session_id(self, mocker):
        """
        Given:
            - Valid credentials.

        When:
            - Calling _get_session_id method.

        Then:
            - Ensure session ID is returned correctly.
        """
        mocker.patch.object(VMware.Client, "_http_request", return_value=f'"{CLIENT_SESSION_ID}"')

        client = VMware.Client(full_url=CLIENT_FULL_URL, user_name=CLIENT_USER_NAME, password=CLIENT_PASSWORD)
        assert client.session_id == CLIENT_SESSION_ID

    def test_logout(self, mocker):
        """
        Given:
            - An active client session.

        When:
            - Calling logout method.

        Then:
            - Ensure the session is closed via DELETE request.
        """
        mock_http_request = mocker.patch.object(
            VMware.Client, "_http_request", side_effect=['"test-session-id"', None]
        )  # login, logout

        client = VMware.Client(full_url=CLIENT_FULL_URL, user_name=CLIENT_USER_NAME, password=CLIENT_PASSWORD)

        client.logout()

        assert mock_http_request.call_count == 2
        assert mock_http_request.call_args_list[1].kwargs == {
            "method": "DELETE",
            "url_suffix": "/api/session",
            "resp_type": "response",
        }

    def test_get_category_id(self, mocker):
        """
        Given:
            - A category name to search for.

        When:
            - Calling get_category_id method.

        Then:
            - Ensure the correct category ID is returned.
        """
        category_name = "test-category"  # Name of category whose ID we would like to get
        category_id = "cat-id-2"  # Assume this is the corresponding ID

        mock_http_request = mocker.patch.object(
            VMware.Client,
            "_http_request",
            side_effect=[
                f'"{CLIENT_SESSION_ID}"',  # INIT - Get session ID
                ["cat-id-1", category_id],  # STEP 1 - Get list of category IDs
                {"name": "wrong-category", "id": "cat-id-1"},  # STEP 2 - Get category details per ID (find match by name)
                {"name": category_name, "id": category_id},
            ],
        )

        client = VMware.Client(full_url=CLIENT_FULL_URL, user_name=CLIENT_USER_NAME, password=CLIENT_PASSWORD)

        assert client.get_category_id(category_name) == category_id
        # STEP 1 - Get list of category IDs
        assert mock_http_request.call_args_list[1].kwargs == {"method": "GET", "url_suffix": "/api/cis/tagging/category"}
        # STEP 2 - Get category details per ID (find match by name)
        assert mock_http_request.call_args_list[2].kwargs == {"method": "GET", "url_suffix": "/api/cis/tagging/category/cat-id-1"}
        assert mock_http_request.call_args_list[3].kwargs == {
            "method": "GET",
            "url_suffix": f"/api/cis/tagging/category/{category_id}",
        }

    def test_get_tag_id(self, mocker):
        """
        Given:
            - A tag name and category ID.

        When:
            - Calling get_tag_id method.

        Then:
            - Ensure the correct tag ID is returned.
        """
        tag_name = "test-tag"  # Name of tag whose ID we would like to get
        tag_id = "tag-id-2"  # Assume this is the corresponding ID
        category_id = "cat-id-123"  # Category ID we are querying by

        mock_http_request = mocker.patch.object(
            VMware.Client,
            "_http_request",
            side_effect=[
                f'"{CLIENT_SESSION_ID}"',  # INIT - Get session ID
                ["tag-id-1", tag_id],  # STEP 1 - Get list of tag IDs associated with category
                {"name": "wrong-tag", "id": "tag-id-1"},  # STEP 2 - Get tag details per ID (find match by name)
                {"name": tag_name, "id": tag_id},
            ],
        )

        client = VMware.Client(full_url=CLIENT_FULL_URL, user_name=CLIENT_USER_NAME, password=CLIENT_PASSWORD)

        assert client.get_tag_id(tag_name=tag_name, category_id=category_id) == tag_id
        # STEP 1 - Get list of tag IDs associated with category
        assert mock_http_request.call_args_list[1].kwargs == {
            "method": "POST",
            "url_suffix": "/api/cis/tagging/tag?action=list-tags-for-category",
            "json_data": {"category_id": "cat-id-123"},
        }
        # STEP 2 - Get tag details per ID (find match by name)
        assert mock_http_request.call_args_list[2].kwargs == {"method": "GET", "url_suffix": "/api/cis/tagging/tag/tag-id-1"}
        assert mock_http_request.call_args_list[3].kwargs == {"method": "GET", "url_suffix": f"/api/cis/tagging/tag/{tag_id}"}

    def test_list_associated_objects(self, mocker):
        """
        Given:
            - A tag ID.

        When:
            - Calling list_associated_objects method.

        Then:
            - Ensure the list of associated objects is returned.
        """
        tag_id = "tag-id-123"
        associated_objects = [{"id": "vm-1", "type": "VirtualMachine"}, {"id": "vm-2", "type": "VirtualMachine"}]

        mock_http_request = mocker.patch.object(
            VMware.Client, "_http_request", side_effect=[f'"{CLIENT_SESSION_ID}"', associated_objects]
        )

        client = VMware.Client(full_url=CLIENT_FULL_URL, user_name=CLIENT_USER_NAME, password=CLIENT_PASSWORD)

        assert client.list_associated_objects(tag_id=tag_id) == associated_objects
        assert mock_http_request.call_args_list[1].kwargs == {
            "method": "POST",
            "url_suffix": f"/api/cis/tagging/tag-association/{tag_id}?action=list-attached-objects",
        }

    def test_list_vms(self, mocker):
        """
        Given:
            - A list of VM IDs.

        When:
            - Calling list_vms method.

        Then:
            - Ensure the list of VMs is returned.
        """
        vm_ids = ["vm-1", "vm-2"]
        vms_list = [{"vm": vm_ids[0], "name": "VM1"}, {"vm": vm_ids[1], "name": "VM2"}]
        mock_http_request = mocker.patch.object(VMware.Client, "_http_request", side_effect=[f'"{CLIENT_SESSION_ID}"', vms_list])

        client = VMware.Client(full_url=CLIENT_FULL_URL, user_name=CLIENT_USER_NAME, password=CLIENT_PASSWORD)

        vms = client.list_vms(vm_ids=vm_ids)

        assert vms == vms_list
        assert mock_http_request.call_args_list[1].kwargs == {
            "method": "GET",
            "url_suffix": "/api/vcenter/vm",
            "params": {"vms": vm_ids},
        }


def test_list_vms_by_tag(mocker):
    """
    Given:
        - A category name and tag name.

    When:
        - Calling list_vms_by_tag function.

    Then:
        - Ensure the function returns CommandResults with correct outputs.
    """
    category_name = "Environment"
    category_id = "category-123"
    tag_name = "Production"
    tag_id = "tag-456"
    vm_ids = ["vm-1", "vm-2"]

    # Mock the Client methods
    mock_get_category_id = mocker.patch.object(VMware.Client, "get_category_id", return_value=category_id)
    mock_get_tag_id = mocker.patch.object(VMware.Client, "get_tag_id", return_value=tag_id)
    mock_list_associated_objects = mocker.patch.object(
        VMware.Client,
        "list_associated_objects",
        return_value=[
            {"id": vm_ids[0], "type": "VirtualMachine"},
            {"id": vm_ids[1], "type": "VirtualMachine"},
            {"id": "host-1", "type": "HostSystem"},
        ],
    )
    mock_list_vms = mocker.patch.object(
        VMware.Client,
        "list_vms",
        return_value=[
            {"vm": vm_ids[0], "name": "TestVM1"},
            {"vm": vm_ids[1], "name": "TestVM2"},
        ],
    )
    mocker.patch.object(VMware.Client, "_get_session_id", return_value=CLIENT_SESSION_ID)

    client = VMware.Client(full_url=CLIENT_FULL_URL, user_name=CLIENT_USER_NAME, password=CLIENT_PASSWORD)

    command_results = VMware.list_vms_by_tag(client, args={"category": category_name, "tag": tag_name})

    # Check outputs
    assert command_results.outputs_prefix == "VMwareTag"
    assert command_results.outputs_key_field == ["VM", "TagName", "Category"]
    assert command_results.outputs == [
        {"VM": "TestVM1", "TagName": tag_name, "Category": category_name},
        {"VM": "TestVM2", "TagName": tag_name, "Category": category_name},
    ]
    assert f"VMs with category: '{category_name}' and tag: '{tag_name}'" in command_results.readable_output

    # Verify method calls
    assert mock_get_category_id.call_args[0] == (category_name,)
    assert mock_get_tag_id.call_args[0] == (tag_name, category_id)
    assert mock_list_associated_objects.call_args[0] == (tag_id,)
    assert mock_list_vms.call_args[0] == (vm_ids,)