vmware / vsphere-automation-sdk-python

Python samples, language bindings, and API reference documentation for vSphere, VMC, and NSX-T using the VMware REST API
MIT License
746 stars 313 forks source link

Python SDK 8.0 taking more time to listing VMs w.r.t perl SDK version < 8.0 #365

Closed dkbiswas closed 1 year ago

dkbiswas commented 1 year ago

Describe the bug

` [root@$ samples]# cat getallvms2.py

!/usr/bin/env python

VMware vSphere Python SDK

Copyright (c) 2008-2021 VMware, Inc. All Rights Reserved.

#

Licensed under the Apache License, Version 2.0 (the "License");

you may not use this file except in compliance with the License.

You may obtain a copy of the License at

#

http://www.apache.org/licenses/LICENSE-2.0

#

Unless required by applicable law or agreed to in writing, software

distributed under the License is distributed on an "AS IS" BASIS,

WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

See the License for the specific language governing permissions and

limitations under the License.

""" Python program for listing the VMs on an ESX / vCenter host """

import re from pyVmomi import vmodl, vim from tools import cli, service_instance

def print_vm_info(virtual_machine): """ Print information for a particular virtual machine or recurse into a folder with depth protection """ vm_config = {} summary = virtual_machine.summary host_ref = virtual_machine.runtime.host if not host_ref: print("Can't find host ref") accessibility = summary.runtime.connectionState extra_config = virtual_machine.config.extraConfig vname = summary.config.name

uuid = summary.config.uuid
if uuid:
    vm_config.update({ "uuid": uuid })

iuuid = summary.config.instanceUuid
if iuuid:
    vm_config.update({ "instanceUuid": iuuid })

cversion  = virtual_machine.config.version
if cversion is not None:
    vm_config.update({ "version": cversion })

change_tracking_enable = virtual_machine.config.changeTrackingEnabled
if change_tracking_enable is not None:
    vm_config.update({ "changeTrackingEnabled": "1" if change_tracking_enable else "0" })

change_tracking_support = virtual_machine.capability.changeTrackingSupported
if change_tracking_support is not None: 
    vm_config.update({ "changeTrackingSupported": "1" if change_tracking_support else "0"})

ctemplate = summary.config.template
if ctemplate:
    vm_config.update({ "template": "1" if ctemplate else "0" })

gfullname = summary.config.guestFullName
if gfullname:
    vm_config.update({"guestFullName": gfullname})

devs = virtual_machine.config.hardware.device
extra_config = virtual_machine.config.extraConfig
if extra_config: 
    config_name = virtual_machine.config.name
    for entry in extra_config:
        if entry.key == 'unitrends.vm.type':
            if entry.value in ['instant_recovery_audit', 'replica_vm', 'virtual_appliance']:
                debug_message("Skipping VM  %s since .it was created for VMware IR." % config_name)
                exclude_vm_from_inventory = 1
                break

print("Name       : ", summary.config.name)
print("Template   : ", summary.config.template)
print("Path       : ", summary.config.vmPathName)
print("Guest      : ", summary.config.guestFullName)
print("Instance UUID : ", summary.config.instanceUuid)
print("Bios UUID     : ", summary.config.uuid)
annotation = summary.config.annotation
if annotation:
    print("Annotation : ", annotation)
print("State      : ", summary.runtime.powerState)
if summary.guest is not None:
    ip_address = summary.guest.ipAddress
    tools_version = summary.guest.toolsStatus
    if tools_version is not None:
        print("VMware-tools: ", tools_version)
    else:
        print("Vmware-tools: None")
    if ip_address:
        print("IP         : ", ip_address)
    else:
        print("IP         : None")
if summary.runtime.question is not None:
    print("Question  : ", summary.runtime.question.text)
print("")

def main(): """ Simple command-line program for listing the virtual machines on a system. """

parser = cli.Parser()
parser.add_custom_argument('-f', '--find', required=False,
                           action='store', help='String to match VM names')
args = parser.get_args()
si = service_instance.connect(args)

try:
    content = si.RetrieveContent()

    container = content.rootFolder  # starting point to look into
    view_type = [vim.VirtualMachine]  # object types to look for
    recursive = True  # whether we should look into it recursively
    container_view = content.viewManager.CreateContainerView(
        container, view_type, recursive)

    children = container_view.view
    if args.find is not None:
        pat = re.compile(args.find, re.IGNORECASE)
    for child in children:
        if args.find is None:
            print_vm_info(child)
        else:
            if pat.search(child.summary.config.name) is not None:
                print_vm_info(child)

except vmodl.MethodFault as error:
    print("Caught vmodl fault : " + error.msg)
    return -1

return 0

Start program

if name == "main": main()

Time is taken by the above python script to list VMs with required attributes. ` real 0m4.137s user 0m3.021s sys 0m0.074s

