2

I'm querying an API using an example script I've made a few changes to from their documentation. The function I'm using looks like this

def info(vm, depth=1):

    if hasattr(vm,'childEntity'):
        if depth > MAX_DEPTH:
            return
        vms = vm.childEntity
        for child in vms:
            info(child, depth+1)
        return

    summary = vm.summary
    hardware = vm.config.hardware.device

    macs = []

    print("Name            : {}".format(summary.config.name))
    print("No of vCPUs     : {}".format(summary.config.numCpu))
    print("Memory (Mb)     : {}".format(summary.config.memorySizeMB))
    print("IP Address      : {}".format(summary.guest.ipAddress))
    for hw in hardware:
        if hasattr(hw, 'macAddress'):
            macs.append(hw.macAddress)
    print("MAC Addresses   :{}".format(mac_addresses))

def main():
    si = None

    host = creds.host
    user = creds.user
    password = creds.password

    try:
        si = SmartConnectNoSSL(host=host,
                               user=user,
                               pwd=password)
        atexit.register(Disconnect, si)
    except vim.fault.InvalidLogin:
        raise SystemExit("Unable to connect to host "
                         "with supplied credentials.")

    content = si.RetrieveContent()
    for child in content.rootFolder.childEntity:
        if hasattr(child, 'vmFolder'):
            datacenter = child
            vmfolder = datacenter.vmFolder
            vmlist = vmfolder.childEntity

            for vm in vmlist:
                printvminfo(vm)

if __name__ == "__main__":
    main()

This will print out something like this

Name            : vm1
No of vCPUs     : 2
Memory (Mb)     : 10000
IP Address      : 127.0.0.1
MAC Addresses   :['00:01:22:33:4a:b5']

Name            : vm2
No of vCPUs     : 2
Memory (Mb)     : 10000
IP Address      : 127.0.0.2
MAC Addresses   :['00:01:12:33:4g:b9', '40:51:21:38:4t:b5', '00:01:88:55:6y:z1']

Name            : vm3
No of vCPUs     : 2
Memory (Mb)     : 10000
IP Address      : 127.0.0.3
MAC Addresses   :['00:50:56:83:d0:10']

I'm trying to create a dictionary of the entire output with

test['name'] = summary.config.name
test['vCPU'] = summary.config.numCpu
test['memory'] = summary.config.memorySizeMB
test['IP'] = summary.guest.ipAddress
test['mac'] = mac_addresses
print(test)

But keep overwriting the dictionary so only one vm entry will print at a time rather than the entire output, so my output currently is

{'vCPU': 2, 'IP': '127.0.0.1', 'mac': ['00:01:22:33:4a:b5'], 'name': 'vm1', 'memory': 10000}
{'vCPU': 2, 'IP': '127.0.0.2', 'mac': ['00:01:12:33:4g:b9', '40:51:21:38:4t:b5', '00:01:88:55:6y:z1'], 'name': 'vm2', 'memory': 10000}
{'vCPU': 2, 'IP': '127.0.0.3', 'mac': ['00:50:56:83:d0:10'], 'name': 'vm3', 'memory': 10000}

Whereas I would like

{
 {
 'vCPU': 2,
 'IP': '127.0.0.1',
 'mac': ['00:01:22:33:4a:b5'],
 'name': 'vm1', 
 'memory': 10000 
 }, 
 {
 'vCPU': 2, 
 'IP': '127.0.0.2', 
 'mac': ['00:01:12:33:4g:b9', '40:51:21:38:4t:b5', '00:01:88:55:6y:z1'], 
 'name': 'vm2',
 'memory': 10000
 }
 {
 'vCPU': 2,
 'IP': '127.0.0.3',
 'mac': ['00:50:56:83:d0:10'],
 'name': 'vm3',
 'memory': 10000
 }
}

Is there a more efficient function/loop I could be using?

1
  • Make it a list of dictionaries? Commented Mar 2, 2018 at 15:00

2 Answers 2

1

Here is an idea, utilizing a class to hold the properties of the Virtual Machine and you can simply override the __str__ definition of the class so you can output whatever you'd like when you print the class.

Keep in mind, I couldn't test this because I don't know which API you are using and you didn't post the full code set; so this may be a bit buggy. Somewhere you must be creating a loop that calls def info() multiple times, and I don't see that here.

Essentially, before the loop that calls def info() multiple times, you need to create an empty list/dict to hold all the virtual machine objects you are going to create in this process.

class VirtualMachine :
    def __init__ (self, name, numCpu, mem, ip, mac):

        self.name = name
        self.vCPU = numCpu
        self.memory = mem
        self.IP = ip
        self.mac = mac

    def __str__ (self):
        return """Name            : {} \n
                  No of vCPUs     : {} \n
                  Memory (Mb)     : {} \n
                  IP Address      : {} \n
                  MAC Addresses   : {}
               """.format(self.name, self.vCPU, self.memory, self.IP, self.mac)


def info(vm, depth=1):

    if hasattr(vm,'childEntity'):
        if depth > MAX_DEPTH:
            return
        vms = vm.childEntity
        for child in vms:
            info(child, depth+1)
        return

    summary = vm.summary
    hardware = vm.config.hardware.device

    macs = []
    for hw in hardware:
        if hasattr(hw, 'macAddress'):
            macs.append(hw.macAddress)

    v = VirtualMachine(summary.config.name, summary.config.numCPU, summary.config.memorySizeMB, summary.guest.ipAddress, mac_addresses)

    # Here you should append `v` to some other dictionary that you defined before you entered the loop calling `info(vm, depth)`.
    # Then you will have a full dictionary of all virtual machines you found in the API call loop.

    print( v ) 
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for the reply, I'll have a go at implementing it. I've added the rest of the code and am using the VMware API
0

Turned out to be incredibly simple and I just needed a break from looking at it. Just needed to initiate a list out of the class and a dict in the class, append the dict to the list in the loop and print it from another class as to not print each iteration.

test_list = []

def printvminfo(vm, depth=1):
    if hasattr(vm,'childEntity'):
    if depth > MAX_DEPTH:
        return
    vms = vm.childEntity
    for child in vms:
        info(child, depth+1)
    return

summary = vm.summary
hardware = vm.config.hardware.device

macs = []
test = {}

test['name'] = summary.config.name
test['vCPU'] = summary.config.numCpu
test['memory'] = summary.config.memorySizeMB
test['IP'] = summary.guest.ipAddress
for d in hardware:
    if hasattr(d, 'macAddress'):
        mac_addresses.append(d.macAddress)
test['mac'] = mac_addresses


test_list.append(test)

def get_list():
    print(test_list)

Now running

python script.py > file.txt

outputs a file with an iterable data structure.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.