Cleaning and commenting mostly.
authorSandrine Avakian <sandrine.avakian@inria.fr>
Tue, 16 Jul 2013 14:37:11 +0000 (16:37 +0200)
committerSandrine Avakian <sandrine.avakian@inria.fr>
Tue, 16 Jul 2013 14:37:11 +0000 (16:37 +0200)
Adding a new class in OARrestapi.py to put together all the parsing functions
used for a GET_resources_full.

sfa/iotlab/LDAPapi.py
sfa/iotlab/OARrestapi.py
sfa/iotlab/iotlabaggregate.py
sfa/iotlab/iotlabdriver.py

index 1ba0b6f..284ca44 100644 (file)
@@ -14,11 +14,10 @@ import os.path
 
 class LdapConfig():
     """
-    Ldap configuration class@make_ldap_filters_from_record and sets the
-        ldap IP address, password, people dn, web dn, group dn
-        . All these settings were defined in a separate
-        file  ldap_config.py to avoid sharing them in the SFA git as it contains
-        sensible information.
+    Ldap configuration class loads the configuration file and sets the
+    ldap IP address, password, people dn, web dn, group dn. All these settings
+    were defined in a separate file  ldap_config.py to avoid sharing them in
+    the SFA git as it contains sensible information.
 
     """
     def __init__(self, config_file='/etc/sfa/ldap_config.py'):
@@ -121,14 +120,14 @@ class LoginPassword():
     """
 
     Class to handle login and password generation, using custom login generation
-        algorithm.
+    algorithm.
 
     """
     def __init__(self):
         """
 
-        Sets password  and login maximum length, and defines the characters
-            that can be found in a random generated password.
+        Sets password  and login maximum length, and defines the characters that
+        can be found in a random generated password.
 
         """
         self.login_max_length = 8
@@ -147,8 +146,8 @@ class LoginPassword():
     def clean_user_names(record):
         """
 
-        Removes special characters such as
-            '-', '_' , '[', ']' and ' ' from the first name and last name.
+        Removes special characters such as '-', '_' , '[', ']' and ' ' from the
+        first name and last name.
 
         :param record: user's record
         :type record: dict
@@ -176,10 +175,10 @@ class LoginPassword():
         """
 
         When there is no valid first name and last name in the record,
-            the email is used to generate the login. Here, we assume the email
-            is firstname.lastname@something.smthg. The first name and last names
-            are extracted from the email, special charcaters are removed and
-            they are changed into lower case.
+        the email is used to generate the login. Here, we assume the email
+        is firstname.lastname@something.smthg. The first name and last names
+        are extracted from the email, special charcaters are removed and
+        they are changed into lower case.
 
         :param record: user's data
         :type record: dict
@@ -214,8 +213,8 @@ class LoginPassword():
     def get_user_firstname_lastname(self, record):
         """
 
-        Get the user first name and last name from the information
-            we have in the record.
+        Get the user first name and last name from the information we have in
+        the record.
 
         :param record: user's information
         :type record: dict
@@ -238,9 +237,9 @@ class LoginPassword():
     def choose_sets_chars_for_login(self, lower_first_name, lower_last_name):
         """
 
-        Algorithm to select sets of characters from the first name and
-            last name, depending on the lenght of the last name and the
-            maximum login length which in our case is set to 8 characters.
+        Algorithm to select sets of characters from the first name and last
+        name, depending on the lenght of the last name and the maximum login
+        length which in our case is set to 8 characters.
 
         :param lower_first_name: user's first name in lower case.
         :param lower_last_name: usr's last name in lower case.
@@ -285,8 +284,8 @@ class LoginPassword():
         """
 
         Generate a password upon  adding a new user in LDAP Directory
-            (8 characters length). The generated password is composed
-            of characters from the charsPassword list.
+        (8 characters length). The generated password is composed of characters
+        from the chars_password list.
 
         :returns: the randomly generated password
         :rtype: string
@@ -305,8 +304,8 @@ class LoginPassword():
     def encrypt_password(password):
         """
 
