vmware-archive / pyvcloud

Python SDK for VMware vCloud Director
https://vmware.github.io/pyvcloud
Other
170 stars 189 forks source link

Can't get all VMs from vApp #757

Open RyanW8 opened 3 years ago

RyanW8 commented 3 years ago

With the following methods:

from pyvcloud.vcd.client import BasicLoginCredentials, Client, EntityType
from pyvcloud.vcd.org import Org
from pyvcloud.vcd.vapp import VApp
from pyvcloud.vcd.vm import VM
from pyvcloud.vcd.vdc import VDC
from typing import List
import requests

requests.packages.urllib3.disable_warnings()

class VCDCollector:

    def __init__(self, url, username, password, org):
        self.url = url
        self.username = username
        self.password = password
        self.org = org
        self.client = Client(
            self.url,
            verify_ssl_certs=False,
            log_file=f'logs/vcd_{org}.log',
        )
        self.client.set_highest_supported_version()
        self.client.set_credentials(BasicLoginCredentials(
            self.username,
            self.org,
            self.password
        ))
        self.vcd_org = Org(self.client, resource=self.client.get_org())

    def get_vdcs(self) -> List[VDC]:
        return [VDC(self.client, resource=self.vcd_org.get_vdc(vdc['name'])) for vdc in self.vcd_org.list_vdcs()]

    def get_vapps(self, vdc: VDC) -> List[VApp]:
        vapps = vdc.list_resources(EntityType.VAPP)
        vcd_vapps = []
        for vapp in vapps:
            vcd_vapps.append(
                VApp(client=self.client,
                     resource=vdc.get_vapp(name=vapp['name']))
            )
        return vcd_vapps

    def get_vms_from_vapp(self, vapp: VApp) -> List[VM]:
        print(vapp.get_all_vms())

The get_vms_from_vapp method doesn't print anything.

This is my code used to call the above methods:

vcd_col = VCDCollector(url="vcd_url", username='test', password='test', org='test')
for vdc in vcd_col.get_vdcs():
  vapps = vcd_col.get_vapps(vdc=vdc)
  for vapp in vapps:
    vms = vcd_col.get_vms_from_vapp(vapp=vapp)
dcl-fred commented 3 years ago

Hi,

I have the same issue. I'm not trying to do fancy things: just retrieve a list of Virtual Machines in a first time. Is there a known pyvcloud version where this is not broken? (Vapp object creation via resource instead of href)

Additionally here is a little debug I have done. (edit : I was not expecting to find a way to make this work)

Here is my quick&dirty testing code which now works:


# Pyvcloud Examples
#
# Copyright (c) 2018 VMware, Inc. All Rights Reserved.
#
# This product is licensed to you under the
# Apache License, Version 2.0 (the "License").
# You may not use this product except in compliance with the License.
#
# This product may include a number of subcomponents with
# separate copyright notices and license terms. Your use of the source
# code for the these subcomponents is subject to the terms and
# conditions of the subcomponent's license, as noted in the LICENSE file.
#
# Illustrates how to list resources associated with org VDCs.

import sys
from pyvcloud.vcd.client import BasicLoginCredentials
from pyvcloud.vcd.client import Client
from pyvcloud.vcd.org import Org
from pyvcloud.vcd.vdc import VDC
from pyvcloud.vcd.vapp import VApp
from pyvcloud.vcd.vm import VM
import requests

host = "https://yourvcloud.tld"
user = "adminOrAnotherUser"
password = "yourPassword"
org = "system"  # If you want to login as a cloud provider

# Disable warnings from self-signed certificates.
requests.packages.urllib3.disable_warnings()

# Login. SSL certificate verification is turned off to allow self-signed
# certificates.  You should only do this in trusted environments.
print("Logging in: host={0}, org={1}, user={2}".format(host, org, user))
client = Client(host, verify_ssl_certs=False)
client.set_highest_supported_version()
client.set_credentials(BasicLoginCredentials(user, org, password))
orgs = client.get_org_list()
for org in orgs:
    orgObject = Org(client, href=org.attrib["href"])
    orgName = org.attrib["name"]
    for vdc_info in orgObject.list_vdcs():
        vdcName = vdc_info['name']
        vdcHref = vdc_info['href']
        vdc = VDC(client, href=vdcHref)
        for resource in vdc.list_resources():
            if resource["type"] == "application/vnd.vmware.vcloud.vApp+xml":
                currentVappHref = vdc.get_vapp_href(resource["name"])
                currentVapp = VApp(client, href=currentVappHref)
                vmList = currentVapp.get_all_vms()
                for vmElement in vmList:
                    vmName = vmElement.attrib["name"]
                    # vm = VM(client, resource=vmElement)  # no needed in my case 
                    print(f"{orgName=} {vdcName=} {vmName=}")  # Python >= 3.8

# Log out.
print("Logging out")
client.logout()```
mukultaneja commented 3 years ago

@RyanW8, get_all_vms() returns a list of lxml.objectify.ObjectifiedElement. You need to get inside the object to fetch values. Below is the pythonic way which I believe should work for you,

for vm in vapp.get_all_vms():
    print(vm.get('name'))
salyas0v commented 2 years ago

As suggested by @mukultaneja , I'm able to get VMS ! Hence, the question can be closed