If similar perl prog takin near ~1 mili sec. Can someone suggest, how to improve the above python script running time to nearly or equivalent to Perl.

Reproduction steps

  1. run above script with time command. you need to install vsphere python sdk vsphere 8.0.
  2. ...

Expected behavior

expected to run near about ~1 mili sec.

Additional context

No response

dkbiswas commented 1 year ago

cProfile: 1846819 function calls (1836595 primitive calls) in 1.702 seconds

Ordered by: internal time

ncalls tottime percall cumtime percall filename:lineno(function) 262 0.337 0.001 0.337 0.001 {method 'read' of '_ssl._SSLSocket' objects} 36539 0.149 0.000 0.472 0.000 SoapAdapter.py:660(StartElementHandler) 36539 0.128 0.000 0.361 0.000 SoapAdapter.py:721(EndElementHandler) 129 0.119 0.001 0.976 0.008 {method 'ParseFile' of 'pyexpat.xmlparser' objects} 104346 0.071 0.000 0.071 0.000 VmomiSupport.py:461(GetPropertyInfo) 8815 0.070 0.000 0.166 0.000 VmomiSupport.py:624(init) 72738 0.051 0.000 0.074 0.000 SoapAdapter.py:636(SplitTag) 32359/31862 0.049 0.000 0.074 0.000 VmomiSupport.py:1034(CheckField) 326816 0.047 0.000 0.047 0.000 {built-in method builtins.isinstance} 25 0.035 0.001 0.035 0.001 {built-in method _imp.create_dynamic} 289917 0.031 0.000 0.031 0.000 {built-in method builtins.issubclass} 31608 0.031 0.000 0.121 0.000 VmomiSupport.py:662(setattr) 9311 0.028 0.000 0.065 0.000 VmomiSupport.py:649(_GetPropertyList) 20975 0.027 0.000 0.036 0.000 VmomiSupport.py:656() 78240 0.025 0.000 0.025 0.000 {method 'find' of 'str' objects} 42345/41111 0.024 0.000 0.086 0.000 {built-in method builtins.hasattr}

dkbiswas commented 1 year ago

declaring vm properties : vm_properties = ["name", "config.name", "summary.runtime.connectionState", "config.uuid", "summary.config.name", "config.instanceUuid", "config.changeTrackingEnabled", "capability.changeTrackingSupported", "config.guestFullName", "config.version", "config.ftInfo", "config.template", "datastore", "resourcePool", "runtime.host"] """ vm_properties.append(["config.hardware.device", "config.extraConfig"]) """ vm_properties = ["config.template"]

parser = cli.Parser() args = parser.get_args() si = service_instance.connect(args) atexit.register(endit)

root_folder = si.content.rootFolder view = pchelper.get_container_view(si, obj_type=[vim.VirtualMachine]) vm_data = pchelper.collect_properties(si, view_ref=view, obj_type=vim.VirtualMachine, path_set=vm_properties, include_mors=True) would make faster to get vm information.