Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
S
synnefo
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Incidents
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
itminedu
synnefo
Commits
fcc0cf60
Commit
fcc0cf60
authored
Feb 28, 2013
by
Ilias Tsitsimpis
Committed by
Christos Stavrakakis
Mar 12, 2013
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Create AstakosClient Class
parent
9b81d874
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
156 additions
and
123 deletions
+156
-123
snf-astakos-client/astakosclient/__init__.py
snf-astakos-client/astakosclient/__init__.py
+156
-123
No files found.
snf-astakos-client/astakosclient/__init__.py
View file @
fcc0cf60
...
...
@@ -39,11 +39,144 @@ import simplejson
import
objpool.http
logger
=
logging
.
getLogger
(
__name__
)
# --------------------------------------------------------------------
# Astakos Client Exception
class
AstakosClientException
(
Exception
):
def
__init__
(
self
,
message
,
status
=
0
):
self
.
message
=
message
self
.
status
=
status
def
__str__
(
self
):
return
repr
(
self
.
message
)
# --------------------------------------------------------------------
# Astakos client API
# Astakos Client Class
class
AstakosClient
():
"""AstakosClient Class Implementation"""
# ----------------------------------
def
__init__
(
self
,
token
,
astakos_url
,
use_pool
=
False
,
logger
=
None
):
"""Intialize AstakosClient Class
Keyword arguments:
token -- user's token (string)
astakos_url -- i.e https://accounts.example.com (string)
use_pool -- use objpool for http requests (boolean)
logger -- pass a different logger
"""
if
logger
is
None
:
logger
=
logging
.
getLogger
(
"astakosclient"
)
logger
.
debug
(
"Intialize AstakosClient: astakos_url = %s"
"use_pool = %s"
%
(
astakos_url
,
use_pool
))
# Check Input
if
not
token
:
m
=
"Token not given"
logger
.
error
(
m
)
raise
ValueError
(
m
)
if
not
astakos_url
:
m
=
"Astakos url not given"
logger
.
error
(
m
)
raise
ValueError
(
m
)
# Check for supported scheme
p
=
urlparse
.
urlparse
(
astakos_url
)
conn
=
_scheme_to_class
(
p
.
scheme
,
use_pool
)
if
conn
is
None
:
m
=
"Unsupported scheme: %s"
%
p
.
scheme
logger
.
error
(
m
)
raise
ValueError
(
m
)
# Save token and url
self
.
logger
=
logger
self
.
token
=
token
self
.
netloc
=
p
.
netloc
self
.
scheme
=
p
.
scheme
self
.
conn
=
conn
# ----------------------------------
def
_callAstakos
(
self
,
request_path
,
headers
=
{},
body
=
{},
method
=
"GET"
):
"""Make the actual call to Astakos Service"""
self
.
logger
.
debug
(
"Make a %s request to %s with headers %s "
"and body %s"
%
(
method
,
request_path
,
headers
,
body
))
# Build request's header and body
kwargs
=
{}
kwargs
[
'headers'
]
=
headers
kwargs
[
'headers'
][
'X-Auth-Token'
]
=
self
.
token
if
body
:
kwargs
[
'body'
]
=
body
kwargs
[
'headers'
].
setdefault
(
'content-type'
,
'application/octet-stream'
)
kwargs
[
'headers'
].
setdefault
(
'content-length'
,
len
(
body
)
if
body
else
0
)
# Get the connection object
conn
=
self
.
conn
(
self
.
netloc
)
# Send request
try
:
(
data
,
status
)
=
_doRequest
(
conn
,
method
,
request_path
,
**
kwargs
)
except
Exception
as
err
:
self
.
logger
.
error
(
"Failed to send request: %s"
%
err
)
raise
AstakosClientException
(
str
(
err
))
finally
:
conn
.
close
()
# Return
self
.
logger
.
debug
(
"Request returned with status %s"
%
status
)
if
status
<
200
or
status
>=
300
:
raise
AstakosClientException
(
data
,
status
)
return
simplejson
.
loads
(
unicode
(
data
))
# ------------------------
def
authenticate
(
self
,
usage
=
False
):
"""Check if user is authenticated Astakos user
Keyword arguments:
usage -- return usage information for user (boolean)
In case of success return user information (json parsed format).
Otherwise raise an AstakosClientException.
"""
auth_path
=
"/im/authenticate"
if
usage
:
auth_path
+=
"?usage=1"
return
self
.
_callAstakos
(
auth_path
)
# ----------------------------------
def
getDisplayNames
(
self
,
uuids
):
"""Return a uuid_catalog dictionary for the given uuids
Keyword arguments:
uuids -- list of user ids (list of strings)
The returned uuid_catalog is a dictionary with uuids as
keys and the corresponding user names as values
"""
req_headers
=
{
'content-type'
:
'application/json'
}
req_body
=
simplejson
.
dumps
({
'uuids'
:
uuids
})
req_path
=
"/user_catalogs"
data
=
self
.
_callAstakos
(
req_path
,
req_headers
,
req_body
,
"POST"
)
# XXX: check if exists
return
data
.
get
(
"uuid_catalog"
)
def
getDisplayName
(
self
,
uuid
):
"""Return the displayName of a uuid (see getDisplayNames)"""
if
not
uuid
:
m
=
"No uuid was given"
self
.
logger
.
error
(
m
)
raise
ValueError
(
m
)
uuid_dict
=
self
.
getDisplayNames
([
uuid
])
# XXX: check if exists
return
uuid_dict
.
get
(
uuid
)
# A simple retry decorator
def
retry
(
howmany
):
...
...
@@ -68,75 +201,34 @@ def retry(howmany):
return
decorator
# ----------------------------
# Authenticate
@
retry
(
3
)
def
authenticate
(
token
,
astakos_url
,
usage
=
False
,
use_pool
=
False
):
"""Check if user is an authenticated Astakos user
Keyword arguments:
token -- user's token (string)
astakos_url -- i.e https://accounts.example.com (string)
usage -- return usage information for user (boolean)
use_pool -- use objpool for http requests (boolean)
In case of success return user informations (json parsed format).
Otherwise raise an Exception.
"""
authentication_url
=
urlparse
.
urljoin
(
astakos_url
,
"/im/authenticate"
)
if
usage
:
authentication_url
+=
"?usage=1,"
return
_callAstakos
(
token
,
authentication_url
,
use_pool
=
use_pool
)
# ----------------------------
# Display Names
@
retry
(
3
)
def
getDisplayNames
(
token
,
uuids
,
astakos_url
,
use_pool
=
False
):
"""Return a uuid_catalog dictionary for the given uuids
Keyword arguments:
token -- user's token (string)
uuids -- list of user ids (list of strings)
astakos_url -- i.e https://accounts.example.com (string)
use_pool -- use objpool for http requests (boolean)
The returned uuid_catalog is a dictionary with uuids as
keys and the corresponding user names as values
"""
req_headers
=
{
'content-type'
:
'application/json'
}
req_body
=
simplejson
.
dumps
({
'uuids'
:
uuids
})
req_url
=
urlparse
.
urljoin
(
astakos_url
,
"/user_catalogs"
)
data
=
_callAstakos
(
token
,
req_url
,
headers
=
req_headers
,
body
=
req_body
,
method
=
"POST"
,
use_pool
=
use_pool
)
return
data
.
get
(
"uuid_catalog"
)
def
getDisplayName
(
token
,
uuid
,
astakos_url
,
use_pool
=
False
):
"""Return the displayname of a uuid (see getDisplayNames)"""
if
not
uuid
:
m
=
"No uuid was given"
logger
.
error
(
m
)
raise
ValueError
(
m
)
uuid_dict
=
getDisplayNames
(
token
,
[
uuid
],
astakos_url
,
use_pool
)
return
uuid_dict
.
get
(
uuid
)
# --------------------------------------------------------------------
# Private functions
def
_scheme_to_class
(
scheme
):
"""Return the appropriate
httplib
class for given scheme"""
def
_scheme_to_class
(
scheme
,
use_pool
):
"""Return the appropriate
conn
class for given scheme"""
if
scheme
==
"http"
:
return
httplib
.
HTTPConnection
if
use_pool
:
return
_objpoolHttpScheme
else
:
return
httplib
.
HTTPConnection
elif
scheme
==
"https"
:
return
httplib
.
HTTPSConnection
if
use_pool
:
return
_objpoolHttpsScheme
else
:
return
httplib
.
HTTPSConnection
else
:
return
None
def
_objpoolHttpScheme
(
netloc
):
"""Intialize the appropriate objpool.http class"""
return
objpool
.
http
.
get_http_connection
(
netloc
,
"http"
)
def
_objpoolHttpsScheme
(
netloc
):
"""Intialize the appropriate objpool.http class"""
return
objpool
.
http
.
get_http_connection
(
netloc
,
"https"
)
def
_doRequest
(
conn
,
method
,
url
,
**
kwargs
):
"""The actual request. This function can easily be mocked"""
conn
.
request
(
method
,
url
,
**
kwargs
)
...
...
@@ -144,63 +236,4 @@ def _doRequest(conn, method, url, **kwargs):
length
=
response
.
getheader
(
'content-length'
,
None
)
data
=
response
.
read
(
length
)
status
=
int
(
response
.
status
)
return
(
status
,
data
)
def
_callAstakos
(
token
,
url
,
headers
=
{},
body
=
None
,
method
=
'GET'
,
use_pool
=
False
):
"""Make the actual call to astakos service"""
logger
.
debug
(
"Make a %s request to %s with headers %s "
"and body %s, %s using the pool"
%
(
method
,
url
,
headers
,
body
,
"without"
if
not
use_pool
else
""
))
# Check input
if
not
token
:
m
=
"Token not given"
logger
.
error
(
m
)
raise
ValueError
(
m
)
if
not
url
:
m
=
"Url not given"
logger
.
error
(
m
)
raise
ValueError
(
m
)
# Build request's header and body
kwargs
=
{}
kwargs
[
'headers'
]
=
headers
kwargs
[
'headers'
][
'X-Auth-Token'
]
=
token
if
body
:
kwargs
[
'body'
]
=
body
kwargs
[
'headers'
].
setdefault
(
'content-type'
,
'application/octet-stream'
)
kwargs
[
'headers'
].
setdefault
(
'content-length'
,
len
(
body
)
if
body
else
0
)
# Check for supported scheme
p
=
urlparse
.
urlparse
(
url
)
connection_class
=
_scheme_to_class
(
p
.
scheme
)
if
connection_class
is
None
:
m
=
"Unsupported scheme: %s"
%
p
.
scheme
logger
.
error
(
m
)
raise
ValueError
(
m
)
# Get connection object
if
use_pool
:
conn
=
objpool
.
http
.
get_http_connection
(
p
.
netloc
,
p
.
scheme
)
else
:
conn
=
connection_class
(
p
.
netloc
)
# Send request
try
:
request_url
=
p
.
path
+
'?'
+
p
.
query
(
status
,
data
)
=
_doRequest
(
conn
,
method
,
request_url
,
**
kwargs
)
except
httplib
.
HTTPException
as
err
:
logger
.
error
(
"Failed to send request: %s"
%
err
)
raise
finally
:
conn
.
close
()
# Return
logger
.
debug
(
"Request returned with status %s"
%
status
)
if
status
<
200
or
status
>=
300
:
raise
Exception
(
status
,
data
)
return
simplejson
.
loads
(
unicode
(
data
))
return
(
data
,
status
)
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment