Skip to content
This repository has been archived by the owner on Sep 6, 2022. It is now read-only.

Commit

Permalink
Merge pull request #18 from ARGOeu/devel
Browse files Browse the repository at this point in the history
Merge Devel to master to prepare for V0.1.5-1
  • Loading branch information
kkoumantaros authored Aug 30, 2017
2 parents 5abda9c + 44bfc3a commit 55b7ec7
Show file tree
Hide file tree
Showing 3 changed files with 115 additions and 8 deletions.
5 changes: 4 additions & 1 deletion nagios-plugins-fedcloud.spec
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

Summary: Nagios plugins for EGI FedCloud services
Name: nagios-plugins-fedcloud
Version: 0.1.4
Version: 0.1.5
Release: 1%{?dist}
License: ASL 2.0
Group: Network/Monitoring
Expand Down Expand Up @@ -39,6 +39,9 @@ rm -rf $RPM_BUILD_ROOT
%{python_sitelib}/nagios_plugins_fedcloud

%changelog
* Wed Aug 30 2017 Daniel Vrcic <dvrcic@srce.hr> - 0.1.5-1%{?dist}
- novaprobe: use of ids insteads of urls for flavors and image by Enol Fernandez
- novaprobe: added support for OIDC tokens by Enol Fernandez
* Thu Apr 6 2017 Emir Imamagic <eimamagi@srce.hr> - 0.1.4-1%{?dist}
- Version bump
* Tue Dec 13 2016 Daniel Vrcic <dvrcic@srce.hr> - 0.1.3-1%{?dist}
Expand Down
68 changes: 68 additions & 0 deletions pymodule/helpers.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import os
import sys
import re
import socket
Expand All @@ -18,6 +19,73 @@ def nagios_out(status, msg, retcode):
sys.stdout.write(status+": "+msg+"\n")
sys.exit(retcode)

def get_keystone_oidc_token(host, usertoken, capath, timeout):
if verify_cert(host, capath, timeout):
o = urlparse(host)
if o.scheme != 'https':
nagios_out('Critical', 'Connection error %s - Probe expects HTTPS endpoint' % (o.scheme+'://'+o.netloc), 2)

suffix = o.path.rstrip('/')
if suffix.endswith('v2.0') or suffix.endswith('v3'):
suffix = os.path.dirname(suffix)

try:
oidc_suffix = suffix + '/v3/OS-FEDERATION/identity_providers/egi.eu/protocols/oidc/auth'

headers, token = {}, None

headers.update({'Authorization': 'Bearer ' + usertoken})
headers.update({'accept': 'application/json'})
response = requests.post(o.scheme+'://'+o.netloc+oidc_suffix, headers=headers, timeout=timeout)
response.raise_for_status()
token = response.headers['X-Subject-Token']
except(KeyError, IndexError) as e:
nagios_out('Critical', 'Could not fetch unscoped keystone token from response: Key not found %s' % errmsg_from_excp(e), 2)
except (requests.exceptions.ConnectionError, requests.exceptions.HTTPError) as e:
nagios_out('Critical', 'Connection error %s - %s' % (o.netloc+oidc_suffix, errmsg_from_excp(e)), 2)

try:
# use unscoped token to get a list of allowed projects mapped to
# ops VO from atuh token
project_suffix = suffix + '/v3/auth/projects'

headers = {'content-type': 'application/json', 'accept': 'application/json'}
headers.update({'x-auth-token': token})
response = requests.get(o.scheme+'://'+o.netloc+project_suffix, headers=headers,
data=None, timeout=timeout)
response.raise_for_status()
projects = response.json()['projects']
project = ''
for p in projects:
if 'ops' in p['name']:
project = p['id']
break
else:
# just take one
project = projects.pop()
except(KeyError, IndexError) as e:
nagios_out('Critical', 'Could not fetch allowed projects from response: Key not found %s' % errmsg_from_excp(e), 2)
except (requests.exceptions.ConnectionError, requests.exceptions.HTTPError) as e:
nagios_out('Critical', 'Connection error %s - %s' % (o.scheme+'://'+o.netloc+project_suffix, errmsg_from_excp(e)), 2)

try:
# get scoped token for allowed project
token_suffix = suffix + '/v3/auth/tokens'
headers = {'content-type': 'application/json', 'accept': 'application/json'}
payload = {"auth": {"identity": {"methods": ["token"], "token": {"id": token}},
"scope": {"project": {"id": project["id"]}}}}
response = requests.post(o.scheme+'://'+o.netloc+token_suffix, headers=headers,
data=json.dumps(payload), verify=False, timeout=timeout)
response.raise_for_status()
token = response.headers['X-Subject-Token']
except(KeyError, IndexError) as e:
nagios_out('Critical', 'Could not fetch scoped keystone token for %s from response: Key not found %s' % (project, errmsg_from_excp(e)), 2)
except (requests.exceptions.ConnectionError, requests.exceptions.HTTPError) as e:
nagios_out('Critical', 'Connection error %s - %s' % (o.scheme+'://'+o.netloc+token_suffix, errmsg_from_excp(e)), 2)