-        Use passlib library to make a RFC2307 LDAP encrypted password
-            salt size = 8, use sha-1 algorithm.
+        Use passlib library to make a RFC2307 LDAP encrypted password salt size
+        is 8, use sha-1 algorithm.
 
         :param password:  password not encrypted.
         :type password: string
@@ -484,10 +483,9 @@ class LDAPapi:
         """
 
         When adding a new user to Iotlab's LDAP, creates an attributes
-            dictionnary from the SFA record understandable by LDAP.
-            Generates the user's LDAP login.
-            User is automatically validated (account enabled) and described
-            as a SFA USER FROM OUTSIDE IOTLAB.
+        dictionnary from the SFA record understandable by LDAP. Generates the
+        user's LDAP login.User is automatically validated (account enabled)
+        and described as a SFA USER FROM OUTSIDE IOTLAB.
 
         :param record: must contain the following keys and values:
             first_name, last_name, mail, pkey (ssh key).
@@ -659,7 +657,7 @@ class LDAPapi:
 
     def LdapModify(self, dn, old_attributes_dict, new_attributes_dict):
         """ Modifies a LDAP entry, replaces user's old attributes with
-            the new ones given.
+        the new ones given.
 
         :param dn: user's absolute name  in the LDAP hierarchy.
         :param old_attributes_dict: old user's attributes. Keys must match
@@ -691,9 +689,9 @@ class LDAPapi:
         """
 
         Gets the record from one user based on the user sfa recordand changes
-            the attributes according to the specified new_attributes.
-            Do not use this if we need to modify the uid. Use a ModRDN
-            #operation instead ( modify relative DN )
+        the attributes according to the specified new_attributes. Do not use
+        this if we need to modify the uid. Use a ModRDN operation instead
+        ( modify relative DN ).
 
         :param user_record: sfa user record.
         :param new_attributes_dict: new user attributes, keys must be the
@@ -751,18 +749,18 @@ class LDAPapi:
     def LdapMarkUserAsDeleted(self, record):
         """
 
-        Sets shadowExpire to 0, disabling the user in LDAP.
-            Calls LdapModifyUser to change the shadowExpire of the user.
+        Sets shadowExpire to 0, disabling the user in LDAP. Calls LdapModifyUser
+        to change the shadowExpire of the user.
 
         :param record: the record of the user who has to be disabled.
             Should contain first_name,last_name, email or mail, and if the
             record is enabled or not. If the dict record does not have all of
             these, must at least contain the user's email.
         :type record: dict
-        :returns:  bool True if successful or bool False if not
+        :returns: {bool: True} if successful or {bool: False} if not
         :rtype: dict
 
-        .. seealso:: LdapModifyUser , make_ldap_attributes_from_record
+        .. seealso:: LdapModifyUser, make_ldap_attributes_from_record
         """
 
         new_attrs = {}
@@ -799,9 +797,8 @@ class LDAPapi:
 
     def LdapSearch(self, req_ldap=None, expected_fields=None):
         """
-        Used to search directly in LDAP, by using ldap filters and
-            return fields.
-            When req_ldap is None, returns all the entries in the LDAP.
+        Used to search directly in LDAP, by using ldap filters and return
+        fields. When req_ldap is None, returns all the entries in the LDAP.
 
         :param req_ldap: ldap style request, with appropriate filters,
              example: (cn=*).
index ba785a5..35877ae 100644 (file)
@@ -1,21 +1,20 @@
-#import sys
 from httplib import HTTPConnection, HTTPException, NotConnected
 import json
-#import datetime
-#from time import gmtime, strftime
-import os.path
-import sys
-#import urllib
-#import urllib2
 from sfa.util.config import Config
-#from sfa.util.xrn import hrn_to_urn, get_authority, Xrn, get_leaf
-
 from sfa.util.sfalogging import logger
+import os.path
+import sys
 
 
 class JsonPage:
 
     """Class used to manipulate json pages given by OAR.
+
+    In case the json answer from a GET request is too big to fit in one json
+    page, this class provides helper methods to retrieve all the pages and
+    store them in a list before putting them into one single json dictionary,
+    facilitating the parsing.
+
     """
 
     def __init__(self):
@@ -34,12 +33,11 @@ class JsonPage:
 
     def FindNextPage(self):
         """
-        Gets next data page from OAR when the query's results
-            are too big to  be transmitted in a single page.
-            Uses the "links' item in the json returned to check if
-            an additionnal page has to be loaded.
+        Gets next data page from OAR when the query's results are too big to
+        be transmitted in a single page. Uses the "links' item in the json
+        returned to check if an additionnal page has to be loaded. Updates
+        object attributes next_page, next_offset, and end.
 
-        :returns: next page , next offset query
         """
         if "links" in self.raw_json:
             for page in self.raw_json['links']:
@@ -47,7 +45,6 @@ class JsonPage:
                     self.concatenate = True
                     self.next_page = True
                     self.next_offset = "?" + page['href'].split("?")[1]
-                    print>>sys.stderr, "\r\n \t FindNextPage NEXT LINK"
                     return
 
         if self.concatenate:
@@ -67,6 +64,24 @@ class JsonPage:
 
     @staticmethod
     def ConcatenateJsonPages(saved_json_list):
+        """
+        If the json answer is too big to be contained in a single page,
+        all the pages have to be loaded and saved before being appended to the
+        first page.
+
+        :param saved_json_list: list of all the stored pages, including the
+            first page.
+        :type saved_json_list: list
+        :returns: Returns a dictionary with all the pages saved in the
+            saved_json_list. The key of the dictionary is 'items'.
+        :rtype: dict
+
+
+        .. seealso:: SendRequest
+        .. warning:: Assumes the apilib is 0.2.10 (with the 'items' key in the
+            raw json dictionary)
+
+        """
         #reset items list
 
         tmp = {}
@@ -77,6 +92,12 @@ class JsonPage:
         return tmp
 
     def ResetNextPage(self):
+        """
+        Resets all the Json page attributes (next_page, next_offset,
+        concatenate, end). Has to be done before getting another json answer
+        so that the previous page status does not affect the new json load.
+
+        """
         self.next_page = True
         self.next_offset = None
         self.concatenate = False
@@ -84,11 +105,15 @@ class JsonPage:
 
 
 class OARrestapi:
+    """Class used to connect to the OAR server and to send GET and POST
+    requests.
+
+    """
 
     # classes attributes
 
     OAR_REQUEST_POST_URI_DICT = {'POST_job': {'uri': '/oarapi/jobs.json'},
-                                 'DELETE_jobs_id': \
+                                 'DELETE_jobs_id':
                                  {'uri': '/oarapi/jobs/id.json'},
                                  }
 
@@ -125,6 +150,33 @@ class OARrestapi:
 
     def GETRequestToOARRestAPI(self, request, strval=None,
                             next_page=None, username=None):
+
+        """Makes a GET request to OAR.
+
+        Fetch the uri associated with the resquest stored in
+        OARrequests_uri_dict, adds the username if needed and if available, adds
+        strval to the request uri if needed, connects to OAR and issues the GET
+        request. Gets the json reply.
+
+        :param request: One of the known get requests that are keys in the
+            OARrequests_uri_dict.
+        :param strval: used when a job id has to be specified.
+        :param next_page: used to tell OAR to send the next page for this
+            Get request. Is appended to the GET uri.
+        :param username: used when a username has to be specified, when looking
+            for jobs scheduled by a particular user  for instance.
+
+        :type request: string
+        :type strval: integer
+        :type next_page: boolean
+        :type username: string
+
+
+        :returns: a json dictionary if OAR successfully processed the GET
+        request.
+
+        .. seealso:: OARrequests_uri_dict
+        """
         self.oarserver['uri'] = \
             OARGETParser.OARrequests_uri_dict[request]['uri']
         #Get job details with username
@@ -211,7 +263,7 @@ class OARrestapi:
 
         try:
             answer = json.loads(resp)
-            logger.debug("POSTRequestToOARRestAPI : answer %s" %(answer))
+            logger.debug("POSTRequestToOARRestAPI : answer %s" % (answer))
             return answer
 
         except ValueError, error:
@@ -220,73 +272,222 @@ class OARrestapi:
             #raise ServerError("Failed to parse Server Response:" + answer)
 
 
+class ParsingResourcesFull():
+    """
+    Class dedicated to parse the json response from a GET_resources_full from
+    OAR.
 
-def AddOarNodeId(tuplelist, value):
-    """ Adds Oar internal node id to the nodes attributes """
+    """
+    def __init__(self):
+        self.resources_fulljson_dict = {
+        'network_address': self.AddNodeNetworkAddr,
+        'site':  self.AddNodeSite,
+        # 'radio':  self.AddNodeRadio,
+        'mobile':  self.AddMobility,
+        'x':  self.AddPosX,
+        'y':  self.AddPosY,
+        'z': self.AddPosZ,
+        'archi': self.AddHardwareType,
+        'state': self.AddBootState,
+        'id': self.AddOarNodeId,
+        }
 
-    tuplelist.append(('oar_id', int(value)))
 
 
-def AddNodeNetworkAddr(dictnode, value):
-    #Inserts new key. The value associated is a tuple list
-    node_id = value
+    def AddOarNodeId(self, tuplelist, value):
+        """Adds Oar internal node id to the nodes' attributes.
 
-    dictnode[node_id] = [('node_id', node_id),('hostname', node_id) ]
+        Appends tuple ('oar_id', node_id) to the tuplelist. Used by ParseNodes.
 
-    return node_id
+        .. seealso:: ParseNodes
 
-def AddNodeSite(tuplelist, value):
-    tuplelist.append(('site', str(value)))
+        """
 
-def AddNodeRadio(tuplelist, value):
-    tuplelist.append(('radio', str(value)))
+        tuplelist.append(('oar_id', int(value)))
 
 
-def AddMobility(tuplelist, value):
-    if value is 0:
-        tuplelist.append(('mobile', 'False'))
-    else:
-        tuplelist.append(('mobile', 'True'))
+    def AddNodeNetworkAddr(self, dictnode, value):
+        """First parsing function to be called to parse the json returned by OAR
+        answering a GET_resources (/oarapi/resources.json) request.
 
-def AddPosX(tuplelist, value):
-    tuplelist.append(('posx', value))
+        When a new node is found in the json, this function is responsible for
+        creating a new entry in the dictionary for storing information on this
+        specific node. The key is the node network address, which is also the
+        node's hostname.
+        The value associated with the key is a tuple list.It contains all
+        the nodes attributes. The tuplelist will later be turned into a dict.
 
-def AddPosY(tuplelist, value):
-    tuplelist.append(('posy', value))
+        :param dictnode: should be set to the OARGETParser atribute node_dictlist.
+            It will store the information on the nodes.
+        :param value: the node_id is the network_address in the raw json.
+        :type value: string
+        :type dictnode: dictionary
 
-def AddPosZ(tuplelist, value):
-    tuplelist.append(('posz', value))
+        .. seealso: ParseResources, ParseNodes
+        """
+
+        node_id = value
+        dictnode[node_id] = [('node_id', node_id),('hostname', node_id) ]
+
+        return node_id
+
+    def AddNodeSite(self, tuplelist, value):
+        """Add the site's node to the dictionary.
+
+
+        :param tuplelist: tuple list on which to add the node's site. Contains the
+            other node attributes as well.
+        :param value: value to add to the tuple list, in this case the node's site.
+        :type tuplelist: list
+        :type value: string
+
+        .. seealso:: AddNodeNetworkAddr
+
+        """
+        tuplelist.append(('site', str(value)))
+
+    # def AddNodeRadio(tuplelist, value):
+    #     """Add thenode's radio chipset type to the tuple list.
+
+    #     :param tuplelist: tuple list on which to add the node's mobility status. The
+    #         tuplelist is the value associated with the node's id in the OARGETParser
+    #          's dictionary node_dictlist.
+    #     :param value: name of the radio chipset on the node.
+    #     :type tuplelist: list
+    #     :type value: string
+
+    #     .. seealso:: AddNodeNetworkAddr
+
+    #     """
+    #     tuplelist.append(('radio', str(value)))
+
+
+    def AddMobility(self, tuplelist, value):
+        """Add if the node is a mobile node or not to the tuple list.
 
-def AddBootState(tuplelist, value):
-    tuplelist.append(('boot_state', str(value)))
+        :param tuplelist: tuple list on which to add the node's mobility status. The
+            tuplelist is the value associated with the node's id in the OARGETParser
+             's dictionary node_dictlist.
+        :param value: tells if a node is a mobile node or not. The value is found
+            in the json.
 
-#Insert a new node into the dictnode dictionary
-def AddNodeId(dictnode, value):
-    #Inserts new key. The value associated is a tuple list
-    node_id = int(value)
+        :type tuplelist: list
+        :type value: integer
 
-    dictnode[node_id] = [('node_id', node_id)]
-    return node_id
+        .. seealso:: AddNodeNetworkAddr
 
-def AddHardwareType(tuplelist, value):
-    value_list = value.split(':')
-    tuplelist.append(('archi', value_list[0]))
-    tuplelist.append(('radio', value_list[1]))
+        """
+        if value is 0:
+            tuplelist.append(('mobile', 'False'))
+        else:
+            tuplelist.append(('mobile', 'True'))
+
+
+    def AddPosX(self, tuplelist, value):
+        """Add the node's position on the x axis.
+
+        :param tuplelist: tuple list on which to add the node's position . The
+            tuplelist is the value associated with the node's id in the OARGETParser
+             's dictionary node_dictlist.
+        :param value: the position x.
+
+        :type tuplelist: list
+        :type value: integer
+
+         .. seealso:: AddNodeNetworkAddr
+
+        """
+        tuplelist.append(('posx', value ))
+
+
+
+    def AddPosY(self, tuplelist, value):
+        """Add the node's position on the y axis.
+
+        :param tuplelist: tuple list on which to add the node's position . The
+            tuplelist is the value associated with the node's id in the OARGETParser
+             's dictionary node_dictlist.
+        :param value: the position y.
+
+        :type tuplelist: list
+        :type value: integer
+
+         .. seealso:: AddNodeNetworkAddr
+
+        """
+        tuplelist.append(('posy', value))
+
+
+
+    def AddPosZ(self, tuplelist, value):
+        """Add the node's position on the z axis.
+
+        :param tuplelist: tuple list on which to add the node's position . The
+            tuplelist is the value associated with the node's id in the OARGETParser
+             's dictionary node_dictlist.
+        :param value: the position z.
+
+        :type tuplelist: list
+        :type value: integer
+
+         .. seealso:: AddNodeNetworkAddr
+
+        """
+
+        tuplelist.append(('posz', value))
+
+
+
+    def AddBootState(tself, tuplelist, value):
+        """Add the node's state, Alive or Suspected.
+
+        :param tuplelist: tuple list on which to add the node's state . The
+            tuplelist is the value associated with the node's id in the OARGETParser
+             's dictionary node_dictlist.
+        :param value: node's state.
+
+        :type tuplelist: list
+        :type value: string
+
+         .. seealso:: AddNodeNetworkAddr
+
+        """
+        tuplelist.append(('boot_state', str(value)))
+
+
+    def AddHardwareType(self, tuplelist, value):
+        """Add the node's hardware model and radio chipset type to the tuple
+        list.
+
+        :param tuplelist: tuple list on which to add the node's architecture
+            and radio chipset type.
+        :param value: hardware type: radio chipset. The value contains both the
+            architecture and the radio chipset, separated by a colon.
+        :type tuplelist: list
+        :type value: string
+
+        .. seealso:: AddNodeNetworkAddr
+
+        """
+
+        value_list = value.split(':')
+        tuplelist.append(('archi', value_list[0]))
+        tuplelist.append(('radio', value_list[1]))
 
 
 class OARGETParser:
-    resources_fulljson_dict = {
-        'network_address' : AddNodeNetworkAddr,
-        'site': AddNodeSite,
-        'radio': AddNodeRadio,
-        'mobile': AddMobility,
-        'x': AddPosX,
-        'y': AddPosY,
-        'z':AddPosZ,
-        'archi':AddHardwareType,
-        'state':AddBootState,
-        'id' : AddOarNodeId,
-        }
+    resources_fulljson_dict = {
+    #     'network_address': AddNodeNetworkAddr,
+        'site': AddNodeSite,
+    #     # 'radio': AddNodeRadio,
+        'mobile': AddMobility,
+        'x': AddPosX,
+        'y': AddPosY,
+        'z':AddPosZ,
+        'archi':AddHardwareType,
+        'state':AddBootState,
+        'id' : AddOarNodeId,
+        }
 
 
     def __init__(self, srv) :
@@ -306,7 +507,7 @@ class OARGETParser:
         self.node_dictlist = {}
 
         self.json_page = JsonPage()
-
+        self.parsing_resourcesfull = ParsingResourcesFull()
         self.site_dict = {}
         self.SendRequest("GET_version")
 
@@ -315,60 +516,107 @@ class OARGETParser:
 
 
     def ParseVersion(self) :
-        #print self.json_page.raw_json
-        #print >>sys.stderr, self.json_page.raw_json
+        """Parses the OAR answer to the GET_version ( /oarapi/version.json.)
+
+        Finds the OAR apilib version currently used. Has an impact on the json
+        structure returned by OAR, so the version has to be known before trying
+        to parse the jsons returned after a get request has been issued.
+        Updates the attribute version_json_dict.
+
+
+        """
+
         if 'oar_version' in self.json_page.raw_json :
-            self.version_json_dict.update(api_version = \
+            self.version_json_dict.update(api_version =
                                         self.json_page.raw_json['api_version'],
-                    apilib_version = self.json_page.raw_json['apilib_version'],
-                    api_timezone = self.json_page.raw_json['api_timezone'],
-                    api_timestamp = self.json_page.raw_json['api_timestamp'],
-                    oar_version = self.json_page.raw_json['oar_version'] )
+                    apilib_version=self.json_page.raw_json['apilib_version'],
+                    api_timezone=self.json_page.raw_json['api_timezone'],
+                    api_timestamp=self.json_page.raw_json['api_timestamp'],
+                    oar_version=self.json_page.raw_json['oar_version'])
         else:
-            self.version_json_dict.update(api_version = \
-                        self.json_page.raw_json['api'] ,
-                        apilib_version = self.json_page.raw_json['apilib'],
-                        api_timezone = self.json_page.raw_json['api_timezone'],
-                        api_timestamp = self.json_page.raw_json['api_timestamp'],
-                        oar_version = self.json_page.raw_json['oar'] )
+            self.version_json_dict.update(api_version =
+                        self.json_page.raw_json['api'],
+                        apilib_version=self.json_page.raw_json['apilib'],
+                        api_timezone=self.json_page.raw_json['api_timezone'],
+                        api_timestamp=self.json_page.raw_json['api_timestamp'],
+                        oar_version=self.json_page.raw_json['oar'])
 
         print self.version_json_dict['apilib_version']
 
 
-    def ParseTimezone(self) :
+    def ParseTimezone(self):
+        """Get the timezone used by OAR.
+
+        Get the timezone from the answer to the GET_timezone request.
+        :return: api_timestamp and api timezone.
+        :rype: integer, integer
+
+        .. warning:: unused.
+        """
         api_timestamp = self.json_page.raw_json['api_timestamp']
         api_tz = self.json_page.raw_json['timezone']
         return api_timestamp, api_tz
 
-    def ParseJobs(self) :
+    def ParseJobs(self):
+        """Called when a GET_jobs request has been issued to OAR.
+
+        Corresponds to /oarapi/jobs.json uri. Currently returns the raw json
+        information dict.
+        :returns: json_page.raw_json
+        :rtype: dictionary
+
+        .. warning:: Does not actually parse the information in the json. SA
+            15/07/13.
+
+        """
         self.jobs_list = []
         print " ParseJobs "
         return self.json_page.raw_json
 
-    def ParseJobsTable(self) :
+    def ParseJobsTable(self):
+        """In case we need to use the job table in the future.
+
+        Associated with the GET_jobs_table : '/oarapi/jobs/table.json uri.
+        .. warning:: NOT USED. DOES NOTHING.
+        """
         print "ParseJobsTable"
 
-    def ParseJobsDetails (self):
-        # currently, this function is not used a lot,
-        #so i have no idea what be usefull to parse,
-        #returning the full json. NT
+    def ParseJobsDetails(self):
+        """Currently only returns the same json in self.json_page.raw_json.
+
+        .. todo:: actually parse the json
+        .. warning:: currently, this function is not used a lot, so I have no
+            idea what could  be useful to parse, returning the full json. NT
+        """
+
         #logger.debug("ParseJobsDetails %s " %(self.json_page.raw_json))
         return self.json_page.raw_json
 
 
     def ParseJobsIds(self):
+        """Associated with the GET_jobs_id OAR request.
 
-        job_resources = ['wanted_resources', 'name', 'id', 'start_time', \
-                        'state','owner','walltime','message']
+        Parses the json dict (OAR answer) to the GET_jobs_id request
+        /oarapi/jobs/id.json.
 
 
-        job_resources_full = ['launching_directory', 'links', \
-            'resubmit_job_id', 'owner', 'events', 'message', \
-            'scheduled_start', 'id', 'array_id',  'exit_code', \
-            'properties', 'state','array_index', 'walltime', \
-            'type', 'initial_request', 'stop_time', 'project',\
-            'start_time',  'dependencies','api_timestamp','submission_time', \
-            'reservation', 'stdout_file', 'types', 'cpuset_name', \
+        :returns: dictionary whose keys are listed in the local variable
+            job_resources and values that are in the json dictionary returned
+            by OAR with the job information.
+        :rtype: dict
+
+        """
+        job_resources = ['wanted_resources', 'name', 'id', 'start_time',
+                        'state', 'owner', 'walltime', 'message']
+
+
+        job_resources_full = ['launching_directory', 'links',
+            'resubmit_job_id', 'owner', 'events', 'message',
+            'scheduled_start', 'id', 'array_id',  'exit_code',
+            'properties', 'state','array_index', 'walltime',
+            'type', 'initial_request', 'stop_time', 'project',
+            'start_time',  'dependencies','api_timestamp','submission_time',
+            'reservation', 'stdout_file', 'types', 'cpuset_name',
             'name',  'wanted_resources','queue','stderr_file','command']
 
 
@@ -452,7 +700,10 @@ class OARGETParser:
                 nodes.append(node['network_address'])
         return nodes
 
+    def ChangeRawJsonDependingOnApilibVersion(self):
 
+        if self.version_json_dict['apilib_version'] != "0.2.10" :
+            self.json_page.raw_json = self.json_page.raw_json['items']
 
     def ParseDeleteJobs(self):
         """ No need to parse anything in this function.A POST
@@ -472,8 +723,7 @@ class OARGETParser:
         logger.debug("OARRESTAPI ParseResourcesFull________________________ ")
         #print self.json_page.raw_json[1]
         #resources are listed inside the 'items' list from the json
-        if self.version_json_dict['apilib_version'] != "0.2.10" :
-            self.json_page.raw_json = self.json_page.raw_json['items']
+        self.ChangeRawJsonDependingOnApilibVersion()
         self.ParseNodes()
         self.ParseSites()
         return self.node_dictlist
@@ -483,14 +733,12 @@ class OARGETParser:
         ParseResourcesFull is used instead.
 
         """
-        if self.version_json_dict['apilib_version'] != "0.2.10" :
-            self.json_page.raw_json = self.json_page.raw_json['items']
+        self.ChangeRawJsonDependingOnApilibVersion()
         self.ParseNodes()
         self.ParseSites()
         return self.site_dict
 
 
-
     def ParseNodes(self):
         """ Parse nodes properties from OAR
         Put them into a dictionary with key = node id and value is a dictionary
@@ -498,20 +746,22 @@ class OARGETParser:
 
         """
         node_id = None
-        keys = self.resources_fulljson_dict.keys()
+        _resources_fulljson_dict = \
+            self.parsing_resourcesfull.resources_fulljson_dict
+        keys = _resources_fulljson_dict.keys()
         keys.sort()
 
         for dictline in self.json_page.raw_json:
             node_id = None
             # dictionary is empty and/or a new node has to be inserted
-            node_id = self.resources_fulljson_dict['network_address'](\
+            node_id = _resources_fulljson_dict['network_address'](\
                                 self.node_dictlist, dictline['network_address'])
             for k in keys:
                 if k in dictline:
                     if k == 'network_address':
                         continue
 
-                    self.resources_fulljson_dict[k](\
+                    _resources_fulljson_dict[k](\
                                     self.node_dictlist[node_id], dictline[k])
 
             #The last property has been inserted in the property tuple list,
@@ -521,8 +771,20 @@ class OARGETParser:
             node_id = None
 
     @staticmethod
-    def iotlab_hostname_to_hrn( root_auth,  hostname):
-        return root_auth + '.'+ hostname
+    def iotlab_hostname_to_hrn(root_auth,  hostname):
+        """
+        Transforms a node hostname into a SFA hrn.
+
+        :param root_auth: Name of the root authority of the SFA server. In
+            our case, it is set to iotlab.
+        :param hostname: node's hotname, given by OAR.
+        :type root_auth: string
+        :type hostname: string
+        :returns: inserts the root_auth and '.' before the hostname.
+        :rtype: string
+
+        """
+        return root_auth + '.' + hostname
 
 
 
index 8e34d0e..8c3306d 100644 (file)
@@ -49,11 +49,11 @@ class IotlabAggregate:
     def get_slice_and_slivers(self, slice_xrn, login=None):
         """
         Get the slices and the associated leases if any from the iotlab
-        testbed. For each slice, get the nodes in the  associated lease
-        and create a sliver with the necessary info and insertinto the sliver
-        dictionary, keyed on the node hostnames.
-        Returns a dict of slivers based on the sliver's node_id.
-        Called by get_rspec.
+            testbed. For each slice, get the nodes in the  associated lease
+            and create a sliver with the necessary info and insertinto the
+            sliver bdictionary, keyed on the node hostnames.
+            Returns a dict of slivers based on the sliver's node_id.
+            Called by get_rspec.
 
 
         :param slice_xrn: xrn of the slice
@@ -61,7 +61,7 @@ class IotlabAggregate:
 
         :type slice_xrn: string
         :type login: string
-        :reutnr : a list of slices dict and a dictionary of Sliver object
+        :returns: a list of slices dict and a dictionary of Sliver object
         :rtype: (list, dict)
 
         ..note: There is no slivers in iotlab, only leases.
@@ -93,7 +93,8 @@ class IotlabAggregate:
                 node_ids_list =  sfa_slice['node_ids']
             except KeyError:
                 logger.log_exc("SLABAGGREGATE \t \
-                                        get_slice_and_slivers No nodes in the slice - KeyError ")
+                            get_slice_and_slivers No nodes in the slice \
+                            - KeyError ")
                 continue
 
             for node in node_ids_list:
index 8f84513..2d768ed 100644 (file)
@@ -60,6 +60,7 @@ class IotlabDriver(Driver):
 
     def fill_record_info(self, record_list):
         """
+
         For each SFA record, fill in the iotlab specific and SFA specific
             fields in the record.
 
@@ -68,9 +69,9 @@ class IotlabDriver(Driver):
         :returns: list of records with extended information in each record
         :rtype: list
 
-        .. warnings:: Should not be modifying record_list directly because modi
-        fication are kept outside the method's scope. Howerver, there is no
-        other way to do it given the way it's called in registry manager.
+        .. warning:: Should not be modifying record_list directly because modi
+            fication are kept outside the method's scope. Howerver, there is no
+            other way to do it given the way it's called in registry manager.
 
         """
 
@@ -303,7 +304,7 @@ class IotlabDriver(Driver):
 
         :param hrn: user's hrn
         :type hrn: string
-        :return : user record from SFA database
+        :returns: user record from SFA database
         :rtype: RegUser
 
         """