Skip to content

Commit

Permalink
Merge pull request #3 from infrasonar/dev
Browse files Browse the repository at this point in the history
Implement VMware guests creation
  • Loading branch information
joente authored Sep 6, 2023
2 parents 6b16288 + 759f0d7 commit 74e34f5
Show file tree
Hide file tree
Showing 3 changed files with 223 additions and 2 deletions.
24 changes: 24 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,15 @@ Or, it will be asked in a prompt when starting the script.
> :point_right: Note that a **token** with **Agent** flags must be used for the _apply-assets_ action to work. A **container token** is required when no _container Id_ is given or when one or more assets without an _asset Id_ are used.
## Get asset
Get a single asset. _(in the example below, 123 is a asset Id)_
```bash
infrasonar get-asset 123 -o yaml
```

## Get assets

Get container assets. _(in the example below, 123 is a container Id)_
Expand All @@ -72,10 +81,25 @@ infrasonar get-assets 123 -o yaml
```


## VMware guests

Generate YAML (or JSON) with VMware Guests which are found on ESX or vCenter but wherefore no asset with the `vmwareguest` collector is found. This YAML can then be used to install the VMware Guest collector with a single command.

Example: _(in the example below, 123 is a container Id)_

```bash
infrasonar vmware-guests 123 > missing.yaml
infrasonar apply-assets missing.yaml -a -d
```

> :point_right: Do not forget to use **-a** to prevent removing other collectors and use **-d** to perform a dry-run for verifying the changes.
## Help

```
infrasonar -h
infrasonar get-asset -h
infrasonar get-assets -h
infrasonar apply-assets -h
infrasonar vmware-guests -h
```
199 changes: 198 additions & 1 deletion bin/infrasonar
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ from dataclasses import dataclass
from setproctitle import setproctitle
from typing import Any, Optional, Dict, List, Tuple

__version__ = '0.1.10' # Update version in setup as well
__version__ = '0.1.11' # Update version in setup as well


_labels_example = """
Expand Down Expand Up @@ -1007,6 +1007,166 @@ def get_asset(asset_id: int, api: str, verify_ssl: bool, output: str,
Dumper=yamlloader.ordereddict.CDumper)


async def async_get_check_data(api: str, verify_ssl: bool, asset_id: int,
token: str, collector: str):
url = _join(api, f'asset/{asset_id}/collector/{collector}/check/hostVMs')
async with ClientSession(headers=_headers(token)) as session:
async with session.get(url, ssl=verify_ssl) as r:
if r.status != 200:
msg = await r.text()
raise Exception(f'{msg} (error code: {r.status})')
resp = await r.json()

return resp


def vmware_guests(container_id: int, api: str, verify_ssl: bool, output: str,
token: Optional[str], collector: str,
include: Optional[List[int]]):
if token is None:
try:
token = getpass.getpass('Enter user or container token: ')
except KeyboardInterrupt:
sys.exit('Cancelled')

try:
assets = asyncio.run(aget_assets(
api=api,
token=token,
container_id=container_id,
verify_ssl=verify_ssl,
fields=set(['id', 'name', 'collectors']),
kind=None,
not_kind=None,
mode='normal',
not_mode=None,
collector=collector,
not_collector=None,
label=None,
not_label=None))
except KeyboardInterrupt:
sys.exit('Cancelled')
except Exception as e:
msg = str(e) or type(e).__name__
sys.exit(msg)

if not assets:
sys.exit('No assets with the {collector} collector found')

asyncio.run(asyncio.sleep(0.5))

guest_map = {}
for asset in assets:
if include and asset['id'] not in include:
continue
address = next((
x for x in asset['collectors']
if x['key'] == collector
))['config'].get('address', '') or asset['name']

data = asyncio.run(async_get_check_data(api, verify_ssl, asset['id'],
token, collector))
for guest in data['data']['guests']:
guest['_parent'] = address
guest_map[guest['name']] = guest # name=instanceUuid

asyncio.run(asyncio.sleep(0.5))

try:
installed = asyncio.run(aget_assets(
api=api,
token=token,
container_id=container_id,
verify_ssl=verify_ssl,
fields=set(['id', 'collectors']),
kind=None,
not_kind=None,
mode=None,
not_mode=None,
collector='vmwareguest',
not_collector=None,
label=None,
not_label=None))
except KeyboardInterrupt:
sys.exit('Cancelled')
except Exception as e:
msg = str(e) or type(e).__name__
sys.exit(msg)

asyncio.run(asyncio.sleep(0.5))

try:
not_installed = asyncio.run(aget_assets(
api=api,
token=token,
container_id=container_id,
verify_ssl=verify_ssl,
fields=set(['id', 'name']),
kind=None,
not_kind=None,
mode=None,
not_mode=None,
collector=None,
not_collector='vmwareguest',
label=None,
not_label=None))
except KeyboardInterrupt:
sys.exit('Cancelled')
except Exception as e:
msg = str(e) or type(e).__name__
sys.exit(msg)

not_installed = {a['name']: a['id'] for a in not_installed}
total = len(guest_map)

for asset in installed:
instance_uuid = next((
x for x in asset['collectors']
if x['key'] == 'vmwareguest'))['config']['instance_uuid']
guest_map.pop(instance_uuid, None)

if not guest_map:
print('No missing guests are found '
f'(installed guests: {total})')
sys.exit(0)

assets = []
for guest in guest_map.values():
asset = OrderedDict()
name = guest['instanceName']

if name in not_installed:
asset['id'] = not_installed[name]

asset['name'] = name
asset['collectors'] = [{
'key': 'vmwareguest',
'config': {
'hypervisor': guest['_parent'],
'instance_uuid': guest['name'],
},
}]
assets.append(asset)

data = OrderedDict()
data['container'] = container_id
data['assets'] = assets

if output == 'json':
json.dump(data, sys.stdout)
elif output == 'yaml':
yaml.dump(data, sys.stdout,
Dumper=yamlloader.ordereddict.CDumper)

print("""
# !! IMPORTANT !!
# * Make sure to use -a when applying the YAML to prevent
# removing existing collectors.
# * Be sure to simulate and verify the changes
# using a dry-run with the -d argument
""")


if __name__ == '__main__':
setproctitle('infrasonar')

Expand Down Expand Up @@ -1128,6 +1288,33 @@ if __name__ == '__main__':
default=None,
help='Token for authentication')

action_vmware_guests = \
action.add_parser(
'vmware-guests',
help='Output YAML for missing guests')

action_vmware_guests.add_argument('containerId', type=int)

action_vmware_guests.add_argument('-o', '--output',
choices=['json', 'yaml'],
default='yaml')
action_vmware_guests.add_argument('-c', '--collector',
choices=['vcenter', 'esx'],
default='vcenter',
help=(
'Use either vCenter or ESX for '
'getting the guests list'))
action_vmware_guests.add_argument('-i', '--include',
metavar='N', type=int, nargs='+',
help=(
'Include only (vCenter or ESX) '
'assets for the lookup. If this list '
'remains empty, all vCenter or ESX '
'assets will be used'
))
action_vmware_guests.add_argument('--token',
default=None,
help='Token for authentication')
args = parser.parse_args()

if args.version:
Expand Down Expand Up @@ -1170,5 +1357,15 @@ if __name__ == '__main__':
args.token,
args.field,
args.include_defaults)
elif args.action == 'vmware-guests':
vmware_guests(
args.containerId,
args.api,
not args.skip_verify_ssl,
args.output,
args.token,
args.collector,
args.include or None,
)
else:
parser.print_help()
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

setup(
name='infrasonar',
version='0.1.10', # Update version in infrasonar as well
version='0.1.11', # Update version in infrasonar as well
description='InfraSonar Toolkit',
url='https://github.com/infrasonar/toolkit',
long_description=long_description,
Expand Down

0 comments on commit 74e34f5

Please sign in to comment.