return token, project, response


def get_keystone_token(host, userca, capath, timeout):
if verify_cert(host, capath, timeout):
o = urlparse(host)
Expand Down
50 changes: 43 additions & 7 deletions src/novaprobe.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,31 @@
strerr = ''
num_excp_expand = 0

def get_info(tenant, last_response):
def get_info_v3(tenant, last_response):
try:
tenant_id = last_response.json()['token']['project']['id']
except(KeyError, IndexError) as e:
helpers.nagios_out('Critical', 'Could not fetch id for tenant %s: Key not found %s' % (tenant, helpers.errmsg_from_excp(e)), 2)

try:
service_catalog = last_response.json()['token']['catalog']
except(KeyError, IndexError) as e:
helpers.nagios_out('Critical', 'Could not fetch service catalog: Key not found %s' % (helpers.errmsg_from_excp(e)), 2)

try:
nova_url = None
for e in service_catalog:
if e['type'] == 'compute':
for ep in e['endpoints']:
if ep['interface'] == 'public':
nova_url = ep['url']
assert nova_url is not None
except(KeyError, IndexError, AssertionError) as e:
helpers.nagios_out('Critical', 'Could not fetch nova compute service URL: Key not found %s' % (helpers.errmsg_from_excp(e)), 2)

return tenant_id, nova_url

def get_info_v2(tenant, last_response):
try:
tenant_id = last_response.json()['access']['token']['tenant']['id']
except(KeyError, IndexError) as e:
Expand Down Expand Up @@ -64,29 +88,41 @@ class ArgHolder(object):
parser.add_argument('--flavor', dest='flavor', nargs='?')
parser.add_argument('--image', dest='image', nargs='?')
parser.add_argument('--cert', dest='cert', nargs='?')
parser.add_argument('--access-token', dest='access_token', nargs='?')
parser.add_argument('-t', dest='timeout', type=int, nargs='?', default=120)
parser.add_argument('--capath', dest='capath', nargs='?', default='/etc/grid-security/certificates')

parser.parse_args(namespace=argholder)

for arg in ['endpoint', 'cert', 'capath', 'timeout']:
for arg in ['endpoint', 'capath', 'timeout']:
if eval('argholder.'+arg) == None:
argnotspec.append(arg)

if argholder.cert is None and argholder.access_token is None:
helpers.nagios_out('Unknown', 'cert or access-token command-line arguments not specified', 3)

if argholder.cert and argholder.access_token:
helpers.nagios_out('Unknown', 'both cert and accesstoken command-line arguments specified', 3)

if len(argnotspec) > 0:
msg_error_args = ''
for arg in argnotspec:
msg_error_args += '%s ' % (arg)
helpers.nagios_out('Unknown', 'command-line arguments not specified, '+msg_error_args, 3)
else:
if not argholder.endpoint.startswith("http") \
or not os.path.isfile(argholder.cert) \
or not type(argholder.timeout) == int \
or not os.path.isdir(argholder.capath):
helpers.nagios_out('Unknown', 'command-line arguments are not correct', 3)
if argholder.cert and not os.path.isfile(argholder.cert):
helpers.nagios_out('Unknown', 'command-line arguments are not correct', 3)

ks_token, tenant, last_response = helpers.get_keystone_token(argholder.endpoint, argholder.cert, argholder.capath, argholder.timeout)
tenant_id, nova_url = get_info(tenant, last_response)
if argholder.cert:
ks_token, tenant, last_response = helpers.get_keystone_token(argholder.endpoint, argholder.cert, argholder.capath, argholder.timeout)
tenant_id, nova_url = get_info_v2(tenant, last_response)
else:
ks_token, tenant, last_response = helpers.get_keystone_oidc_token(argholder.endpoint, argholder.access_token, argholder.capath, argholder.timeout)
tenant_id, nova_url = get_info_v3(tenant, last_response)

# remove once endpoints properly expose images openstackish way
if not argholder.image:
Expand Down Expand Up @@ -141,8 +177,8 @@ class ArgHolder(object):
headers = {'content-type': 'application/json', 'accept': 'application/json'}
headers.update({'x-auth-token': ks_token})
payload = {'server': {'name': SERVER_NAME,
'imageRef': nova_url + '/images/%s' % (image),
'flavorRef': nova_url + '/flavors/%s'% (flavor_id)}}
'imageRef': image,
'flavorRef': flavor_id}}
response = requests.post(nova_url + '/servers', headers=headers,
data=json.dumps(payload),
cert=argholder.cert, verify=False,
Expand Down

0 comments on commit 55b7ec7

Please sign in to comment.