diff --git a/server/src/uds/services/OpenStack/openStack/UDSOpenStackClient.py b/server/src/uds/services/OpenStack/openStack/UDSOpenStackClient.py index f099132b..ef6bd9ba 100644 --- a/server/src/uds/services/OpenStack/openStack/UDSOpenStackClient.py +++ b/server/src/uds/services/OpenStack/openStack/UDSOpenStackClient.py @@ -42,14 +42,12 @@ import dateutil.parser import hashlib import six - -__updated__ = '2017-03-21' +__updated__ = '2018-02-27' logger = logging.getLogger(__name__) # Required: Authentication v3 - # This is a vary basic implementation for what we need from openstack # This does not includes (nor it is intention) full API implementation, just the parts we need # Theese are related to auth, compute & network basically @@ -60,6 +58,7 @@ logger = logging.getLogger(__name__) # Do not verify SSL conections right now VERIFY_SSL = False + # Helpers def ensureResponseIsValid(response, errMsg=None): if response.ok is False: @@ -96,6 +95,7 @@ def getRecurringUrlJson(url, headers, key, params=None, errMsg=None, timeout=10) # Decorators def authRequired(func): + def ensurer(obj, *args, **kwargs): obj.ensureAuthenticated() try: @@ -104,14 +104,18 @@ def authRequired(func): logger.error('Got error {} for openstack'.format(e)) obj._cleanCache() # On any request error, force next time auth raise + return ensurer + def authProjectRequired(func): + def ensurer(obj, *args, **kwargs): if obj._projectId is None: raise Exception('Need a project for method {}'.format(func)) obj.ensureAuthenticated() return func(obj, *args, **kwargs) + return ensurer @@ -193,8 +197,8 @@ class Client(object): def authPassword(self): # If cached data exists, use it as auth - if self._getFromCache() is True: - return + # if self._getFromCache() is True: + # return data = { 'auth': { @@ -239,20 +243,18 @@ class Client(object): self._userId = token['user']['id'] validity = (dateutil.parser.parse(token['expires_at']).replace(tzinfo=None) - dateutil.parser.parse(token['issued_at']).replace(tzinfo=None)).seconds - 60 - logger.debug('The token {} will be valid for {}'.format(self._tokenId, validity)) # Now, if endpoints are present (only if tenant was specified), store & cache them if self._projectId is not None: self._catalog = token['catalog'] - self._saveToCache(validity) + # self._saveToCache(validity) def ensureAuthenticated(self): if self._authenticated is False: self.authPassword() - @authRequired def listProjects(self): return getRecurringUrlJson(self._authUrl + 'v3/users/{user_id}/projects'.format(user_id=self._userId), @@ -261,7 +263,6 @@ class Client(object): errMsg='List Projects', timeout=self._timeout) - @authRequired def listRegions(self): return getRecurringUrlJson(self._authUrl + 'v3/regions/', @@ -270,7 +271,6 @@ class Client(object): errMsg='List Regions', timeout=self._timeout) - @authProjectRequired def listServers(self, detail=False, params=None): path = '/servers/' + 'detail' if detail is True else '' @@ -281,7 +281,6 @@ class Client(object): errMsg='List Vms', timeout=self._timeout) - @authProjectRequired def listImages(self): return getRecurringUrlJson(self._getEndpointFor('image') + '/v2/images?status=active', @@ -290,7 +289,6 @@ class Client(object): errMsg='List Images', timeout=self._timeout) - @authProjectRequired def listVolumeTypes(self): return getRecurringUrlJson(self._getEndpointFor('volumev2') + '/types', @@ -299,7 +297,6 @@ class Client(object): errMsg='List Volume Types', timeout=self._timeout) - @authProjectRequired def listVolumes(self): # self._getEndpointFor('volumev2') + '/volumes' @@ -309,7 +306,6 @@ class Client(object): errMsg='List Volumes', timeout=self._timeout) - @authProjectRequired def listVolumeSnapshots(self, volumeId=None): for s in getRecurringUrlJson(self._getEndpointFor('volumev2') + '/snapshots', @@ -320,7 +316,6 @@ class Client(object): if volumeId is None or s['volume_id'] == volumeId: yield s - @authProjectRequired def listAvailabilityZones(self): for az in getRecurringUrlJson(self._getEndpointFor('compute') + '/os-availability-zone', @@ -331,7 +326,6 @@ class Client(object): if az['zoneState']['available'] is True: yield az['zoneName'] - @authProjectRequired def listFlavors(self): return getRecurringUrlJson(self._getEndpointFor('compute') + '/flavors', @@ -340,7 +334,6 @@ class Client(object): errMsg='List Flavors', timeout=self._timeout) - @authProjectRequired def listNetworks(self): return getRecurringUrlJson(self._getEndpointFor('network') + '/v2.0/networks', @@ -372,7 +365,6 @@ class Client(object): errMsg='List security groups', timeout=self._timeout) - @authProjectRequired def getServer(self, serverId): r = requests.get(self._getEndpointFor('compute') + '/servers/{server_id}'.format(server_id=serverId), @@ -396,7 +388,6 @@ class Client(object): return v - @authProjectRequired def getSnapshot(self, snapshotId): ''' @@ -414,7 +405,6 @@ class Client(object): return v - @authProjectRequired def updateSnapshot(self, snapshotId, name=None, description=None): data = { 'snapshot': {} } @@ -436,7 +426,6 @@ class Client(object): return v - @authProjectRequired def createVolumeSnapshot(self, volumeId, name, description=None): description = 'UDS Snapshot' if description is None else description @@ -461,7 +450,6 @@ class Client(object): return r.json()['snapshot'] - @authProjectRequired def createVolumeFromSnapshot(self, snapshotId, name, description=None): description = 'UDS Volume' if description is None else description @@ -520,7 +508,6 @@ class Client(object): return r.json()['server'] - @authProjectRequired def deleteServer(self, serverId): r = requests.post(self._getEndpointFor('compute') + '/servers/{server_id}/action'.format(server_id=serverId), @@ -533,7 +520,6 @@ class Client(object): # This does not returns anything - @authProjectRequired def deleteSnapshot(self, snapshotId): r = requests.delete(self._getEndpointFor('volumev2') + '/snapshots/{snapshot_id}'.format(snapshot_id=snapshotId), @@ -545,7 +531,6 @@ class Client(object): # Does not returns a message body - @authProjectRequired def startServer(self, serverId): r = requests.post(self._getEndpointFor('compute') + '/servers/{server_id}/action'.format(server_id=serverId), @@ -558,7 +543,6 @@ class Client(object): # This does not returns anything - @authProjectRequired def stopServer(self, serverId): r = requests.post(self._getEndpointFor('compute') + '/servers/{server_id}/action'.format(server_id=serverId), @@ -589,7 +573,6 @@ class Client(object): ensureResponseIsValid(r, 'Resuming server') - def testConnection(self): # First, ensure requested api is supported # We need api version 3.2 or greater