1#!/usr/local/bin/python3.8
2
3# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
4
5from __future__ import (absolute_import, division, print_function)
6__metaclass__ = type
7
8import sys
9from subprocess import Popen, PIPE
10
11import json
12
13
14class SetEncoder(json.JSONEncoder):
15    def default(self, o):
16        if isinstance(o, set):
17            return list(o)
18        return json.JSONEncoder.default(self, o)
19
20
21VBOX = "VBoxManage"
22
23
24def get_hosts(host=None):
25
26    returned = {}
27    try:
28        if host:
29            p = Popen([VBOX, 'showvminfo', host], stdout=PIPE)
30        else:
31            returned = {'all': set(), '_metadata': {}}
32            p = Popen([VBOX, 'list', '-l', 'vms'], stdout=PIPE)
33    except Exception:
34        sys.exit(1)
35
36    hostvars = {}
37    prevkey = pref_k = ''
38
39    for line in p.stdout.readlines():
40
41        try:
42            k, v = line.split(':', 1)
43        except Exception:
44            continue
45
46        if k == '':
47            continue
48
49        v = v.strip()
50        if k.startswith('Name'):
51            if v not in hostvars:
52                curname = v
53                hostvars[curname] = {}
54                try:  # try to get network info
55                    x = Popen([VBOX, 'guestproperty', 'get', curname, "/VirtualBox/GuestInfo/Net/0/V4/IP"], stdout=PIPE)
56                    ipinfo = x.stdout.read()
57                    if 'Value' in ipinfo:
58                        a, ip = ipinfo.split(':', 1)
59                        hostvars[curname]['ansible_ssh_host'] = ip.strip()
60                except Exception:
61                    pass
62
63            continue
64
65        if not host:
66            if k == 'Groups':
67                for group in v.split('/'):
68                    if group:
69                        if group not in returned:
70                            returned[group] = set()
71                        returned[group].add(curname)
72                    returned['all'].add(curname)
73                continue
74
75        pref_k = 'vbox_' + k.strip().replace(' ', '_')
76        if k.startswith(' '):
77            if prevkey not in hostvars[curname]:
78                hostvars[curname][prevkey] = {}
79            hostvars[curname][prevkey][pref_k] = v
80        else:
81            if v != '':
82                hostvars[curname][pref_k] = v
83
84        prevkey = pref_k
85
86    if not host:
87        returned['_metadata']['hostvars'] = hostvars
88    else:
89        returned = hostvars[host]
90    return returned
91
92
93if __name__ == '__main__':
94
95    inventory = {}
96    hostname = None
97
98    if len(sys.argv) > 1:
99        if sys.argv[1] == "--host":
100            hostname = sys.argv[2]
101
102    if hostname:
103        inventory = get_hosts(hostname)
104    else:
105        inventory = get_hosts()
106
107    sys.stdout.write(json.dumps(inventory, indent=2, cls=SetEncoder))
108