Back to index

nordugrid-arc-nox  1.1.0~rc6
Public Member Functions | Public Attributes | Private Member Functions
storage.bartender.bartender.Bartender Class Reference

List of all members.

Public Member Functions

def __init__
def initThread
def isisThread
def stat
def delFile
def getFile
def addReplica
def putFile
def unlink
def unmakeCollection
def makeCollection
def unmakeMountpoint
 Created by Salman Toor ###.
def makeMountpoint
def list
 


def move
def modify

Public Attributes

 service_state
 gateway
 ssl_config
 librarian

Private Member Functions

def _traverse
def _new
def _externalStore
def _find_alive_ses
def _add_replica

Detailed Description

Definition at line 23 of file bartender.py.


Constructor & Destructor Documentation

def storage.bartender.bartender.Bartender.__init__ (   self,
  cfg,
  ssl_config,
  service_state 
)
Constructor of the Bartender business-logic class.

Definition at line 25 of file bartender.py.

00025 
00026     def __init__(self, cfg, ssl_config, service_state):
00027         """ Constructor of the Bartender business-logic class.
00028         
00029         """
00030         self.service_state = service_state
00031         gatewayclass = str(cfg.Get('GatewayClass'))
00032         self.gateway = None
00033         if gatewayclass :
00034             cl = import_class_from_string(gatewayclass) 
00035             gatewaycfg = cfg.Get('GatewayCfg')
00036             self.gateway = cl(gatewaycfg)
00037             log.msg(arc.INFO, 'accessing gateway: %s', gatewayclass)
00038         else:
00039             log.msg(arc.INFO, 'This bartender does not support gateway') 
00040             log.msg(arc.INFO, 'cannot connect to gateway. Access of third party store required gateway.')
00041         self.ssl_config = ssl_config
00042         
00043         # get the URLs of the Librarians from the config file
00044         librarian_urls =  get_child_values_by_name(cfg, 'LibrarianURL')
00045         if librarian_urls:
00046             log.msg(arc.INFO,'Got Librarian URLs from the config:', librarian_urls)
00047             self.librarian = LibrarianClient(librarian_urls, ssl_config = self.ssl_config)
00048             self.service_state.running = True
00049         else:
00050             isis_urls = get_child_values_by_name(cfg, 'ISISURL')
00051             if not isis_urls:
00052                 log.msg(arc.ERROR, "Librarian URL or ISIS URL not found in the configuration.")
00053                 raise Exception, 'Bartender cannot run with no Librarian'
00054             log.msg(arc.INFO,'Got ISIS URL, starting initThread')
00055             threading.Thread(target = self.initThread, args = [isis_urls]).start()


Member Function Documentation

def storage.bartender.bartender.Bartender._add_replica (   self,
  size,
  checksumType,
  checksum,
  GUID,
  protocols,
  exceptedSEs = [] 
) [private]
Helper method to initiate addition of a replica to a file.

_add_replica(size, checksumType, checksum, GUID, protocols)

size is the size of the file
checksumType indicates the type of the checksum
checksum is the checksum itself
GUID is the GUID of the file
protocols is a list of protocols

Definition at line 413 of file bartender.py.

00413 
00414     def _add_replica(self, size, checksumType, checksum, GUID, protocols, exceptedSEs=[]):
00415         """ Helper method to initiate addition of a replica to a file.
00416         
00417         _add_replica(size, checksumType, checksum, GUID, protocols)
00418         
00419         size is the size of the file
00420         checksumType indicates the type of the checksum
00421         checksum is the checksum itself
00422         GUID is the GUID of the file
00423         protocols is a list of protocols
00424         """
00425         turl = ''
00426         protocol = ''
00427         # prepare the 'put' request for the shepherd
00428         put_request = [('size', size), ('checksumType', checksumType),
00429             ('checksum', checksum), ('GUID', GUID)] + \
00430             [('protocol', protocol) for protocol in protocols]
00431         # find an alive Shepherd
00432         shepherds = self._find_alive_ses(exceptedSEs)
00433         random.shuffle(shepherds)
00434         while len(shepherds) > 0:
00435             shepherd = shepherds.pop()
00436             # call the SE's put method with the prepared request
00437             try:
00438                 put_response = dict(shepherd.put({'putFile': put_request})['putFile'])
00439             except:
00440                 put_response = {'error' : traceback.format_exc()}
00441             if put_response.has_key('error'):
00442                 log.msg(arc.VERBOSE, 'ERROR from the chosen Shepherd', put_response['error'])
00443             else:
00444                 # if the put request was successful then we have a transfer URL, a choosen protocol and the referenceID of the file
00445                 turl = put_response['TURL']
00446                 protocol = put_response['protocol']
00447                 return 'done', turl, protocol
00448         return 'no suitable shepherd found', turl, protocol
            

Here is the call graph for this function:

Here is the caller graph for this function:

def storage.bartender.bartender.Bartender._externalStore (   self,
  auth,
  url,
  flag = '' 
) [private]
This method calles the gateway backend class to get/check the full URL of the externally stored file

Definition at line 254 of file bartender.py.

00254 
00255     def _externalStore(self, auth, url, flag=''):
00256         """ This method calles the gateway backend class to get/check the full URL of the externally stored file"""
00257         response = {}
00258         if self.gateway != None:
00259             if flag == 'list':      
00260                 response = self.gateway.list(auth, url, flag)
00261             elif flag == 'getFile':
00262                 response = self.gateway.get(auth, url, flag)
00263             elif flag == 'delFile':
00264                 response = self.gateway.remove(auth, url, flag)
00265             elif flag == 'putFile': 
00266                  response = self.gateway.put(auth, url, flag)
00267         else:
00268             if flag == 'list':
00269                 response[url] = {'list': '', 'status': 'gateway is not configured. Bartender does not support mount points', 'protocol':''}            
00270             else:
00271                 response[url]={'turl': '' ,'status': 'gateway is not configured. Bartender does not support mount points', 'protocol':''}
00272         log.msg(arc.VERBOSE, '//// response from the external store:', response)
00273         return response

Here is the caller graph for this function:

def storage.bartender.bartender.Bartender._find_alive_ses (   self,
  except_these = [] 
) [private]
Get the list of currently alive Shepherds.

_find_alive_ses()

Definition at line 394 of file bartender.py.

00394 
00395     def _find_alive_ses(self, except_these=[]):
00396         """  Get the list of currently alive Shepherds.
00397         
00398         _find_alive_ses()
00399         """
00400         # sestore_guid is the GUID of the librarian entry which the list of Shepherds registered by the Librarian
00401         SEs = self.librarian.get([sestore_guid])[sestore_guid]
00402         # SEs contains entries such as {(serviceID, 'nextHeartbeat') : timestamp} which indicates
00403         #   when a specific Shepherd service should report next
00404         #   if this timestamp is not a positive number, that means the Shepherd have not reported in time, probably it is not alive
00405         log.msg(arc.VERBOSE, 'Registered Shepherds in Librarian', SEs)
00406         # get all the Shepherds which has a positiv nextHeartbeat timestamp and which has not already been used
00407         alive_SEs = [s for (s, p), v in SEs.items() if p == 'nextHeartbeat' and int(v) > 0 and not s in except_these]
00408         log.msg(arc.VERBOSE, 'Alive Shepherds:', alive_SEs)
00409         response = []
00410         for se in alive_SEs:
00411             response.append(ShepherdClient(se, ssl_config = self.ssl_config))
00412         return response

Here is the caller graph for this function:

def storage.bartender.bartender.Bartender._new (   self,
  auth,
  child_metadata,
  child_name = None,
  parent_GUID = None,
  parent_metadata = {} 
) [private]
Helper method which create a new entry in the librarian.

_new(child_metadata, child_name = None, parent_GUID = None)

child_metadata is a dictionary with {(section, property) : values} containing the metadata of the new entry
child_name is the name of the new entry 
parent_GUID is the GUID of the parent of the new entry

This method creates a new librarian-entry with the given metadata.
If child_name and parent_GUID are both given, then this method adds a new entry to the parent collection.

Definition at line 201 of file bartender.py.

00201 
00202     def _new(self, auth, child_metadata, child_name = None, parent_GUID = None, parent_metadata = {}):
00203         """ Helper method which create a new entry in the librarian.
00204         
00205         _new(child_metadata, child_name = None, parent_GUID = None)
00206         
00207         child_metadata is a dictionary with {(section, property) : values} containing the metadata of the new entry
00208         child_name is the name of the new entry 
00209         parent_GUID is the GUID of the parent of the new entry
00210         
00211         This method creates a new librarian-entry with the given metadata.
00212         If child_name and parent_GUID are both given, then this method adds a new entry to the parent collection.
00213         """
00214         try:
00215             # set creation time stamp
00216             child_metadata[('timestamps', 'created')] = str(time.time())
00217             if child_name and parent_GUID:
00218                 child_metadata[('parents', '%s/%s' % (parent_GUID, child_name))] = 'parent' # this 'parent' string is never used
00219             # call the new method of the librarian with the child's metadata (requestID is '_new')
00220             new_response = self.librarian.new({'_new' : child_metadata})
00221             # we can access the response with the requestID, so we get the GUID of the newly created entry
00222             (child_GUID, new_success) = new_response['_new']
00223             # if the new method was not successful
00224             if new_success != 'success':
00225                 return 'failed to create new librarian entry', child_GUID
00226             else:
00227                 # if it was successful and we have a parent collection
00228                 if child_name and parent_GUID:
00229                     decision = make_decision_metadata(parent_metadata, auth.get_request('addEntry'))
00230                     if decision == arc.DECISION_PERMIT:
00231                         # we need to add the newly created librarian-entry to the parent collection
00232                         log.msg(arc.VERBOSE, 'adding', child_GUID, 'to parent', parent_GUID)
00233                         # this modifyMetadata request adds a new (('entries',  child_name) : child_GUID) element to the parent collection
00234                         modify_response = self.librarian.modifyMetadata({'_new' : (parent_GUID, 'add', 'entries', child_name, child_GUID),
00235                                                                         '_new_closed?' : (parent_GUID, 'setifvalue=yes', 'states', 'closed', 'broken')})
00236                         log.msg(arc.VERBOSE, 'modifyMetadata response', modify_response)
00237                         # get the 'success' value
00238                         modify_success = modify_response['_new']
00239                     else:
00240                         modify_success = 'denied'
00241                     # if the new element was not set, we have a problem
00242                     if modify_success != 'set':
00243                         log.msg(arc.VERBOSE, 'modifyMetadata failed, removing the new librarian entry', child_GUID)
00244                         # remove the newly created librarian-entry
00245                         self.librarian.remove({'_new' : child_GUID})
00246                         return 'failed to add child to parent', child_GUID
00247                     else:
00248                         return 'done', child_GUID
00249                 else: # no parent given, skip the 'adding child to parent' part
00250                     return 'done', child_GUID
00251         except Exception, e:
00252             log.msg(arc.ERROR, "Error creating new entry in Librarian: %s" % e)
00253             return 'internal error', None
        

Here is the call graph for this function:

Here is the caller graph for this function:

def storage.bartender.bartender.Bartender._traverse (   self,
  requests 
) [private]
Helper method which connects the librarian, and traverses the LNs of the requests.

_traverse(requests)

Removes the trailing slash from  all the LNs in the request.
Returns the requests and the traverse response.

Definition at line 177 of file bartender.py.

00177 
00178     def _traverse(self, requests):
00179         """ Helper method which connects the librarian, and traverses the LNs of the requests.
00180         
00181         _traverse(requests)
00182         
00183         Removes the trailing slash from  all the LNs in the request.
00184         Returns the requests and the traverse response.
00185         """
00186         # in each request the requestID is the key and the value is a list
00187         # the first item of the list is the Logical Name, we want to remove the trailing slash, and
00188         # leave the other items intact
00189         requests = [(rID, [remove_trailing_slash(data[0])] + list(data[1:])) for rID, data in requests.items()]
00190         log.msg(arc.VERBOSE, '//// _traverse request trailing slash removed:', dict(requests))
00191         # then we do the traversing. a traverse request contains a requestID and the Logical Name
00192         # so we just need the key (which is the request ID) and the first item of the value (which is the LN)
00193         traverse_request = dict([(rID, data[0]) for rID, data in requests])
00194         # call the librarian service
00195         traverse_response = self.librarian.traverseLN(traverse_request)
00196         if not traverse_response:
00197             raise Exception, 'Empty response from the Librarian'
00198         # return the requests as list (without the trailing slashes) and the traverse response from the librarian
00199         return requests, traverse_response
00200 

Here is the call graph for this function:

Here is the caller graph for this function:

def storage.bartender.bartender.Bartender.addReplica (   self,
  auth,
  requests,
  protocols 
)
This method initiates the addition of a new replica to a file.

addReplica(requests, protocols)

requests is a dictionary with requestID-GUID pairs
protocols is a list of supported protocols

Definition at line 363 of file bartender.py.

00363 
00364     def addReplica(self, auth, requests, protocols):
00365         """ This method initiates the addition of a new replica to a file.
00366         
00367         addReplica(requests, protocols)
00368         
00369         requests is a dictionary with requestID-GUID pairs
00370         protocols is a list of supported protocols
00371         """
00372         # currently we permit everyone to upload a new replica,
00373         #   if it not matches the checksum or the size, then it will be removed
00374         # get the size and checksum information about all the requested GUIDs (these are in the 'states' section)
00375         #   the second argument of the get method specifies that we only need metadata from the 'states' section
00376         data = self.librarian.get(requests.values(), [('states',''),('locations',''),('policy','')])
00377         response = {}
00378         for rID, GUID in requests.items():
00379             # for each requested GUID
00380             metadata = data[GUID]
00381             log.msg(arc.VERBOSE, 'addReplica', 'requestID', rID, 'GUID', GUID, 'metadata', metadata, 'protocols', protocols)
00382             # get the size and checksum information of the file
00383             size = metadata[('states','size')]
00384             checksumType = metadata[('states','checksumType')]
00385             checksum = metadata[('states','checksum')]
00386             # list of shepherds with an alive or creating replica of this file (to avoid using one shepherd twice)
00387             exceptedSEs = [deserialize_ids(location)[0] 
00388                            for (section, location), status in metadata.items() if section == 'locations' and status in [ALIVE, CREATING, THIRDWHEEL]]
00389             # initiate replica addition of this file with the given protocols 
00390             success, turl, protocol = self._add_replica(size, checksumType, checksum, GUID, protocols, exceptedSEs)
00391             # set the response of this request
00392             response[rID] = (success, turl, protocol)
00393         return response

Here is the call graph for this function:

def storage.bartender.bartender.Bartender.delFile (   self,
  auth,
  requests 
)
Delete a file from the storage: initiate the process.

delFile(requests)

requests is a dictionary with requestID as key and (Logical Name, child metadata, protocols) as value

Definition at line 126 of file bartender.py.

00126 
00127     def delFile(self, auth, requests):
00128         """ Delete a file from the storage: initiate the process.
00129         
00130         delFile(requests)
00131         
00132         requests is a dictionary with requestID as key and (Logical Name, child metadata, protocols) as value
00133         """
00134         auth_request = auth.get_request('delete')
00135         import time
00136         response = {}
00137         # get the information from the librarian
00138         #requests, traverse_response = self._traverse(requests)
00139         traverse_response = self.librarian.traverseLN(requests)
00140         cat_rem_requests = {}
00141         cat_mod_requests = {}
00142         check_again = []
00143         for requestID, (metadata, GUID, LN, restLN, wasComplete, traversedList) in traverse_response.items():
00144             decision = make_decision_metadata(metadata, auth_request)
00145             if decision != arc.DECISION_PERMIT:
00146                 response[requestID] = 'denied'
00147             elif wasComplete and metadata[('entry', 'type')]=='file': # if it was complete, then we found the entry and got the metadata
00148                 # remove the file
00149                 cat_rem_requests[requestID] = GUID
00150                 # if this entry has a parent:
00151                 parents = [p for (s,p) in metadata.keys() if s == 'parents']
00152                 for parent in parents:
00153                     parent_GUID, child_name = parent.split('/')
00154                     cat_mod_requests[requestID + '-' + parent] = (parent_GUID, 'unset', 'entries', child_name, GUID)
00155                     cat_mod_requests[requestID + '-' + parent + '-closed?'] = (parent_GUID, 'setifvalue=yes', 'states', 'closed', 'broken')
00156                 response[requestID] = 'deleted'
00157             elif metadata.get(('entry', 'type'), '') == 'mountpoint' :
00158                 url = metadata[('mountpoint', 'externalURL')]+'/'+restLN
00159                 #print url
00160                 res = self._externalStore(auth ,url,'delFile')
00161                 #print res
00162                 #print res[url]['status']  
00163                 if 'successfully' in res[url]['status']:
00164                     response[requestID] = 'deleted'
00165                 else:
00166                     response[requestID] = 'nosuchLN'       
00167             else: # if it was not complete, then we didn't find the entry, so metadata will be empty
00168                 response[requestID] = 'nosuchLN'
00169         #print cat_rem_requests
00170         #print cat_mod_requests
00171         success = self.librarian.remove(cat_rem_requests)
00172         modify_success = self.librarian.modifyMetadata(cat_mod_requests)
00173         #print success
00174         #print modify_success 
00175         #print response
00176         return response

Here is the call graph for this function:

def storage.bartender.bartender.Bartender.getFile (   self,
  auth,
  requests 
)
Get files from the storage.

getFile(requests)

requests is a dictionary with requestID as key, and (Logical Name, protocol list) as value

Definition at line 274 of file bartender.py.

00274 
00275     def getFile(self, auth, requests):
00276         """ Get files from the storage.
00277         
00278         getFile(requests)
00279         
00280         requests is a dictionary with requestID as key, and (Logical Name, protocol list) as value
00281         """
00282         auth_request = auth.get_request('read')
00283         # call the _traverse helper method the get the information about the requested Logical Names
00284         requests, traverse_response = self._traverse(requests)
00285         response = {}
00286         #print traverse_response
00287         # for each requested LN
00288         for rID, (LN, protocols) in requests:
00289             turl = ''
00290             protocol = ''
00291             success = 'unknown'
00292             try:
00293                 log.msg(arc.VERBOSE, traverse_response[rID])
00294                 # split the traverse response
00295                 metadata, GUID, traversedLN, restLN, wasComplete, traversedList = traverse_response[rID]
00296                 # wasComplete is true if the given LN was found, so it could have been fully traversed
00297                 if not wasComplete:
00298                     if metadata.get(('entry', 'type'), '') == 'mountpoint':
00299                         url = metadata[('mountpoint', 'externalURL')]
00300                         res = self._externalStore(auth ,url+'/'+restLN,'getFile')
00301                         if res:
00302                             for key in res.keys():
00303                                 turl = res[key]['turl']
00304                                 protocol = res[key]['protocol'] 
00305                                 if res[key]['status'] == 'successful':
00306                                     success = 'done'
00307                                 else:
00308                                     success = res[key]['status']  
00309                         else:   
00310                             success = 'not found'
00311                     else:       
00312                         success = 'not found'
00313                 else:
00314                     # metadata contains all the metadata of the given entry
00315                     # ('entry', 'type') is the type of the entry: file, collection, etc.
00316                     decision = make_decision_metadata(metadata, auth_request)
00317                     if decision != arc.DECISION_PERMIT:
00318                         success = 'denied'
00319                     else:
00320                         type = metadata[('entry', 'type')]
00321                         if type != 'file':
00322                             success = 'is not a file'
00323                         else:
00324                             # if it is a file,  then we need all the locations where it is stored and alive
00325                             # this means all the metadata entries with in the 'locations' sections whose value is ALIVE
00326                             # the location itself serialized from the ID of the service and the ID of the replica within the service
00327                             # so the location needs to be deserialized into two ID with deserialize_ids()
00328                             # valid_locations will contain a list if (serviceID, referenceID, state)
00329                             valid_locations = [deserialize_ids(location) + [state] for (section, location), state in metadata.items() if section == 'locations' and state == ALIVE]
00330                             # if this list is empty
00331                             if not valid_locations:
00332                                 success = 'file has no valid replica'
00333                             else:
00334                                 ok = False
00335                                 while not ok and len(valid_locations) > 0:
00336                                     # if there are more valid_locations, randomly select one
00337                                     location = valid_locations.pop(random.choice(range(len(valid_locations))))
00338                                     log.msg(arc.VERBOSE, 'location chosen:', location)
00339                                     # split it to serviceID, referenceID - serviceID currently is just a plain URL of the service
00340                                     url, referenceID, _ = location
00341                                     # create an ShepherdClient with this URL, then send a get request with the referenceID
00342                                     try:
00343                                         get_response = dict(ShepherdClient(url, ssl_config = self.ssl_config).get({'getFile' :
00344                                             [('referenceID', referenceID)] + [('protocol', proto) for proto in protocols]})['getFile'])
00345                                     except:
00346                                         get_response = {'error' : traceback.format_exc()}
00347                                     # get_response is a dictionary with keys such as 'TURL', 'protocol' or 'error'
00348                                     if get_response.has_key('error'):
00349                                         # if there was an error
00350                                         log.msg(arc.VERBOSE, 'ERROR from the chosen Shepherd', get_response['error'])
00351                                         success = 'error while getting TURL (%s)' % get_response['error']
00352                                     else:
00353                                         # get the TURL and the choosen protocol, these will be set as reply for this requestID
00354                                         turl = get_response['TURL']
00355                                         protocol = get_response['protocol']
00356                                         success = 'done'
00357                                         ok = True
00358             except:
00359                 success = 'internal error (%s)' % traceback.format_exc()
00360             # set the success, turl, protocol for this request
00361             response[rID] = (success, turl, protocol)
00362         return response
   

Here is the call graph for this function:

def storage.bartender.bartender.Bartender.initThread (   self,
  isis_urls 
)

Definition at line 56 of file bartender.py.

00056 
00057     def initThread(self, isis_urls):
00058         librarian_found = False
00059         while not librarian_found:
00060             try:
00061                 log.msg(arc.INFO,'Getting Librarians from ISISes')
00062                 for isis_url in isis_urls:
00063                     log.msg(arc.INFO,'Trying to get Librarian from', isis_url)
00064                     isis = ISISClient(isis_url, ssl_config = self.ssl_config)
00065                     try:
00066                         librarian_urls = isis.getServiceURLs(librarian_servicetype)
00067                         log.msg(arc.INFO,'Got Librarian from ISIS:', librarian_urls)
00068                         if librarian_urls:
00069                             self.librarian = LibrarianClient(librarian_urls, ssl_config = self.ssl_config)
00070                             librarian_found = True
00071                     except:
00072                         log.msg(arc.VERBOSE, 'Error connecting to ISIS %{iu}s, reason: %{r}s' % {'iu' : isis_url, 'r' : traceback.format_exc()})
00073                 time.sleep(3)
00074             except Exception, e:
00075                 log.msg(arc.WARNING, 'Error in initThread: %s' % e)                
00076         log.msg(arc.INFO,'initThread finished, starting isisThread')
00077         self.service_state.running = True
00078         threading.Thread(target = self.isisThread, args = [isis_urls]).start()
            

Here is the call graph for this function:

def storage.bartender.bartender.Bartender.isisThread (   self,
  isis_urls 
)

Definition at line 79 of file bartender.py.

00079 
00080     def isisThread(self, isis_urls):
00081         while self.service_state.running:
00082             try:
00083                 time.sleep(30)
00084                 log.msg(arc.INFO,'Getting Librarians from ISISes')
00085                 for isis_url in isis_urls:
00086                     if not self.service_state.running:
00087                         return
00088                     log.msg(arc.INFO,'Trying to get Librarian from', isis_url)
00089                     isis = ISISClient(isis_url, ssl_config = self.ssl_config)        
00090                     librarian_urls = isis.getServiceURLs(librarian_servicetype)
00091                     log.msg(arc.INFO, 'Got Librarian from ISIS:', librarian_urls)
00092                     if librarian_urls:
00093                         self.librarian = LibrarianClient(librarian_urls, ssl_config = self.ssl_config)
00094                         break
00095             except Exception, e:
00096                 log.msg(arc.WARNING, 'Error in isisThread: %s' % e)                

Here is the caller graph for this function:

def storage.bartender.bartender.Bartender.list (   self,
  auth,
  requests,
  neededMetadata = [] 
)

List the contents of a collection.

list(requests, neededMetadata = [])

requests is a dictionary with requestID as key and Logical Name as value
neededMetadata is a list of (section, property) where property could be empty which means all properties of that section
    if neededMetadata is empty it means we need everything

Definition at line 701 of file bartender.py.

00701 
00702     def list(self, auth, requests, neededMetadata = []):
00703         """ List the contents of a collection.
00704         
00705         list(requests, neededMetadata = [])
00706         
00707         requests is a dictionary with requestID as key and Logical Name as value
00708         neededMetadata is a list of (section, property) where property could be empty which means all properties of that section
00709             if neededMetadata is empty it means we need everything
00710         """
00711         auth_request = auth.get_request('read')
00712         #print 'ID: '+auth.get_identity()
00713         # do traverse the requested Logical Names
00714         requests, traverse_response = self._traverse(requests)
00715         response = {}
00716         for requestID, [LN] in requests:
00717             try:
00718                 # for each LN
00719                 metadata, GUID, traversedLN, restLN, wasComplete, traversedlist = traverse_response[requestID]
00720                 #print 'metadata'
00721                 #print metadata
00722                 if wasComplete:
00723                     # this means the LN exists
00724                     decision = make_decision_metadata(metadata, auth_request)
00725                     if decision != arc.DECISION_PERMIT:
00726                         entries = {}
00727                         status = 'denied'
00728                     else:
00729                         # let's get the type
00730                         type = metadata[('entry', 'type')]
00731                         if type == 'file': # files have no contents, we do not list them
00732                             status = 'is a file'
00733                             entries = {}
00734                         elif type == 'mountpoint':
00735                             url = metadata[('mountpoint', 'externalURL')]
00736                             res = self._externalStore(auth, url, 'list')[url]
00737                             status = res['status']
00738                             entries = dict([(name, ('', {})) for name in res['list']])
00739                         else: #if it is not a file, it must be a collection (currently there is no other type)
00740                             status = 'found'
00741                             # get all the properties and values from the 'entries' metadata section of the collection
00742                             #   these are the names and GUIDs: the contents of the collection
00743                             GUIDs = dict([(name, GUID)
00744                                 for (section, name), GUID in metadata.items() if section == 'entries'])
00745                             # get the needed metadata of all the entries
00746                             metadata = self.librarian.get(GUIDs.values(), neededMetadata)
00747                             # create a dictionary with the name of the entry as key and (GUID, metadata) as value
00748                             entries = dict([(name, (GUID, metadata[GUID])) for name, GUID in GUIDs.items()])
00749                 elif metadata.get(('entry', 'type'), '') == 'mountpoint':
00750                     url = metadata[('mountpoint', 'externalURL')] + '/' + restLN
00751                     res = self._externalStore(auth, url, 'list')[url]
00752                     status = res['status']
00753                     entries = dict([(name, ('', {})) for name in res['list']])
00754                 else:
00755                     entries = {}
00756                     status = 'not found'
00757             except Exception, e:
00758                 entries = {}
00759                 status = 'internal error (%s)' % traceback.format_exc()
00760             response[requestID] = (entries, status)
00761         return response

Here is the call graph for this function:

Here is the caller graph for this function:

def storage.bartender.bartender.Bartender.makeCollection (   self,
  auth,
  requests 
)
Create a new collection.

makeCollection(requests)

requests is dictionary with requestID as key and (Logical Name, metadata) as value

Definition at line 589 of file bartender.py.

00589 
00590     def makeCollection(self, auth, requests):
00591         """ Create a new collection.
00592         
00593         makeCollection(requests)
00594         
00595         requests is dictionary with requestID as key and (Logical Name, metadata) as value
00596         """
00597         # do traverse all the requests
00598         requests, traverse_response = self._traverse(requests)
00599         response = {}
00600         for rID, (LN, child_metadata) in requests:
00601             # for each request first split the Logical Name
00602             rootguid, _, child_name = splitLN(LN)
00603             metadata, GUID, traversedLN, restLN, wasComplete, traversedlist = traverse_response[rID]
00604             #print metadata[('entry', 'type')]
00605             if metadata.get(('entry', 'type'), '') == 'mountpoint':
00606                 success = 'cannot create collection in mountpoint'      
00607                 response[rID] = success    
00608                 return response
00609             log.msg(arc.VERBOSE, 'metadata', metadata, 'GUID', GUID, 'traversedLN', traversedLN, 'restLN', restLN, 'wasComplete',wasComplete, 'traversedlist', traversedlist)
00610             child_metadata[('entry','owner')] = auth.get_identity()
00611             child_metadata[('entry','type')] = 'collection'
00612             if wasComplete: # this means the LN exists
00613                 success = 'LN exists'
00614             elif child_name == '': # this only can happen if the LN was a single GUID
00615                 # this means the collection has no parent
00616                 # we only allow this for the global root
00617                 if rootguid != global_root_guid and rootguid != '':
00618                     success = 'cannot create collection without a parent collection'
00619                 else:
00620                     child_metadata[('entry','GUID')] = global_root_guid
00621                     success, _ = self._new(auth, child_metadata)
00622             elif restLN != child_name or GUID == '':
00623                 success = 'parent does not exist'
00624             else:
00625                 # if everything is OK, create the new collection
00626                 #   here GUID is of the parent collection
00627                 success, _ = self._new(auth, child_metadata, child_name, GUID, metadata)
00628             response[rID] = success
00629         return response

Here is the call graph for this function:

def storage.bartender.bartender.Bartender.makeMountpoint (   self,
  auth,
  requests 
)
Create a new Mountpoint.
makeMountpoint(requests)
requests is dictionary with requestID as key and (Logical Name, metadata) as value        

Definition at line 661 of file bartender.py.

00661 
00662     def makeMountpoint(self, auth, requests):
00663         """ Create a new Mountpoint.
00664                 makeMountpoint(requests)
00665                 requests is dictionary with requestID as key and (Logical Name, metadata) as value        """
00666         # do traverse all the requests
00667         requests, traverse_response = self._traverse(requests)
00668         response = {}
00669         
00670         for rID, (LN, child_metadata, URL) in requests:
00671             # for each request first split the Logical Name
00672             rootguid, _, child_name = splitLN(LN)
00673             metadata, GUID, traversedLN, restLN, wasComplete, traversedlist = traverse_response[rID]
00674             #print metadata[('entry', 'type')]
00675             if metadata.get(('entry', 'type'), '') == 'mountpoint':
00676                 success = 'cannot create anything in mountpoint'
00677                 response[rID] = success
00678                 return response
00679 
00680             log.msg(arc.VERBOSE, 'LN', LN, 'URL', URL, 'metadata', metadata, 'GUID', GUID, 'traversedLN', traversedLN, 'restLN', restLN, 'wasComplete',wasComplete, 'traversedlist', traversedlist)
00681             child_metadata[('entry','owner')] = auth.get_identity()
00682             child_metadata[('entry','type')] = 'mountpoint'
00683             child_metadata[('mountpoint','externalURL')] = URL 
00684             if wasComplete: # this means the LN exists
00685                 success = 'LN exists'
00686             elif child_name == '': # this only can happen if the LN was a single GUID
00687                 # this means the collection has no parent
00688                 child_metadata[('entry','GUID')] = rootguid or global_root_guid
00689                 success, _ = self._new(auth, child_metadata)
00690             elif restLN != child_name or GUID == '':
00691                 success = 'parent does not exist'
00692             else:
00693                 # if everything is OK, create the new collection
00694                 #   here GUID is of the parent collection
00695                 success, _ = self._new(auth, child_metadata, child_name, GUID, metadata)
00696             response[rID] = success
00697         return response

Here is the call graph for this function:

def storage.bartender.bartender.Bartender.modify (   self,
  auth,
  requests 
)

Definition at line 860 of file bartender.py.

00860 
00861     def modify(self, auth, requests):
00862         requests, traverse_response = self._traverse(requests)
00863         librarian_requests = {}
00864         not_found = []
00865         denied = []
00866         for changeID, (LN, changeType, section, property, value) in requests:
00867             metadata, GUID, _, _, wasComplete, _ = traverse_response[changeID]
00868             if wasComplete:
00869                 if section == 'states':
00870                     decision = make_decision_metadata(metadata, auth.get_request('modifyStates'))
00871                     # TODO: do this instead with conditions in the Librarian
00872                     if property == 'closed':
00873                         current_state = metadata.get(('states','closed'),'no')
00874                         if value == 'no':
00875                             if current_state != 'no':
00876                                 decision = arc.DECISION_DENY
00877                         elif value == 'yes':
00878                             if current_state not in ['no', 'yes']:
00879                                 decision = arc.DECISION_DENY
00880                         else:
00881                             decision = arc.DECISION_DENY
00882                 elif section == 'metadata':
00883                     decision = make_decision_metadata(metadata, auth.get_request('modifyMetadata'))
00884                 elif section == 'policy':
00885                     decision = make_decision_metadata(metadata, auth.get_request('modifyPolicy'))
00886                 else:
00887                     decision = arc.DECISION_DENY
00888                 if decision == arc.DECISION_PERMIT:
00889                     librarian_requests[changeID] = (GUID, changeType, section, property, value)
00890                 else:
00891                     denied.append(changeID)
00892             else:
00893                 not_found.append(changeID)
00894         response = self.librarian.modifyMetadata(librarian_requests)
00895         for changeID in not_found:
00896             response[changeID] = 'no such LN'
00897         for changeID in denied:
00898             response[changeID] = 'denied'
00899         return response

Here is the call graph for this function:

def storage.bartender.bartender.Bartender.move (   self,
  auth,
  requests 
)
Move a file or collection within the global namespace.

move(requests)

requests is a dictionary with requestID as key and
    (sourceLN, targetLN, preserverOriginal) as value
if preserverOriginal is true this method creates a hard link instead of moving

Definition at line 762 of file bartender.py.

00762 
00763     def move(self, auth, requests):
00764         """ Move a file or collection within the global namespace.
00765         
00766         move(requests)
00767         
00768         requests is a dictionary with requestID as key and
00769             (sourceLN, targetLN, preserverOriginal) as value
00770         if preserverOriginal is true this method creates a hard link instead of moving
00771         """
00772         traverse_request = {}
00773         # create a traverse request, each move request needs two traversing: source and target
00774         for requestID, (sourceLN, targetLN, _) in requests.items():
00775             # from one requestID we create two: one for the source and one for the target
00776             traverse_request[requestID + 'source'] = remove_trailing_slash(sourceLN)
00777             traverse_request[requestID + 'target'] = targetLN
00778         traverse_response = self.librarian.traverseLN(traverse_request)
00779         log.msg(arc.VERBOSE, '\/\/', traverse_response)
00780         response = {}
00781         for requestID, (sourceLN, targetLN, preserveOriginal) in requests.items():
00782             sourceLN = remove_trailing_slash(sourceLN)
00783             # for each request
00784             log.msg(arc.VERBOSE, requestID, sourceLN, targetLN, preserveOriginal)
00785             # get the old and the new name of the entry, these are the last elements of the Logical Names
00786             _, _, old_child_name = splitLN(sourceLN)
00787             _, _, new_child_name = splitLN(targetLN)
00788             # get the GUID of the source LN from the traverse response
00789             _, sourceGUID, _, _, sourceWasComplete, sourceTraversedList \
00790                 = traverse_response[requestID + 'source']
00791             # get the GUID form the target's traverse response, this should be the parent of the target LN
00792             targetMetadata, targetGUID, _, targetRestLN, targetWasComplete, targetTraversedList \
00793                 = traverse_response[requestID + 'target']
00794             if targetMetadata.get(('entry', 'type'), '') == 'mountpoint':
00795                 success = 'moving into a mountpoint is not supported'
00796                 response[requestID] = success
00797                 return response
00798             # if the source traverse was not complete: the source LN does not exist
00799             if not sourceWasComplete:
00800                 success = 'nosuchLN'
00801             # if the target traverse was complete: the target LN already exists
00802             #   but if the new_child_name was empty, then the target is considered to be a collection, so it is OK
00803             elif targetWasComplete and new_child_name != '':
00804                 success = 'targetexists'
00805             # if the target traverse was not complete, and the non-traversed part is not just the new name
00806             # (which means that the parent collection does not exist)
00807             # or the target's traversed list is empty (which means that it has no parent: it's just a single GUID)
00808             elif not targetWasComplete and (targetRestLN != new_child_name or len(targetTraversedList) == 0):
00809                 success = 'invalidtarget'
00810             elif sourceGUID in [guid for (_, guid) in targetTraversedList]:
00811                 # if the the target is within the source's subtree, we cannot move it
00812                 success = 'invalidtarget'
00813             else:
00814                 # if the new child name is empty that means that the target LN has a trailing slash
00815                 #   so we just put the old name after it
00816                 if new_child_name == '':
00817                     new_child_name = old_child_name
00818                 decision = make_decision_metadata(targetMetadata, auth.get_request('addEntry'))
00819                 if decision != arc.DECISION_PERMIT:
00820                     success = 'adding child to parent denied'
00821                 else:
00822                     log.msg(arc.VERBOSE, 'adding', sourceGUID, 'to parent', targetGUID)
00823                     # adding the entry to the new parent
00824                     mm_resp = self.librarian.modifyMetadata(
00825                         {'move-target' : (targetGUID, 'add', 'entries', new_child_name, sourceGUID),
00826                         'move-target-parent' : (sourceGUID, 'set', 'parents', '%s/%s' % (targetGUID, new_child_name), 'parent'),
00827                         'move-target-closed?' : (targetGUID, 'setifvalue=yes', 'states', 'closed', 'broken')})
00828                     mm_succ = mm_resp['move-target']
00829                     if mm_succ != 'set':
00830                         success = 'failed adding child to parent'
00831                     else:
00832                         if preserveOriginal == true:
00833                             success = 'moved'
00834                         else:
00835                             # then we need to remove the source LN
00836                             # get the parent of the source: the source traverse has a list of the GUIDs of all the element along the path
00837                             source_parent_guid = sourceTraversedList[-2][1]
00838                             try:
00839                                 source_parent_metadata = self.librarian.get([source_parent_guid])[source_parent_guid]
00840                                 decision = make_decision_metadata(source_parent_metadata, auth.get_request('removeEntry'))
00841                                 if decision == arc.DECISION_PERMIT:
00842                                     log.msg(arc.VERBOSE, 'removing', sourceGUID, 'from parent', source_parent_guid)
00843                                     # delete the entry from the source parent
00844                                     mm_resp = self.librarian.modifyMetadata(
00845                                         {'move-source' : (source_parent_guid, 'unset', 'entries', old_child_name, ''),
00846                                         'move-source-parent' : (sourceGUID, 'unset', 'parents', '%s/%s' % (source_parent_guid, old_child_name), ''),
00847                                         'move-source-closed?' : (source_parent_guid, 'setifvalue=yes', 'states', 'closed', 'broken')})
00848                                     mm_succ = mm_resp['move-source']
00849                                     if mm_succ != 'unset':
00850                                         success = 'failed to remove original link'
00851                                         # TODO: need some handling; remove the new entry or something
00852                                     else:
00853                                         success = 'moved'
00854                                 else:
00855                                     success = 'denied to remove original link'
00856                             except:
00857                                 success = 'error while removing original link'
00858             response[requestID] = success
00859         return response

Here is the call graph for this function:

def storage.bartender.bartender.Bartender.putFile (   self,
  auth,
  requests 
)
Put a new file to the storage: initiate the process.

putFile(requests)

requests is a dictionary with requestID as key and (Logical Name, child metadata, protocols) as value

Definition at line 449 of file bartender.py.

00449 
00450     def putFile(self, auth, requests):
00451         """ Put a new file to the storage: initiate the process.
00452         
00453         putFile(requests)
00454         
00455         requests is a dictionary with requestID as key and (Logical Name, child metadata, protocols) as value
00456         """
00457         # get all the information about the requested Logical Names from the librarian
00458         requests, traverse_response = self._traverse(requests)
00459         response = {}
00460         for rID, (LN, child_metadata, protocols) in requests:
00461             # for each request
00462             turl = ''
00463             protocol = ''
00464             metadata_ok = False
00465             try:
00466                 # get the size and checksum of the new file
00467                 log.msg(arc.VERBOSE, protocols)
00468                 size = child_metadata[('states', 'size')]
00469                 checksum = child_metadata[('states', 'checksum')]
00470                 checksumType = child_metadata[('states', 'checksumType')]
00471                 # need neededReplicas to see if we should call _add_replica
00472                 neededReplicas = child_metadata[('states', 'neededReplicas')]
00473                 metadata_ok = True
00474             except Exception, e:
00475                 success = 'missing metadata ' + str(e)
00476             if metadata_ok:
00477                 # if the metadata of the new file is OK
00478                 child_metadata[('entry','type')] = 'file'
00479                 child_metadata[('entry','owner')] = auth.get_identity()
00480                 try:
00481                     # split the Logical Name, rootguid will be the GUID of the root collection of this LN,
00482                     #   child_name is the name of the new file withing the parent collection
00483                     rootguid, _, child_name = splitLN(LN)
00484                     log.msg(arc.VERBOSE, 'LN', LN, 'rootguid', rootguid, 'child_name', child_name, 'real rootguid', rootguid or global_root_guid)
00485                     # get the traverse response corresponding to this request
00486                     #   metadata is the metadata of the last element which could been traversed, e.g. the parent of the new file
00487                     #   GUID is the GUID of the same
00488                     #   traversedLN indicates which part of the requested LN could have been traversed
00489                     #   restLN is the non-traversed part of the Logical Name, e.g. the filename of a non-existent file whose parent does exist
00490                     #   wasComplete indicates if the traverse was complete or not, if it was complete means that this LN exists
00491                     #   traversedlist contains the GUID and metadata of each element along the path of the LN
00492                     metadata, GUID, traversedLN, restLN, wasComplete, traversedlist = traverse_response[rID]
00493                     log.msg(arc.VERBOSE, 'metadata', metadata, 'GUID', GUID, 'traversedLN', traversedLN, 'restLN', restLN, 'wasComplete',wasComplete, 'traversedlist', traversedlist)
00494                     # if the traversing stopped at a mount point:
00495                     if metadata.get(('entry','type'), '') == 'mountpoint':
00496                         url = metadata[('mountpoint','externalURL')] + '/' + restLN                
00497                         res = self._externalStore(auth, url, 'putFile') 
00498                         response[rID] = (res[url]['status'],res[url]['turl'],res[url]['protocol']) 
00499                         return response    
00500                     if wasComplete: # this means the LN already exists, so we couldn't put a new file there
00501                         success = 'LN exists'
00502                     elif child_name == '': # this only can happen if the LN was a single GUID
00503                         # this means that the new file will have no parent
00504                         # we don't want to allow this:
00505                         success = 'cannot create a file without a parent collection'
00506                         # # set the type and GUID of the new file
00507                         # child_metadata[('entry','GUID')] = rootguid or global_root_guid
00508                         # # create the new entry
00509                         # success, GUID = self._new(auth, child_metadata)
00510                     elif restLN != child_name or GUID == '':
00511                         # if the non-traversed part of the Logical Name is not actully the name of the new file
00512                         #   or we have no parent guid
00513                         success = 'parent does not exist'
00514                     else:
00515                         # if everything is OK, then we create the new entry
00516                         success, GUID = self._new(auth, child_metadata, child_name, GUID, metadata)
00517                     if success == 'done':
00518                         # if the file was successfully created, it still has no replica, so we initiate creating one
00519                         # if neededReplicas is 0, we do nothing
00520                         if int(neededReplicas) > 0: # this will call shepherd.put()
00521                             success, turl, protocol = self._add_replica(size, checksumType, checksum, GUID, protocols)
00522                 except:
00523                     success = 'internal error (%s)' % traceback.format_exc()
00524             response[rID] = (success, turl, protocol)
00525         return response
        

Here is the call graph for this function:

def storage.bartender.bartender.Bartender.stat (   self,
  auth,
  requests 
)
Returns stat information about entries.

stat(auth, requests)

auth is an AuthRequest object containing information about the user's identity
requests is a dictionary with requestIDs as keys, and Logical Names as values.
    
Returns a dictionary with requestIDs as keys, and metadata as values.
The 'metadata' is a dictionary with (section, property) pairs as keys.

Definition at line 97 of file bartender.py.

00097 
00098     def stat(self, auth, requests):
00099         """ Returns stat information about entries.
00100         
00101         stat(auth, requests)
00102         
00103         auth is an AuthRequest object containing information about the user's identity
00104         requests is a dictionary with requestIDs as keys, and Logical Names as values.
00105     
00106         Returns a dictionary with requestIDs as keys, and metadata as values.
00107         The 'metadata' is a dictionary with (section, property) pairs as keys.
00108         """
00109         response = {}
00110         # get the information from the librarian
00111         requests, traverse_response = self._traverse(requests)
00112         # we are only interested in the metadata and if the traversing was complete or not
00113         for requestID, (metadata, _, _, _, wasComplete, _) in traverse_response.items():
00114             if wasComplete: # if it was complete, then we found the entry and got the metadata
00115                 try:
00116                     decision = make_decision_metadata(metadata, auth.get_request('read'))
00117                     if decision != arc.DECISION_PERMIT:
00118                         metadata = {('error','permission denied') : 'you are not allowed to read'}
00119                 except:
00120                     #log.msg()
00121                     metadata = {('error', 'error checking permission') : traceback.format_exc()}
00122                 response[requestID] = metadata
00123             else: # if it was not complete, then we didn't found the entry, so metadata will be empty
00124                 response[requestID] = {}
00125         return response
   

Here is the call graph for this function:

def storage.bartender.bartender.Bartender.unlink (   self,
  auth,
  requests 
)
docstring for unlink

Definition at line 526 of file bartender.py.

00526 
00527     def unlink(self, auth, requests):
00528         """docstring for unlink"""
00529         auth_request = auth.get_request('removeEntry')
00530         requests, traverse_response = self._traverse(requests)
00531         response = {}
00532         for rID, [LN] in requests:
00533             metadata, GUID, traversedLN, restLN, wasComplete, traversedlist = traverse_response[rID]
00534             #print 'metadata', metadata, 'GUID', GUID, 'traversedLN', traversedLN, 'restLN', restLN, 'wasComplete',wasComplete, 'traversedlist', traversedlist
00535             if not wasComplete:
00536                 success = 'no such LN'
00537             else:
00538                 if len(traversedlist) < 2:
00539                     success = 'nothing to unlink'
00540                 else:
00541                     parent_GUID = traversedlist[-2][1]
00542                     child_name = traversedlist[-1][0]
00543                     parent_metadata = self.librarian.get([parent_GUID])[parent_GUID]
00544                     decision = make_decision_metadata(parent_metadata, auth_request)
00545                     if decision != arc.DECISION_PERMIT:
00546                         success = 'denied'
00547                     else:
00548                         mod_requests = {'unlink' : (parent_GUID, 'unset', 'entries', child_name, ''),
00549                                         'unlink-closed?' : (parent_GUID, 'setifvalue=yes', 'states', 'closed', 'broken')}
00550                         mod_response = self.librarian.modifyMetadata(mod_requests)
00551                         success = mod_response['unlink']
00552             response[rID] = success
00553         return response

Here is the call graph for this function:

def storage.bartender.bartender.Bartender.unmakeCollection (   self,
  auth,
  requests 
)
docstring for unmakeCollection

Definition at line 554 of file bartender.py.

00554 
00555     def unmakeCollection(self, auth, requests):
00556         """docstring for unmakeCollection"""
00557         auth_request = auth.get_request('delete')
00558         requests, traverse_response = self._traverse(requests)
00559         response = {}
00560         for rID, [LN] in requests:
00561             metadata, GUID, traversedLN, restLN, wasComplete, traversedlist = traverse_response[rID]
00562             log.msg(arc.VERBOSE, 'metadata', metadata, 'GUID', GUID, 'traversedLN', traversedLN, 'restLN', restLN, 'wasComplete',wasComplete, 'traversedlist', traversedlist)
00563             if not wasComplete:
00564                 success = 'no such LN'
00565             else:
00566                 decision = make_decision_metadata(metadata, auth_request)
00567                 if decision != arc.DECISION_PERMIT:
00568                     success = 'denied'
00569                 else:
00570                     number_of_entries = len([section for (section, _), _ in metadata.items() if section == 'entries'])
00571                     if number_of_entries > 0:
00572                         success = 'collection is not empty'
00573                     else:
00574                         try:
00575                             parentLN, parentGUID = traversedlist[-2]
00576                             # TODO: get the metadata of the parent, and check if the user has permission to removeEntry from it
00577                             mod_requests = {'unmake' : (parentGUID, 'unset', 'entries', traversedlist[-1][0], ''),
00578                                             'unmake-closed?' : (parentGUID, 'setifvalue=yes', 'states', 'closed', 'broken')}
00579                             mod_response = self.librarian.modifyMetadata(mod_requests)
00580                             success = mod_response['unmake']
00581                         except IndexError:
00582                             # it has no parent
00583                             success = 'unset'
00584                         if success == 'unset':
00585                             # TODO: handle hardlinks to collections
00586                             success = self.librarian.remove({'unmake' : GUID})['unmake']
00587             response[rID] = success
00588         return response

Here is the call graph for this function:

def storage.bartender.bartender.Bartender.unmakeMountpoint (   self,
  auth,
  requests 
)

Created by Salman Toor ###.

docstring for unmakeMountpoint

Definition at line 632 of file bartender.py.

00632 
00633     def unmakeMountpoint(self, auth, requests):        
00634         """docstring for unmakeMountpoint"""  
00635         auth_request = auth.get_request('delete')      
00636         requests, traverse_response = self._traverse(requests)
00637         response = {}
00638         for rID, [LN] in requests:
00639             metadata, GUID, traversedLN, restLN, wasComplete, traversedlist = traverse_response[rID]
00640             log.msg(arc.VERBOSE, 'metadata', metadata, 'GUID', GUID, 'traversedLN', traversedLN, 'restLN', restLN, 'wasComplete',wasComplete, 'traversedlist', traversedlist)
00641             if not wasComplete:
00642                 success = 'no such LN'
00643             else:
00644                 decision = make_decision_metadata(metadata, auth_request)
00645                 if decision != arc.DECISION_PERMIT:
00646                     success = 'denied'
00647                 else:
00648                     try:
00649                         parentLN, parentGUID = traversedlist[-2]
00650                         # TODO: get the metadata of the parent, and check if the user has permission to removeEntry from it
00651                         mod_requests = {'unmake' : (parentGUID, 'unset', 'entries', traversedlist[-1][0], '')}
00652                         mod_response = self.librarian.modifyMetadata(mod_requests)
00653                         success = mod_response['unmake']
00654                     except IndexError:
00655                         # it has no parent
00656                         success = 'unset'
00657                     if success == 'unset':
00658                         success = self.librarian.remove({'unmake' : GUID})['unmake']
00659             response[rID] = success
00660         return response

Here is the call graph for this function:


Member Data Documentation

Definition at line 31 of file bartender.py.

Definition at line 46 of file bartender.py.

Definition at line 29 of file bartender.py.

Definition at line 40 of file bartender.py.


The documentation for this class was generated from the following file: