merged from onelab newplc-4.0.13 tag
authorThierry Parmentelat <thierry.parmentelat@sophia.inria.fr>
Thu, 25 Oct 2007 19:59:31 +0000 (19:59 +0000)
committerThierry Parmentelat <thierry.parmentelat@sophia.inria.fr>
Thu, 25 Oct 2007 19:59:31 +0000 (19:59 +0000)
31 files changed:
PLC/AddressTypes.py
PLC/Addresses.py
PLC/ConfFiles.py
PLC/EventObjects.py
PLC/Events.py
PLC/Filter.py
PLC/InitScripts.py
PLC/Keys.py
PLC/Messages.py
PLC/Methods/GetPCUs.py
PLC/Methods/GetPeers.py
PLC/Methods/GetPersons.py
PLC/Methods/GetSliceAttributes.py
PLC/Methods/GetSlices.py
PLC/Methods/ResetPassword.py
PLC/Methods/VerifyPerson.py
PLC/NodeGroups.py
PLC/NodeNetworkSettingTypes.py
PLC/NodeNetworkSettings.py
PLC/NodeNetworks.py
PLC/Nodes.py
PLC/PCUs.py
PLC/Peers.py
PLC/Persons.py
PLC/Roles.py
PLC/Sessions.py
PLC/Sites.py
PLC/SliceAttributeTypes.py
PLC/SliceAttributes.py
PLC/Slices.py
PLCAPI.spec

index 19f9b16..0effbe2 100644 (file)
@@ -58,9 +58,9 @@ class AddressTypes(Table):
                 ints = filter(lambda x: isinstance(x, (int, long)), address_type_filter)
                 strs = filter(lambda x: isinstance(x, StringTypes), address_type_filter)
                 address_type_filter = Filter(AddressType.fields, {'address_type_id': ints, 'name': strs})
-                sql += " AND (%s)" % address_type_filter.sql(api, "OR")
+                sql += " AND (%s) %s" % address_type_filter.sql(api, "OR")
             elif isinstance(address_type_filter, dict):
                 address_type_filter = Filter(AddressType.fields, address_type_filter)
-                sql += " AND (%s)" % address_type_filter.sql(api, "AND")
+                sql += " AND (%s) %s" % address_type_filter.sql(api, "AND")
 
         self.selectall(sql)
index 62f9e3b..36c0d1d 100644 (file)
@@ -94,6 +94,6 @@ class Addresses(Table):
                 address_filter = Filter(Address.fields, {'address_id': address_filter})
             elif isinstance(address_filter, dict):
                 address_filter = Filter(Address.fields, address_filter)
-            sql += " AND (%s)" % address_filter.sql(api)
+            sql += " AND (%s) %s" % address_filter.sql(api)
 
         self.selectall(sql)
index 78853df..dbd46f3 100644 (file)
@@ -150,6 +150,6 @@ class ConfFiles(Table):
                 conf_file_filter = Filter(ConfFile.fields, {'conf_file_id': conf_file_filter})
             elif isinstance(conf_file_filter, dict):
                 conf_file_filter = Filter(ConfFile.fields, conf_file_filter)
-            sql += " AND (%s)" % conf_file_filter.sql(api)
+            sql += " AND (%s) %s" % conf_file_filter.sql(api)
 
         self.selectall(sql)
index 2f4c895..25df867 100644 (file)
@@ -48,15 +48,16 @@ class EventObjects(Table):
        if event_filter is not None:
             if isinstance(event_filter, (list, tuple, set)):
                 event_filter = Filter(EventObject.fields, {'event_id': event_filter})
-                sql += " AND (%s)" % event_filter.sql(api, "OR")
+                sql += " AND (%s) %s" % event_filter.sql(api, "OR")
             elif isinstance(event_filter, dict):
                 event_filter = Filter(EventObject.fields, event_filter)
-                sql += " AND (%s)" % event_filter.sql(api, "AND")
+                sql += " AND (%s) %s" % event_filter.sql(api, "AND")
             elif isinstance (event_filter, int):
                 event_filter = Filter(EventObject.fields, {'event_id':[event_filter]})
-                sql += " AND (%s)" % event_filter.sql(api, "AND")
+                sql += " AND (%s) %s" % event_filter.sql(api, "AND")
             else:
                 raise PLCInvalidArgument, "Wrong event object filter %r"%event_filter
-       sql += " ORDER BY %s" % EventObject.primary_key
+# with new filtering, caller needs to set this explicitly
+#      sql += " ORDER BY %s" % EventObject.primary_key
         
        self.selectall(sql)
index 726777c..ff80efc 100644 (file)
@@ -73,6 +73,7 @@ class Events(Table):
                 event_filter = Filter(Event.fields, {'event_id': event_filter})
             elif isinstance(event_filter, dict):
                 event_filter = Filter(Event.fields, event_filter)
-            sql += " AND (%s)" % event_filter.sql(api)
-       sql += " ORDER BY %s" % Event.primary_key
+            sql += " AND (%s) %s" % event_filter.sql(api)
+# with new filtering, caller needs to set this explicitly
+#      sql += " ORDER BY %s" % Event.primary_key
         self.selectall(sql)
index c20fd9c..4063496 100644 (file)
@@ -14,34 +14,56 @@ class Filter(Parameter, dict):
     """
     A type of parameter that represents a filter on one or more
     columns of a database table.
+    Special features provide support for negation, upper and lower bounds, 
+    as well as sorting and clipping.
 
-    field should be a dictionary of field names and types, e.g.
-
-    {'node_id': Parameter(int, "Node identifier"),
-     'hostname': Parameter(int, "Fully qualified hostname", max = 255),
-     ...}
 
+    fields should be a dictionary of field names and types
     Only filters on non-sequence type fields are supported.
+    example : fields = {'node_id': Parameter(int, "Node identifier"),
+                        'hostname': Parameter(int, "Fully qualified hostname", max = 255),
+                        ...}
+
 
     filter should be a dictionary of field names and values
-    representing an intersection (if join_with is AND) or union (if
-    join_with is OR) filter. If a value is a sequence type, then it
-    should represent a list of possible values for that field.
+    representing  the criteria for filtering. 
+    example : filter = { 'hostname' : '*.edu' , site_id : [34,54] }
+    Whether the filter represents an intersection (AND) or a union (OR) 
+    of these criteria is determined by the join_with argument 
+    provided to the sql method below
+
+    Special features:
 
-    Special forms:
     * a field starting with the ~ character means negation.
-    example :  { '~peer_id' : None }
+    example :  filter = { '~peer_id' : None }
+
     * a field starting with < [  ] or > means lower than or greater than
       < > uses strict comparison
       [ ] is for using <= or >= instead
-    example :  { '>time' : 1178531418 }
-    example :  { ']event_id' : 2305 }
-    * a field starting with [ or ] means older than or more recent than
-      the associated value should be a given unix timestamp
+    example :  filter = { ']event_id' : 2305 }
+    example :  filter = { '>time' : 1178531418 }
+      in this example the integer value denotes a unix timestamp
+
+    * if a value is a sequence type, then it should represent 
+      a list of possible values for that field
+    example : filter = { 'node_id' : [12,34,56] }
+
     * a (string) value containing either a * or a % character is
       treated as a (sql) pattern; * are replaced with % that is the
       SQL wildcard character.
-    example :  { 'hostname' : '*.jp' } 
+    example :  filter = { 'hostname' : '*.jp' } 
+
+    * fields starting with - are special and relate to row selection, i.e. sorting and clipping
+    * '-SORT' : a field name, or an ordered list of field names that are used for sorting
+    * these fields may start with + (default) or - for denoting increasing or decreasing order
+    example : filter = { '-SORT' : [ '+node_id', '-hostname' ] }
+    * '-OFFSET' : the number of first rows to be ommitted
+    * '-LIMIT' : the amount of rows to be returned 
+    example : filter = { '-OFFSET' : 100, '-PAGE':25}
+
+    A realistic example would read
+    GetNodes ( { 'hostname' : '*.edu' , '-SORT' : 'hostname' , '-OFFSET' : 30 , '-PAGE' : 25 } )
+    and that would return nodes matching '*.edu' in alphabetical order from 31th to 55th
     """
 
     def __init__(self, fields = {}, filter = {}, doc = "Attribute filter"):
@@ -86,6 +108,10 @@ class Filter(Parameter, dict):
         else:
             assert join_with in ("AND", "OR")
 
+        # init 
+        sorts = []
+        clips = []
+
         for field, value in self.iteritems():
            # handle negation, numeric comparisons
            # simple, 1-depth only mechanism
@@ -93,6 +119,7 @@ class Filter(Parameter, dict):
            modifiers={'~' : False, 
                       '<' : False, '>' : False,
                       '[' : False, ']' : False,
+                       '-' : False,
                       }
 
            for char in modifiers.keys():
@@ -101,45 +128,76 @@ class Filter(Parameter, dict):
                    field = field[1:]
                    break
 
-            if field not in self.fields:
-#              print 'current fields',self.fields
-                raise PLCInvalidArgument, "Invalid filter field '%s'" % field
-
-            if isinstance(value, (list, tuple, set)):
-                # Turn empty list into (NULL) instead of invalid ()
-                if not value:
-                    value = [None]
-
-                operator = "IN"
-                value = map(str, map(api.db.quote, value))
-                value = "(%s)" % ", ".join(value)
+            # filter on fields
+            if not modifiers['-']:
+                if field not in self.fields:
+                    raise PLCInvalidArgument, "Invalid filter field '%s'" % field
+
+                if isinstance(value, (list, tuple, set)):
+                    # Turn empty list into (NULL) instead of invalid ()
+                    if not value:
+                        value = [None]
+
+                    operator = "IN"
+                    value = map(str, map(api.db.quote, value))
+                    value = "(%s)" % ", ".join(value)
+                else:
+                    if value is None:
+                        operator = "IS"
+                        value = "NULL"
+                    elif isinstance(value, StringTypes) and \
+                            (value.find("*") > -1 or value.find("%") > -1):
+                        operator = "LIKE"
+                        value = str(api.db.quote(value.replace("*", "%")))
+                    else:
+                        operator = "="
+                        if modifiers['<']:
+                            operator='<'
+                        if modifiers['>']:
+                            operator='>'
+                        if modifiers['[']:
+                            operator='<='
+                        if modifiers[']']:
+                            operator='>='
+                        else:
+                            value = str(api.db.quote(value))
+                clause = "%s %s %s" % (field, operator, value)
+
+                if modifiers['~']:
+                    clause = " ( NOT %s ) " % (clause)
+
+                conditionals.append(clause)
+            # sorting and clipping
             else:
-                if value is None:
-                    operator = "IS"
-                    value = "NULL"
-                elif isinstance(value, StringTypes) and \
-                     (value.find("*") > -1 or value.find("%") > -1):
-                   operator = "LIKE"
-                    value = str(api.db.quote(value.replace("*", "%")))
-               else:
-                    operator = "="
-                   if modifiers['<']:
-                       operator='<'
-                   if modifiers['>']:
-                       operator='>'
-                   if modifiers['[']:
-                       operator='<='
-                   if modifiers[']']:
-                       operator='>='
-                   else:
-                       value = str(api.db.quote(value))
-
-            clause = "%s %s %s" % (field, operator, value)
-
-           if modifiers['~']:
-               clause = " ( NOT %s ) " % (clause)
-
-            conditionals.append(clause)
-
-#      print 'sql=',(" %s " % join_with).join(conditionals)
-        return (" %s " % join_with).join(conditionals)
+                if field not in ('SORT','OFFSET','LIMIT'):
+                    raise PLCInvalidArgument, "Invalid filter, unknown sort and clip field %r"%field
+                # sorting
+                if field == 'SORT':
+                    if not isinstance(value,(list,tuple,set)):
+                        value=[value]
+                    for field in value:
+                        order = 'ASC'
+                        if field[0] == '+':
+                            field = field[1:]
+                        elif field[0] == '-':
+                            field = field[1:]
+                            order = 'DESC'
+                        if field not in self.fields:
+                            raise PLCInvalidArgument, "Invalid field %r in SORT filter"%field
+                        sorts.append("%s %s"%(field,order))
+                # clipping
+                elif field == 'OFFSET':
+                    clips.append("OFFSET %d"%value)
+                # clipping continued
+                elif field == 'LIMIT' :
+                    clips.append("LIMIT %d"%value)
+
+        where_part = (" %s " % join_with).join(conditionals)
+        clip_part = ""
+        if sorts:
+            clip_part += " ORDER BY " + ",".join(sorts)
+        if clips:
+            clip_part += " " + " ".join(clips)
+#      print 'where_part=',where_part,'clip_part',clip_part
+        return (where_part,clip_part)
index f425698..9f864d2 100644 (file)
@@ -58,9 +58,9 @@ class InitScripts(Table):
                 ints = filter(lambda x: isinstance(x, (int, long)), initscript_filter)
                 strs = filter(lambda x: isinstance(x, StringTypes), initscript_filter)
                 initscript_filter = Filter(InitScript.fields, {'initscript_id': ints, 'name': strs })
-               sql += " AND (%s)" % initscript_filter.sql(api, "OR")
+               sql += " AND (%s) %s" % initscript_filter.sql(api, "OR")
             elif isinstance(initscript_filter, dict):
                 initscript_filter = Filter(InitScript.fields, initscript_filter)
-               sql += " AND (%s)" % initscript_filter.sql(api, "AND")
+               sql += " AND (%s) %s" % initscript_filter.sql(api, "AND")
 
         self.selectall(sql)
index b81442d..8d22dc2 100644 (file)
@@ -117,6 +117,6 @@ class Keys(Table):
                 key_filter = Filter(Key.fields, {'key_id': key_filter})
             elif isinstance(key_filter, dict):
                 key_filter = Filter(Key.fields, key_filter)
-            sql += " AND (%s)" % key_filter.sql(api)
+            sql += " AND (%s) %s" % key_filter.sql(api)
 
        self.selectall(sql)
index 250ff12..36ff436 100644 (file)
@@ -42,9 +42,9 @@ class Messages(Table):
         if message_filter is not None:
             if isinstance(message_filter, (list, tuple, set)):
                 message_filter = Filter(Message.fields, {'message_id': message_filter})
-                sql += " AND (%s)" % message_filter.sql(api, "OR")
+                sql += " AND (%s) %s" % message_filter.sql(api, "OR")
             elif isinstance(message_filter, dict):
                 message_filter = Filter(Message.fields, message_filter)
-                sql += " AND (%s)" % message_filter.sql(api, "AND")
+                sql += " AND (%s) %s" % message_filter.sql(api, "AND")
 
         self.selectall(sql)
index 3280070..ee9ab4d 100644 (file)
@@ -67,6 +67,7 @@ class GetPCUs(Method):
         # Remove pcu_id if not specified
         if added_fields:
             for pcu in pcus:
-                del pcu['pcu_id']
+               if 'pcu_id' in pcu:
+                   del pcu['pcu_id']
 
         return pcus
index 235c27c..e93fe36 100644 (file)
@@ -8,6 +8,7 @@ from PLC.Parameter import Parameter, Mixed
 from PLC.Filter import Filter
 from PLC.Auth import Auth
 
+from PLC.Persons import Person
 from PLC.Peers import Peer, Peers
 
 class GetPeers (Method):
@@ -19,7 +20,7 @@ class GetPeers (Method):
     specified details will be returned.
     """
 
-    roles = ['admin', 'node']
+    roles = ['admin', 'node','pi','user']
 
     accepts = [
         Auth(),
@@ -32,4 +33,15 @@ class GetPeers (Method):
     returns = [Peer.fields]
 
     def call (self, auth, peer_filter = None, return_fields = None):
-       return Peers(self.api, peer_filter, return_fields)
+        
+        peers = Peers(self.api, peer_filter, return_fields)
+
+        # Remove admin only fields
+        if not isinstance(self.caller, Person) or \
+                'admin' not in self.caller['roles']:
+            for peer in peers:    
+               for field in ['key', 'cacert']:
+                    if field in peer:
+                        del peer[field]
+
+        return peers
index a483dd4..5228933 100644 (file)
@@ -81,6 +81,7 @@ class GetPersons(Method):
         if added_fields:
             for person in persons:
                 for field in added_fields:
-                    del person[field]
+                   if field in person:
+                       del person[field]
 
         return persons
index 80fc344..b8a0a11 100644 (file)
@@ -82,6 +82,7 @@ class GetSliceAttributes(Method):
         # Remove slice_attribute_id if not specified
         if added_fields:
             for slice_attribute in slice_attributes:
-                del slice_attribute['slice_attribute_id']
+               if 'slice_attribute_id' in slice_attribute:
+                   del slice_attribute['slice_attribute_id']
 
         return slice_attributes
index c300ce0..63dc0b4 100644 (file)
@@ -26,7 +26,7 @@ class GetSlices(Method):
         Auth(),
         Mixed([Mixed(Slice.fields['slice_id'],
                      Slice.fields['name'])],
-             Parameter(str,"name"),
+              Parameter(str,"name"),
               Parameter(int,"slice_id"),
               Filter(Slice.fields)),
         Parameter([str], "List of fields to return", nullok = True)
@@ -69,6 +69,7 @@ class GetSlices(Method):
         # Remove slice_id if not specified
         if added_fields:
             for slice in slices:
-                del slice['slice_id']
+               if 'slice_id' in slice:
+                   del slice['slice_id']
 
         return slices
index 367b7c8..0e2d2a9 100644 (file)
@@ -3,6 +3,8 @@ import base64
 import time
 import urllib
 
+from types import StringTypes
+
 from PLC.Debug import log
 from PLC.Faults import *
 from PLC.Method import Method
@@ -41,7 +43,13 @@ class ResetPassword(Method):
 
     def call(self, auth, person_id_or_email, verification_key = None, verification_expires = None):
        # Get account information
-        persons = Persons(self.api, [person_id_or_email])
+        # we need to search in local objects only
+        if isinstance (person_id_or_email,StringTypes):
+            filter={'email':person_id_or_email}
+        else:
+            filter={'person_id':person_id_or_email}
+        filter['peer_id']=None
+        persons = Persons(self.api, filter)
         if not persons:
             raise PLCInvalidArgument, "No such account"
         person = persons[0]
index fd4adb7..9dd784b 100644 (file)
@@ -46,14 +46,14 @@ class VerifyPerson(Method):
        # Get account information
         persons = Persons(self.api, [person_id_or_email])
         if not persons:
-            raise PLCInvalidArgument, "No such account"
+            raise PLCInvalidArgument, "No such account %r"%person_id_or_email
         person = persons[0]
 
         if person['peer_id'] is not None:
-            raise PLCInvalidArgument, "Not a local account"
+            raise PLCInvalidArgument, "Not a local account %r"%person_id_or_email
 
         if person['enabled']:
-            raise PLCInvalidArgument, "Account must be new (disabled)"
+            raise PLCInvalidArgument, "Account %r must be new (disabled)"%person_id_or_email
 
         # Get the primary site name
         person_sites = Sites(self.api, person['site_ids'])
index 90bd5f9..3b00bc6 100644 (file)
@@ -116,9 +116,9 @@ class NodeGroups(Table):
                 ints = filter(lambda x: isinstance(x, (int, long)), nodegroup_filter)
                 strs = filter(lambda x: isinstance(x, StringTypes), nodegroup_filter)
                 nodegroup_filter = Filter(NodeGroup.fields, {'nodegroup_id': ints, 'name': strs})
-                sql += " AND (%s)" % nodegroup_filter.sql(api, "OR")
+                sql += " AND (%s) %s" % nodegroup_filter.sql(api, "OR")
             elif isinstance(nodegroup_filter, dict):
                 nodegroup_filter = Filter(NodeGroup.fields, nodegroup_filter)
-                sql += " AND (%s)" % nodegroup_filter.sql(api, "AND")
+                sql += " AND (%s) %s" % nodegroup_filter.sql(api, "AND")
 
         self.selectall(sql)
index 786ec73..20718dd 100644 (file)
@@ -70,13 +70,13 @@ class NodeNetworkSettingTypes(Table):
                 ints = filter(lambda x: isinstance(x, (int, long)), nodenetwork_setting_type_filter)
                 strs = filter(lambda x: isinstance(x, StringTypes), nodenetwork_setting_type_filter)
                 nodenetwork_setting_type_filter = Filter(NodeNetworkSettingType.fields, {'nodenetwork_setting_type_id': ints, 'name': strs})
-                sql += " AND (%s)" % nodenetwork_setting_type_filter.sql(api, "OR")
+                sql += " AND (%s) %s" % nodenetwork_setting_type_filter.sql(api, "OR")
             elif isinstance(nodenetwork_setting_type_filter, dict):
                 nodenetwork_setting_type_filter = Filter(NodeNetworkSettingType.fields, nodenetwork_setting_type_filter)
-                sql += " AND (%s)" % nodenetwork_setting_type_filter.sql(api, "AND")
+                sql += " AND (%s) %s" % nodenetwork_setting_type_filter.sql(api, "AND")
             elif isinstance (nodenetwork_setting_type_filter, StringTypes):
                 nodenetwork_setting_type_filter = Filter(NodeNetworkSettingType.fields, {'name':[nodenetwork_setting_type_filter]})
-                sql += " AND (%s)" % nodenetwork_setting_type_filter.sql(api, "AND")
+                sql += " AND (%s) %s" % nodenetwork_setting_type_filter.sql(api, "AND")
             else:
                 raise PLCInvalidArgument, "Wrong nodenetwork setting type filter %r"%nodenetwork_setting_type_filter
 
index bba560d..c85bae5 100644 (file)
@@ -51,7 +51,7 @@ class NodeNetworkSettings(Table):
                 nodenetwork_setting_filter = Filter(NodeNetworkSetting.fields, {'nodenetwork_setting_id': [nodenetwork_setting_filter]})
             else:
                 raise PLCInvalidArgument, "Wrong nodenetwork setting filter %r"%nodenetwork_setting_filter
-            sql += " AND (%s)" % nodenetwork_setting_filter.sql(api)
+            sql += " AND (%s) %s" % nodenetwork_setting_filter.sql(api)
 
 
         self.selectall(sql)
index fc21a7d..52f688f 100644 (file)
@@ -221,6 +221,6 @@ class NodeNetworks(Table):
                 nodenetwork_filter = Filter(NodeNetwork.fields, {'nodenetwork_id': [nodenetwork_filter]})
             else:
                 raise PLCInvalidArgument, "Wrong node network filter %r"%nodenetwork_filter
-            sql += " AND (%s)" % nodenetwork_filter.sql(api)
+            sql += " AND (%s) %s" % nodenetwork_filter.sql(api)
 
         self.selectall(sql)
index 1475ca2..517a16a 100644 (file)
@@ -164,16 +164,16 @@ class Nodes(Table):
                 ints = filter(lambda x: isinstance(x, (int, long)), node_filter)
                 strs = filter(lambda x: isinstance(x, StringTypes), node_filter)
                 node_filter = Filter(Node.fields, {'node_id': ints, 'hostname': strs})
-                sql += " AND (%s)" % node_filter.sql(api, "OR")
+                sql += " AND (%s) %s" % node_filter.sql(api, "OR")
             elif isinstance(node_filter, dict):
                 node_filter = Filter(Node.fields, node_filter)
-                sql += " AND (%s)" % node_filter.sql(api, "AND")
+                sql += " AND (%s) %s" % node_filter.sql(api, "AND")
             elif isinstance (node_filter, StringTypes):
                 node_filter = Filter(Node.fields, {'hostname':[node_filter]})
-                sql += " AND (%s)" % node_filter.sql(api, "AND")
+                sql += " AND (%s) %s" % node_filter.sql(api, "AND")
             elif isinstance (node_filter, int):
                 node_filter = Filter(Node.fields, {'node_id':[node_filter]})
-                sql += " AND (%s)" % node_filter.sql(api, "AND")
+                sql += " AND (%s) %s" % node_filter.sql(api, "AND")
             else:
                 raise PLCInvalidArgument, "Wrong node filter %r"%node_filter
 
index 5b69c0a..e1cf6ca 100644 (file)
@@ -111,6 +111,6 @@ class PCUs(Table):
                 pcu_filter = Filter(PCU.fields, {'pcu_id': pcu_filter})
             elif isinstance(pcu_filter, dict):
                 pcu_filter = Filter(PCU.fields, pcu_filter)
-            sql += " AND (%s)" % pcu_filter.sql(api)
+            sql += " AND (%s) %s" % pcu_filter.sql(api)
 
         self.selectall(sql)
index b1de5e7..0973c3d 100644 (file)
@@ -227,9 +227,9 @@ class Peers (Table):
                 ints = filter(lambda x: isinstance(x, (int, long)), peer_filter)
                 strs = filter(lambda x: isinstance(x, StringTypes), peer_filter)
                 peer_filter = Filter(Peer.fields, {'peer_id': ints, 'peername': strs})
-                sql += " AND (%s)" % peer_filter.sql(api, "OR")
+                sql += " AND (%s) %s" % peer_filter.sql(api, "OR")
             elif isinstance(peer_filter, dict):
                 peer_filter = Filter(Peer.fields, peer_filter)
-                sql += " AND (%s)" % peer_filter.sql(api, "AND")
+                sql += " AND (%s) %s" % peer_filter.sql(api, "AND")
 
        self.selectall(sql)
index 139deef..24d71d3 100644 (file)
@@ -322,18 +322,18 @@ class Persons(Table):
                 ints = filter(lambda x: isinstance(x, (int, long)), person_filter)
                 strs = filter(lambda x: isinstance(x, StringTypes), person_filter)
                 person_filter = Filter(Person.fields, {'person_id': ints, 'email': strs})
-                sql += " AND (%s)" % person_filter.sql(api, "OR")
+                sql += " AND (%s) %s" % person_filter.sql(api, "OR")
             elif isinstance(person_filter, dict):
                 person_filter = Filter(Person.fields, person_filter)
-                sql += " AND (%s)" % person_filter.sql(api, "AND")
-           elif isinstance (person_filter, StringTypes):
+                sql += " AND (%s) %s" % person_filter.sql(api, "AND")
+            elif isinstance (person_filter, StringTypes):
                 person_filter = Filter(Person.fields, {'email':[person_filter]})
-                sql += " AND (%s)" % person_filter.sql(api, "AND")
+                sql += " AND (%s) %s" % person_filter.sql(api, "AND")
             elif isinstance (person_filter, int):
                 person_filter = Filter(Person.fields, {'person_id':[person_filter]})
-                sql += " AND (%s)" % person_filter.sql(api, "AND")
-           else:
-                raise PLCInvalidArgument, "Wrong person filter %r"%person_filter           
+                sql += " AND (%s) %s" % person_filter.sql(api, "AND")
+            else:
+                raise PLCInvalidArgument, "Wrong person filter %r"%person_filter
 
        # aggregate data
        all_persons = {}
index 8647766..42b2622 100644 (file)
@@ -64,9 +64,9 @@ class Roles(Table):
                 ints = filter(lambda x: isinstance(x, (int, long)), role_filter)
                 strs = filter(lambda x: isinstance(x, StringTypes), role_filter)
                 role_filter = Filter(Role.fields, {'role_id': ints, 'name': strs})
-                sql += " AND (%s)" % role_filter.sql(api, "OR")
+                sql += " AND (%s) %s" % role_filter.sql(api, "OR")
             elif isinstance(role_filter, dict):
                 role_filter = Filter(Role.fields, role_filter)
-                sql += " AND (%s)" % role_filter.sql(api, "AND")
+                sql += " AND (%s) %s" % role_filter.sql(api, "AND")
 
         self.selectall(sql)
index b470c96..e0a57b3 100644 (file)
@@ -76,10 +76,10 @@ class Sessions(Table):
                 ints = filter(lambda x: isinstance(x, (int, long)), session_filter)
                 strs = filter(lambda x: isinstance(x, StringTypes), session_filter)
                 session_filter = Filter(Session.fields, {'person_id': ints, 'session_id': strs})
-                sql += " AND (%s)" % session_filter.sql(api, "OR")
+                sql += " AND (%s) %s" % session_filter.sql(api, "OR")
            elif isinstance(session_filter, dict):
                session_filter = Filter(Session.fields, session_filter)
-               sql += " AND (%s)" % session_filter.sql(api, "AND")
+               sql += " AND (%s) %s" % session_filter.sql(api, "AND")
 
         if expires is not None:
             if expires >= 0:
index 759e1d7..6157ca5 100644 (file)
@@ -182,16 +182,16 @@ class Sites(Table):
                 ints = filter(lambda x: isinstance(x, (int, long)), site_filter)
                 strs = filter(lambda x: isinstance(x, StringTypes), site_filter)
                 site_filter = Filter(Site.fields, {'site_id': ints, 'login_base': strs})
-                sql += " AND (%s)" % site_filter.sql(api, "OR")
+                sql += " AND (%s) %s" % site_filter.sql(api, "OR")
             elif isinstance(site_filter, dict):
                 site_filter = Filter(Site.fields, site_filter)
-                sql += " AND (%s)" % site_filter.sql(api, "AND")
-           elif isinstance (site_filter, StringTypes):
+                sql += " AND (%s) %s" % site_filter.sql(api, "AND")
+            elif isinstance (site_filter, StringTypes):
                 site_filter = Filter(Site.fields, {'login_base':[site_filter]})
-                sql += " AND (%s)" % site_filter.sql(api, "AND")
+                sql += " AND (%s) %s" % site_filter.sql(api, "AND")
             elif isinstance (site_filter, int):
                 site_filter = Filter(Site.fields, {'site_id':[site_filter]})
-                sql += " AND (%s)" % site_filter.sql(api, "AND")
+                sql += " AND (%s) %s" % site_filter.sql(api, "AND")
             else:
                 raise PLCInvalidArgument, "Wrong site filter %r"%site_filter
 
index 6aa4baa..5884fe0 100644 (file)
@@ -64,9 +64,9 @@ class SliceAttributeTypes(Table):
                 ints = filter(lambda x: isinstance(x, (int, long)), attribute_type_filter)
                 strs = filter(lambda x: isinstance(x, StringTypes), attribute_type_filter)
                 attribute_type_filter = Filter(SliceAttributeType.fields, {'attribute_type_id': ints, 'name': strs})
-                sql += " AND (%s)" % attribute_type_filter.sql(api, "OR")
+                sql += " AND (%s) %s" % attribute_type_filter.sql(api, "OR")
             elif isinstance(attribute_type_filter, dict):
                 attribute_type_filter = Filter(SliceAttributeType.fields, attribute_type_filter)
-                sql += " AND (%s)" % attribute_type_filter.sql(api, "AND")
+                sql += " AND (%s) %s" % attribute_type_filter.sql(api, "AND")
 
         self.selectall(sql)
index cfc0298..9f0b1fb 100644 (file)
@@ -41,6 +41,6 @@ class SliceAttributes(Table):
                 slice_attribute_filter = Filter(SliceAttribute.fields, {'slice_attribute_id': slice_attribute_filter})
             elif isinstance(slice_attribute_filter, dict):
                 slice_attribute_filter = Filter(SliceAttribute.fields, slice_attribute_filter)
-            sql += " AND (%s)" % slice_attribute_filter.sql(api)
+            sql += " AND (%s) %s" % slice_attribute_filter.sql(api)
 
         self.selectall(sql)
index 88c0b57..99054c8 100644 (file)
@@ -151,16 +151,16 @@ class Slices(Table):
                 ints = filter(lambda x: isinstance(x, (int, long)), slice_filter)
                 strs = filter(lambda x: isinstance(x, StringTypes), slice_filter)
                 slice_filter = Filter(Slice.fields, {'slice_id': ints, 'name': strs})
-                sql += " AND (%s)" % slice_filter.sql(api, "OR")
+                sql += " AND (%s) %s" % slice_filter.sql(api, "OR")
             elif isinstance(slice_filter, dict):
                 slice_filter = Filter(Slice.fields, slice_filter)
-                sql += " AND (%s)" % slice_filter.sql(api, "AND")
-           elif isinstance (slice_filter, StringTypes):
+                sql += " AND (%s) %s" % slice_filter.sql(api, "AND")
+            elif isinstance (slice_filter, StringTypes):
                 slice_filter = Filter(Slice.fields, {'name':[slice_filter]})
-                sql += " AND (%s)" % slice_filter.sql(api, "AND")
+                sql += " AND (%s) %s" % slice_filter.sql(api, "AND")
             elif isinstance (slice_filter, int):
                 slice_filter = Filter(Slice.fields, {'slice_id':[slice_filter]})
-                sql += " AND (%s)" % slice_filter.sql(api, "AND")
+                sql += " AND (%s) %s" % slice_filter.sql(api, "AND")
             else:
                 raise PLCInvalidArgument, "Wrong slice filter %r"%slice_filter
 
index 58c1498..28c6703 100644 (file)
@@ -1,10 +1,20 @@
+#
+# $Id$
+#
+
+%define name PLCAPI
+%define version 4.1
+%define subversion 2
+
+%define release %{subversion}%{?pldistro:.%{pldistro}}%{?date:.%{date}}
+
 Summary: PlanetLab Central API
-Name: PLCAPI
-Version: 4.1
-Release: 2%{?pldistro:.%{pldistro}}%{?date:.%{date}}
+Name: %{name}
+Version: %{version}
+Release: %{release}
 License: PlanetLab
 Group: System Environment/Daemons
-URL: http://cvs.planet-lab.org/cvs/new_plc_api
+URL: $URL$
 Source0: %{name}-%{version}.tar.gz
 BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root
 
@@ -43,13 +53,21 @@ through Apache mod_python.
 %setup -q
 
 %build
-# Build __init__.py metafiles and PHP API. Do not build documentation
-# for now.
+# Build __init__.py metafiles and PHP API. 
 %{__make} %{?_smp_mflags} subdirs="php php/xmlrpc"
+# Build documentation
+# beware that making the pdf file somehow overwrites the html
+%{__make} -C doc PLCAPI.pdf
+rm -f doc/PLCAPI.html
+%{__make} -C doc PLCAPI.html
 
 %install
 rm -rf $RPM_BUILD_ROOT
 %{__make} %{?_smp_mflags} install DESTDIR="$RPM_BUILD_ROOT" datadir="%{_datadir}" bindir="%{_bindir}"
+#someone out there skips doc installation - we DO want this installed
+for doc in PLCAPI.html PLCAPI.pdf ; do
+    install -D -m 644 doc/$doc $RPM_BUILD_ROOT/"%{_datadir}"/plc_api/doc/$doc
+done
 
 # Install shell symlink
 mkdir -p $RPM_BUILD_ROOT/%{_bindir}
@@ -68,7 +86,8 @@ rm -rf $RPM_BUILD_ROOT
 
 %files
 %defattr(-,root,root,-)
-%doc doc/PLCAPI.xml doc/PLCAPI.pdf doc/PLCAPI.html
+#someone out there skips doc installation - we DO want this installed
+#%doc doc/PLCAPI.xml doc/PLCAPI.pdf doc/PLCAPI.html
 %dir %{_datadir}/plc_api
 %{_datadir}/plc_api/*
 %{_bindir}/plcsh
@@ -79,4 +98,3 @@ rm -rf $RPM_BUILD_ROOT
 %changelog
 * Fri Oct 27 2006 Mark Huang <mlhuang@CS.Princeton.EDU> - 
 - Initial build.
-