Skip to content

Instantly share code, notes, and snippets.

@larsks
Created August 16, 2021 13:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save larsks/8aeed8f092980e56f264705a050d6e81 to your computer and use it in GitHub Desktop.
Save larsks/8aeed8f092980e56f264705a050d6e81 to your computer and use it in GitHub Desktop.
#!/usr/bin/python3
import click
import json
import logging
import requests
import subprocess
LOG = logging.getLogger(__name__)
class AssistedInstallerAPI:
baseUrl = 'https://api.openshift.com/api/assisted-install/v1'
def __init__(self, offlinetoken):
self.offlinetoken = offlinetoken.strip()
self.session = requests.Session()
def get_access_token(self):
if not self.offlinetoken:
raise ValueError(self.offlinetoken)
data = {
'client_id': 'cloud-services',
'grant_type': 'refresh_token',
'refresh_token': self.offlinetoken,
}
res = self.session.post(
'https://sso.redhat.com/auth/realms/redhat-external/protocol/openid-connect/token',
data=data,
)
res.raise_for_status()
self.session.headers['Authorization'] = 'Bearer {}'.format(res.json()['access_token'])
def list_clusters(self):
res = self.session.get(f'{self.baseUrl}/clusters')
res.raise_for_status()
return res.json()
def get_cluster(self, cluster_id):
res = self.session.get(f'{self.baseUrl}/clusters/{cluster_id}')
res.raise_for_status()
return res.json()
def set_hostnames(self, cluster_id, hostnames):
res = self.session.patch(f'{self.baseUrl}/clusters/{cluster_id}',
json={'hosts_names': hostnames})
res.raise_for_status()
def get_hosts_from_ansible(wantgroup):
raw = subprocess.check_output(
'ansible-inventory --list --export', shell=True)
inventory = json.loads(raw)
groups = []
hosts = {}
groups.append(wantgroup)
while len(groups) > 0:
group = groups.pop()
members = inventory[group]
if 'children' in members:
groups.extend(members['children'])
if 'hosts' in members:
for host in members['hosts']:
hosts[host] = inventory['_meta']['hostvars'][host]
return hosts
def hosts_by_hostvar(varname, hosts):
hostmap = {}
for host, hostvars in hosts.items():
try:
hostmap[hostvars[varname]] = host
except KeyError:
LOG.warning('host %s has no %s', host, varname)
return hostmap
@click.command()
@click.option('--offline-token', '-t', envvar='OAI_OFFLINE_TOKEN',
type=click.File(mode='r'))
@click.option('--verbose', '-v', count=True)
@click.argument('ansible_group_name')
@click.argument('cluster_name_or_id')
def main(offline_token, verbose,
ansible_group_name, cluster_name_or_id):
if verbose == 0:
loglevel = 'WARNING'
elif verbose == 1:
loglevel = 'INFO'
else:
loglevel = 'DEBUG'
logging.basicConfig(level=loglevel)
ansible_hosts = get_hosts_from_ansible(ansible_group_name)
ansible_hosts_by_bmc = hosts_by_hostvar('ipmi_host', ansible_hosts)
with offline_token:
api = AssistedInstallerAPI(offlinetoken=offline_token.read())
try:
api.get_access_token()
clusters = api.list_clusters()
for cluster in clusters:
if cluster_name_or_id in [cluster['name'], cluster['id']]:
selected = cluster
break
else:
raise KeyError(cluster_name_or_id)
print('found cluster', selected['name'])
cluster_detail = api.get_cluster(selected['id'])
hostnames = []
for host in cluster_detail['hosts']:
inventory = json.loads(host['inventory'])
bmc_address = inventory['bmc_address']
match = ansible_hosts_by_bmc[bmc_address]
LOG.info('found host name %s for host id %s', match, host['id'])
hostnames.append({
'id': host['id'],
'hostname': match,
})
api.set_hostnames(cluster['id'], hostnames)
except requests.exceptions.HTTPError as err:
raise click.ClickException(err.response.text)
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment