pyvcloud icon indicating copy to clipboard operation
pyvcloud copied to clipboard

Can't get all VMs from vApp

Open RyanW8 opened this issue 3 years ago • 3 comments

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)

RyanW8 avatar Mar 25 '21 14:03 RyanW8

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)

  • get_all_vms is looking for some attributes which are non-existent in my case : hasattr(self.resource.Children, 'Vm')
  • I am using 'resource' to set my vapp as the vdc does not return a 'href' for the vapp: currentVapp = VApp(client, resource=resource)
  • Even after VApp object initialisation, href is empty.
  • If I call the VApp reload() method I got errors like "requests.exceptions.MissingSchema: Invalid URL 'None': " which seems related to the empty href.
  • I tried to instantiate the object via 'href' instead of 'resource', and then reload() and get_all_vms() works. The problem with this is that the Vdc object does not return 'href' for vapps, just names.
  • I just found that there is a vdc method get_vapp_href() which works.
  • now I am able to properly create the VApp object and the get_all_vms() function is properly working.

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()```

dcl-fred avatar Apr 02 '21 08:04 dcl-fred

@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'))

mukultaneja avatar Apr 02 '21 08:04 mukultaneja

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

salyas0v avatar Feb 22 '22 12:02 salyas0v