merge changes from HEAD
authorTony Mack <tmack@cs.princeton.edu>
Mon, 23 Jul 2007 12:56:38 +0000 (12:56 +0000)
committerTony Mack <tmack@cs.princeton.edu>
Mon, 23 Jul 2007 12:56:38 +0000 (12:56 +0000)
27 files changed:
Makefile
ModPython.py
PLC/Auth.py
PLC/EventObjects.py
PLC/Events.py
PLC/Filter.py
PLC/Method.py
PLC/Methods/AddNodeToPCU.py
PLC/Methods/AddSlice.py
PLC/Methods/DeleteNodeFromPCU.py
PLC/Methods/DeleteSliceAttribute.py
PLC/Methods/GetNodes.py
PLC/Methods/GetSlivers.py
PLC/Methods/RefreshPeer.py
PLC/Methods/__init__.py
PLC/NodeNetworks.py
PLC/Nodes.py
PLC/Persons.py
PLC/PostgreSQL.py
PLC/Sessions.py
PLC/Shell.py
PLC/Slices.py
PLCAPI.spec
doc/DocBook.py
planetlab4.sql
plcsh
refresh-peer.py

index 1851f23..9948225 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -4,7 +4,7 @@
 # Mark Huang <mlhuang@cs.princeton.edu>
 # Copyright (C) 2005 The Trustees of Princeton University
 #
-# $Id: Makefile,v 1.10 2006/12/15 16:20:20 mlhuang Exp $
+# $Id: Makefile,v 1.12 2007/07/02 19:28:52 tmack Exp $
 #
 
 # Metafiles
@@ -42,6 +42,7 @@ install: $(modules-install)
            --install-scripts=$(DESTDIR)/$(datadir)/plc_api \
            --install-data=$(DESTDIR)/$(datadir)/plc_api
        install -D -m 755 php/xmlrpc/xmlrpc.so $(DESTDIR)/$(shell php-config --extension-dir)/xmlrpc.so
+       install -D -m 755 refresh-peer.py $(DESTDIR)/$(bindir)/refresh-peer.py
 
 $(subdirs): $(init) $(modules)
 
index c722114..a1b2ab2 100644 (file)
@@ -5,7 +5,7 @@
 # Mark Huang <mlhuang@cs.princeton.edu>
 #
 # Copyright (C) 2004-2006 The Trustees of Princeton University
-# $Id$
+# $Id: ModPython.py,v 1.5 2007/02/12 18:42:49 mlhuang Exp $
 #
 
 import sys
index f62b511..83bd211 100644 (file)
@@ -4,7 +4,7 @@
 # Mark Huang <mlhuang@cs.princeton.edu>
 # Copyright (C) 2006 The Trustees of Princeton University
 #
-# $Id$
+# $Id: Auth.py,v 1.18 2007/03/08 22:22:21 tmack Exp $
 #
 
 import crypt
index c239ca4..cbdae05 100644 (file)
@@ -4,7 +4,7 @@
 # Tony Mack <tmack@cs.princeton.edu>
 # Copyright (C) 2006 The Trustees of Princeton University
 #
-# $Id$
+# $Id: EventObjects.py,v 1.3 2007/05/16 18:07:02 tmack Exp $
 #
 
 from PLC.Faults import *
@@ -21,7 +21,7 @@ class EventObject(Row):
     table_name = 'event_object'
     primary_key = 'event_id'
     fields = {
-        'event_object.event_id': Parameter(int, "Event identifier"),
+        'event_id': Parameter(int, "Event identifier"),
         'person_id': Parameter(int, "Identifier of person responsible for event, if any"),
         'node_id': Parameter(int, "Identifier of node responsible for event, if any"),
         'fault_code': Parameter(int, "Event fault code"),
@@ -41,14 +41,34 @@ class EventObjects(Table):
 
     def __init__(self, api, event_filter = None, columns = None):
         Table.__init__(self, api, EventObject, columns)
+       
+       all_fields = EventObject.fields.keys()
+       if not columns:
+           columns = all_fields
+       else:
+           columns = filter(lambda column: column in all_fields, columns)
+       
+       # Since we are querying a table (not a view) ensure that timestamps
+       # are converted to ints in the db before being returned
+       timestamps = ['time']
+       for col in columns:
+           if col in timestamps:
+               index = columns.index(col)
+               columns[index] = "CAST(date_part('epoch', events.time) AS bigint) AS time"
+           elif col in [EventObject.primary_key]:
+                index = columns.index(col)
+                columns[index] = EventObject.table_name+"."+EventObject.primary_key
+                        
        sql = "SELECT %s FROM event_object, events WHERE True" % \
-            ", ".join(self.columns)
-        if event_filter is not None:
+            ", ".join(columns)
+        
+       if event_filter is not None:
             if isinstance(event_filter, (list, tuple, set)):
                 event_filter = Filter(EventObject.fields, {'event_id': event_filter})
             elif isinstance(event_filter, dict):
                 event_filter = Filter(EventObject.fields, event_filter)
             sql += " AND (%s) " % event_filter.sql(api)
        sql += " AND events.event_id = event_object.event_id " 
-       sql += " ORDER BY %s" % EventObject.primary_key
-        self.selectall(sql)
+       sql += " ORDER BY %s" % EventObject.table_name+"."+EventObject.primary_key
+        
+       self.selectall(sql)
index c66fb59..7eaaed7 100644 (file)
@@ -4,7 +4,7 @@
 # Tony Mack <tmack@cs.princeton.edu>
 # Copyright (C) 2006 The Trustees of Princeton University
 #
-# $Id$
+# $Id: Events.py,v 1.13 2007/04/11 20:29:10 tmack Exp $
 #
 
 from PLC.Faults import *
index 49990c6..c20fd9c 100644 (file)
@@ -5,6 +5,8 @@ except NameError:
     from sets import Set
     set = Set
 
+import time
+
 from PLC.Faults import *
 from PLC.Parameter import Parameter, Mixed, python_type
 
@@ -29,6 +31,13 @@ class Filter(Parameter, dict):
     Special forms:
     * a field starting with the ~ character means negation.
     example :  { '~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
     * a (string) value containing either a * or a % character is
       treated as a (sql) pattern; * are replaced with % that is the
       SQL wildcard character.
@@ -55,6 +64,15 @@ class Filter(Parameter, dict):
         # Null filter means no filter
         Parameter.__init__(self, self.fields, doc = doc, nullok = True)
 
+    # this code is not used anymore
+    # at some point the select in the DB for event objects was done on
+    # the events table directly, that is stored as a timestamp, thus comparisons
+    # needed to be done based on SQL timestamps as well
+    def unix2timestamp (self,unix):
+       s = time.gmtime(unix)
+       return "TIMESTAMP'%04d-%02d-%02d %02d:%02d:%02d'" % (s.tm_year,s.tm_mon,s.tm_mday,
+                                                            s.tm_hour,s.tm_min,s.tm_sec)
+
     def sql(self, api, join_with = "AND"):
         """
         Returns a SQL conditional that represents this filter.
@@ -69,13 +87,22 @@ class Filter(Parameter, dict):
             assert join_with in ("AND", "OR")
 
         for field, value in self.iteritems():
-            # provide for negation with a field starting with ~
-            negation=False
-            if field[0] == '~':
-                negation = True
-                field = field[1:]
+           # handle negation, numeric comparisons
+           # simple, 1-depth only mechanism
+
+           modifiers={'~' : False, 
+                      '<' : False, '>' : False,
+                      '[' : False, ']' : False,
+                      }
+
+           for char in modifiers.keys():
+               if field[0] == char:
+                   modifiers[char]=True;
+                   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)):
@@ -96,12 +123,23 @@ class Filter(Parameter, dict):
                     value = str(api.db.quote(value.replace("*", "%")))
                else:
                     operator = "="
-                    value = str(api.db.quote(value))
+                   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 negation:
-                clause = " ( NOT %s ) "%clause
-                
+
+           if modifiers['~']:
+               clause = " ( NOT %s ) " % (clause)
+
             conditionals.append(clause)
 
+#      print 'sql=',(" %s " % join_with).join(conditionals)
         return (" %s " % join_with).join(conditionals)
index 52577f5..552b703 100644 (file)
@@ -4,7 +4,7 @@
 # Mark Huang <mlhuang@cs.princeton.edu>
 # Copyright (C) 2006 The Trustees of Princeton University
 #
-# $Id$
+# $Id: Method.py,v 1.27 2007/05/16 18:56:03 tmack Exp $
 #
 
 import xmlrpclib
@@ -98,8 +98,15 @@ class Method:
            return result
 
         except PLCFault, fault:
-            # Prepend method name to expected faults
-            fault.faultString = self.name + ": " + fault.faultString
+       
+           caller = ""
+           if isinstance(self.caller, Person):
+               caller = 'person_id %s'  % self.caller['person_id']
+            elif isinstance(self.caller, Node):
+                caller = 'node_id %s'  % self.caller['node_id']
+
+            # Prepend caller and method name to expected faults
+            fault.faultString = caller + ": " +  self.name + ": " + fault.faultString
            runtime = time.time() - start
            self.log(fault.faultCode, runtime, *args)
             raise fault
@@ -125,7 +132,7 @@ class Method:
                auth_methods = ['session', 'password', 'capability', 'gpg', 'hmac','anonymous']
                auth_method = args[0]['AuthMethod']
                if auth_method in auth_methods:
-                   event['auth_method'] = auth_method
+                   event['auth_type'] = auth_method
             for password in 'AuthString', 'session':
                 if args[0].has_key(password):
                     auth = args[0].copy()
index 2da5cd6..c0d5eff 100644 (file)
@@ -3,6 +3,7 @@ from PLC.Method import Method
 from PLC.Parameter import Parameter, Mixed
 from PLC.Nodes import Node, Nodes
 from PLC.PCUs import PCU, PCUs
+from PLC.Sites import Site, Sites
 from PLC.Auth import Auth
 
 class AddNodeToPCU(Method):
index 5642519..6cc056c 100644 (file)
@@ -67,6 +67,9 @@ class AddSlice(Method):
                                                                                                          len(site['slice_ids']),
                                                                                                          site['max_slices'])
 
+       if not site['enabled']:
+           raise PLCInvalidArgument, "Site %s is disabled can cannot create slices" % (site['name'])
+        
         slice = Slice(self.api, slice_fields)
         slice['creator_person_id'] = self.caller['person_id']
         slice['site_id'] = site['site_id']
index d268298..8e728ef 100644 (file)
@@ -3,6 +3,7 @@ from PLC.Method import Method
 from PLC.Parameter import Parameter, Mixed
 from PLC.Nodes import Node, Nodes
 from PLC.PCUs import PCU, PCUs
+from PLC.Sites import Site, Sites
 from PLC.Auth import Auth
 
 class DeleteNodeFromPCU(Method):
index 871e241..06a99f3 100644 (file)
@@ -39,9 +39,6 @@ class DeleteSliceAttribute(Method):
             raise PLCInvalidArgument, "No such slice"
         slice = slices[0]
 
-        if slice['peer_id'] is not None:
-            raise PLCInvalidArgument, "Not a local slice"
-
         assert slice_attribute['slice_attribute_id'] in slice['slice_attribute_ids']
 
         if 'admin' not in self.caller['roles']:
index d308a4f..38dc8f0 100644 (file)
@@ -37,7 +37,16 @@ class GetNodes(Method):
         # Remove admin only fields
         if not isinstance(self.caller, Person) or \
            'admin' not in self.caller['roles']:
+           slice_ids = set()
+           if self.caller:
+               slice_ids.update(self.caller['slice_ids'])
             for node in nodes:
+               # if node has whitelist, make sure the user has a slice on the whitelist 
+               if 'slice_ids_whitelist' in node and \
+                  node['slice_ids_whitelist'] and \
+                  not slice_ids.intersection(node['slice_ids_whitelist']):
+                   nodes.remove(node)
+                   continue 
                 for field in ['boot_nonce', 'key', 'session', 'root_person_ids']:
                     if field in node:
                         del node[field]
index 434429d..890b65f 100644 (file)
@@ -64,6 +64,8 @@ def get_slivers(api, slice_filter, node = None):
 
         # Per-node sliver attributes take precedence over global
         # slice attributes, so set them first.
+        # Then comes nodegroup slice attributes
+       # Followed by global slice attributes
         sliver_attributes = []
 
         if node is not None:
@@ -72,13 +74,13 @@ def get_slivers(api, slice_filter, node = None):
                 attributes.append({'name': sliver_attribute['name'],
                                    'value': sliver_attribute['value']})
 
-       # set nodegroup slice attributes
-       for slice_attribute in filter(lambda a: a['nodegroup_id'] in node['nodegroup_ids'], slice_attributes):
-           # Do not set any nodegroup slice attributes for
-            # which there is at least one sliver attribute
-            # already set.
-           if slice_attribute['name'] not in slice_attributes:
-               attributes.append({'name': slice_attribute['name'],
+           # set nodegroup slice attributes
+           for slice_attribute in filter(lambda a: a['nodegroup_id'] in node['nodegroup_ids'], slice_attributes):
+               # Do not set any nodegroup slice attributes for
+                # which there is at least one sliver attribute
+                # already set.
+               if slice_attribute['name'] not in slice_attributes:
+                   attributes.append({'name': slice_attribute['name'],
                                   'value': slice_attribute['value']})
 
         for slice_attribute in filter(lambda a: a['node_id'] is None, slice_attributes):
@@ -202,8 +204,13 @@ class GetSlivers(Method):
         # Get system slices
         system_slice_attributes = SliceAttributes(self.api, {'name': 'system', 'value': '1'}).dict('slice_id')
         system_slice_ids = system_slice_attributes.keys()
+       
+       # Get nm-controller slices
+       controller_and_delegated_slices = Slices(self.api, {'instantiation': ['nm-controller', 'delegated']}, ['slice_id']).dict('slice_id')
+       controller_and_delegated_slice_ids = controller_and_delegated_slices.keys()
+       slice_ids = system_slice_ids + controller_and_delegated_slice_ids + node['slice_ids']
 
-        slivers = get_slivers(self.api, system_slice_ids + node['slice_ids'], node)
+       slivers = get_slivers(self.api, slice_ids, node)
 
        node.update_last_contact()
 
index 5332074..bf820da 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Thierry Parmentelat - INRIA
 # 
-# $Id$
+# $Id: RefreshPeer.py,v 1.24 2007/06/14 16:26:23 tmack Exp $
 
 import time
 
@@ -228,6 +228,11 @@ class RefreshPeer(Method):
 
         # Keyed on foreign person_id
         old_peer_persons = Persons(self.api, {'peer_id': peer_id}, columns).dict('peer_person_id')
+
+       # artificially attach the persons returned by GetPeerData to the new peer 
+       # this is because validate_email needs peer_id to be correct when checking for duplicates 
+       for person in peer_tables['Persons']: 
+           person['peer_id']=peer_id
         persons_at_peer = dict([(peer_person['person_id'], peer_person) \
                                 for peer_person in peer_tables['Persons']])
 
index f491ff9..3fc2599 100644 (file)
@@ -1 +1 @@
-methods = 'AddAddressType AddAddressTypeToAddress AddBootState AddConfFile AddConfFileToNodeGroup AddConfFileToNode AddInitScript AddKeyType AddMessage AddNetworkMethod AddNetworkType AddNodeGroup AddNodeNetwork AddNode AddNodeToNodeGroup AddNodeToPCU AddPCU AddPeer AddPersonKey AddPerson AddPersonToSite AddPersonToSlice AddRole AddRoleToPerson AddSiteAddress AddSite AddSliceAttribute AddSliceAttributeType AddSliceInstantiation AddSlice AddSliceToNodes AdmAddAddressType AdmAddNodeGroup AdmAddNodeNetwork AdmAddNode AdmAddNodeToNodeGroup AdmAddPersonKey AdmAddPerson AdmAddPersonToSite AdmAddSitePowerControlUnit AdmAddSite AdmAssociateNodeToPowerControlUnitPort AdmAuthCheck AdmDeleteAddressType AdmDeleteAllPersonKeys AdmDeleteNodeGroup AdmDeleteNodeNetwork AdmDeleteNode AdmDeletePersonKeys AdmDeletePerson AdmDeleteSitePowerControlUnit AdmDeleteSite AdmDisassociatePowerControlUnitPort AdmGenerateNodeConfFile AdmGetAllAddressTypes AdmGetAllKeyTypes AdmGetAllNodeNetworks AdmGetAllRoles AdmGetNodeGroupNodes AdmGetNodeGroups AdmGetNodes AdmGetPersonKeys AdmGetPersonRoles AdmGetPersonSites AdmGetPersons AdmGetPowerControlUnitNodes AdmGetPowerControlUnits AdmGetSiteNodes AdmGetSitePersons AdmGetSitePIs AdmGetSitePowerControlUnits AdmGetSites AdmGetSiteTechContacts AdmGrantRoleToPerson AdmIsPersonInRole AdmQueryConfFile AdmQueryNode AdmQueryPerson AdmQueryPowerControlUnit AdmQuerySite AdmRebootNode AdmRemoveNodeFromNodeGroup AdmRemovePersonFromSite AdmRevokeRoleFromPerson AdmSetPersonEnabled AdmSetPersonPrimarySite AdmUpdateNodeGroup AdmUpdateNodeNetwork AdmUpdateNode AdmUpdatePerson AdmUpdateSitePowerControlUnit AdmUpdateSite AnonAdmGetNodeGroups AuthCheck BlacklistKey BootCheckAuthentication BootGetNodeDetails BootNotifyOwners BootUpdateNode DeleteAddress DeleteAddressTypeFromAddress DeleteAddressType DeleteBootState DeleteConfFileFromNodeGroup DeleteConfFileFromNode DeleteConfFile DeleteInitScript DeleteKey DeleteKeyType DeleteMessage DeleteNetworkMethod DeleteNetworkType DeleteNodeFromNodeGroup DeleteNodeFromPCU DeleteNodeGroup DeleteNodeNetwork DeleteNode DeletePCU DeletePeer DeletePersonFromSite DeletePersonFromSlice DeletePerson DeleteRoleFromPerson DeleteRole DeleteSession DeleteSite DeleteSliceAttribute DeleteSliceAttributeType DeleteSliceFromNodes DeleteSliceInstantiation DeleteSlice GetAddresses GetAddressTypes GetBootStates GetConfFiles GetEventObjects GetEvents GetInitScripts GetKeys GetKeyTypes GetMessages GetNetworkMethods GetNetworkTypes GetNodeGroups GetNodeNetworks GetNodes GetPCUs GetPeerData GetPeerName GetPeers GetPersons GetRoles GetSession GetSites GetSliceAttributes GetSliceAttributeTypes GetSliceInstantiations GetSlicesMD5 GetSlices GetSliceTicket GetSlivers NotifyPersons RebootNode RefreshPeer ResetPassword SetPersonPrimarySite SliceCreate SliceDelete SliceExtendedInfo SliceGetTicket SliceInfo SliceListNames SliceListUserSlices SliceNodesAdd SliceNodesDel SliceNodesList SliceRenew SliceTicketGet SliceUpdate SliceUserAdd SliceUserDel SliceUsersList UpdateAddress UpdateAddressType UpdateConfFile UpdateInitScript UpdateKey UpdateMessage UpdateNodeGroup UpdateNodeNetwork UpdateNode UpdatePCU UpdatePeer UpdatePerson UpdateSite UpdateSliceAttribute UpdateSliceAttributeType UpdateSlice VerifyPerson  system.listMethods  system.methodHelp  system.methodSignature  system.multicall'.split()
+methods = 'AddAddressType AddAddressTypeToAddress AddBootState AddConfFile AddConfFileToNodeGroup AddConfFileToNode AddInitScript AddKeyType AddMessage AddNetworkMethod AddNetworkType AddNodeGroup AddNodeNetwork AddNode AddNodeToNodeGroup AddNodeToPCU AddPCU AddPeer AddPersonKey AddPerson AddPersonToSite AddPersonToSlice AddRole AddRoleToPerson AddSession AddSiteAddress AddSite AddSliceAttribute AddSliceAttributeType AddSliceInstantiation AddSlice AddSliceToNodes AddSliceToNodesWhitelist AdmAddAddressType AdmAddNodeGroup AdmAddNodeNetwork AdmAddNode AdmAddNodeToNodeGroup AdmAddPersonKey AdmAddPerson AdmAddPersonToSite AdmAddSitePowerControlUnit AdmAddSite AdmAssociateNodeToPowerControlUnitPort AdmAuthCheck AdmDeleteAddressType AdmDeleteAllPersonKeys AdmDeleteNodeGroup AdmDeleteNodeNetwork AdmDeleteNode AdmDeletePersonKeys AdmDeletePerson AdmDeleteSitePowerControlUnit AdmDeleteSite AdmDisassociatePowerControlUnitPort AdmGenerateNodeConfFile AdmGetAllAddressTypes AdmGetAllKeyTypes AdmGetAllNodeNetworks AdmGetAllRoles AdmGetNodeGroupNodes AdmGetNodeGroups AdmGetNodes AdmGetPersonKeys AdmGetPersonRoles AdmGetPersonSites AdmGetPersons AdmGetPowerControlUnitNodes AdmGetPowerControlUnits AdmGetSiteNodes AdmGetSitePersons AdmGetSitePIs AdmGetSitePowerControlUnits AdmGetSites AdmGetSiteTechContacts AdmGrantRoleToPerson AdmIsPersonInRole AdmQueryConfFile AdmQueryNode AdmQueryPerson AdmQueryPowerControlUnit AdmQuerySite AdmRebootNode AdmRemoveNodeFromNodeGroup AdmRemovePersonFromSite AdmRevokeRoleFromPerson AdmSetPersonEnabled AdmSetPersonPrimarySite AdmUpdateNodeGroup AdmUpdateNodeNetwork AdmUpdateNode AdmUpdatePerson AdmUpdateSitePowerControlUnit AdmUpdateSite AnonAdmGetNodeGroups AuthCheck BlacklistKey BootCheckAuthentication BootGetNodeDetails BootNotifyOwners BootUpdateNode DeleteAddress DeleteAddressTypeFromAddress DeleteAddressType DeleteBootState DeleteConfFileFromNodeGroup DeleteConfFileFromNode DeleteConfFile DeleteInitScript DeleteKey DeleteKeyType DeleteMessage DeleteNetworkMethod DeleteNetworkType DeleteNodeFromNodeGroup DeleteNodeFromPCU DeleteNodeGroup DeleteNodeNetwork DeleteNode DeletePCU DeletePeer DeletePersonFromSite DeletePersonFromSlice DeletePerson DeleteRoleFromPerson DeleteRole DeleteSession DeleteSite DeleteSliceAttribute DeleteSliceAttributeType DeleteSliceFromNodes DeleteSliceFromNodesWhitelist DeleteSliceInstantiation DeleteSlice GenerateNodeConfFile GetAddresses GetAddressTypes GetBootStates GetConfFiles GetEventObjects GetEvents GetInitScripts GetKeys GetKeyTypes GetMessages GetNetworkMethods GetNetworkTypes GetNodeGroups GetNodeNetworks GetNodes GetPCUs GetPeerData GetPeerName GetPeers GetPersons GetRoles GetSession GetSessions GetSites GetSliceAttributes GetSliceAttributeTypes GetSliceInstantiations GetSlicesMD5 GetSlices GetSliceTicket GetSlivers NotifyPersons RebootNode RefreshPeer ResetPassword SetPersonPrimarySite SliceCreate SliceDelete SliceExtendedInfo SliceGetTicket SliceInfo SliceListNames SliceListUserSlices SliceNodesAdd SliceNodesDel SliceNodesList SliceRenew SliceTicketGet SliceUpdate SliceUserAdd SliceUserDel SliceUsersList UpdateAddress UpdateAddressType UpdateConfFile UpdateInitScript UpdateKey UpdateMessage UpdateNodeGroup UpdateNodeNetwork UpdateNode UpdatePCU UpdatePeer UpdatePerson UpdateSite UpdateSliceAttribute UpdateSliceAttributeType UpdateSlice VerifyPerson  system.listMethods  system.methodHelp  system.methodSignature  system.multicall'.split()
index 8733f8d..a643f08 100644 (file)
@@ -4,7 +4,7 @@
 # Mark Huang <mlhuang@cs.princeton.edu>
 # Copyright (C) 2006 The Trustees of Princeton University
 #
-# $Id: NodeNetworks.py,v 1.15 2006/11/09 19:43:55 mlhuang Exp $
+# $Id: NodeNetworks.py,v 1.17 2007/05/11 20:22:55 tmack Exp $
 #
 
 from types import StringTypes
@@ -109,6 +109,15 @@ class NodeNetwork(Row):
     validate_dns1 = validate_ip
     validate_dns2 = validate_ip
 
+    def validate_bwlimit(self, bwlimit):
+       if not bwlimit:
+           return bwlimit
+
+       if bwlimit < 500000:
+           raise PLCInvalidArgument, 'Minimum bw is 500 kbs'
+
+       return bwlimit  
+
     def validate_hostname(self, hostname):
         # Optional
         if not hostname:
index 7954627..4596870 100644 (file)
@@ -4,7 +4,7 @@
 # Mark Huang <mlhuang@cs.princeton.edu>
 # Copyright (C) 2006 The Trustees of Princeton University
 #
-# $Id$
+# $Id: Nodes.py,v 1.34 2007/07/12 17:55:02 tmack Exp $
 #
 
 from types import StringTypes
@@ -17,6 +17,7 @@ from PLC.Debug import profile
 from PLC.Table import Row, Table
 from PLC.NodeNetworks import NodeNetwork, NodeNetworks
 from PLC.BootStates import BootStates
+#from PLC.Slices import Slice, Slices
 
 def valid_hostname(hostname):
     # 1. Each part begins and ends with a letter or number.
@@ -38,7 +39,7 @@ class Node(Row):
 
     table_name = 'nodes'
     primary_key = 'node_id'
-    join_tables = ['nodegroup_node', 'conf_file_node', 'nodenetworks', 'pcu_node', 'slice_node', 'slice_attribute', 'node_session', 'peer_node']
+    join_tables = ['nodegroup_node', 'conf_file_node', 'nodenetworks', 'pcu_node', 'slice_node', 'slice_attribute', 'node_session', 'peer_node', 'node_slice_whitelist']
     fields = {
         'node_id': Parameter(int, "Node identifier"),
         'hostname': Parameter(str, "Fully qualified hostname", max = 255),
@@ -58,6 +59,7 @@ class Node(Row):
         'conf_file_ids': Parameter([int], "List of configuration files specific to this node"),
         # 'root_person_ids': Parameter([int], "(Admin only) List of people who have root access to this node"),
         'slice_ids': Parameter([int], "List of slices on this node"),
+       'slice_ids_whitelist': Parameter([int], "List of slices allowed on this node"),
         'pcu_ids': Parameter([int], "List of PCUs that control this node"),
         'ports': Parameter([int], "List of PCU ports that this node is connected to"),
         'peer_id': Parameter(int, "Peer to which this node belongs", nullok = True),
@@ -95,6 +97,7 @@ class Node(Row):
 
     validate_date_created = Row.validate_timestamp
     validate_last_updated = Row.validate_timestamp
+    validate_last_contact = Row.validate_timestamp
 
     def update_last_contact(self, commit = True):
        """
@@ -107,7 +110,7 @@ class Node(Row):
        self.api.db.do("UPDATE %s SET last_contact = CURRENT_TIMESTAMP " % (self.table_name) + \
                       " where node_id = %d" % ( self['node_id']) )
        self.sync(commit)
-               
+
     def delete(self, commit = True):
         """
         Delete existing node.
index 7a2e635..8e483b3 100644 (file)
@@ -4,7 +4,7 @@
 # Mark Huang <mlhuang@cs.princeton.edu>
 # Copyright (C) 2006 The Trustees of Princeton University
 #
-# $Id$
+# $Id: Persons.py,v 1.37 2007/06/14 16:26:01 tmack Exp $
 #
 
 from types import StringTypes
@@ -100,8 +100,15 @@ class Person(Row):
         if len(domain) < 2:
             raise invalid_email
 
-        conflicts = Persons(self.api, [email])
-        for person in conflicts:
+               # check only against users on the same peer  
+       if 'peer_id' in self:
+            namespace_peer_id = self['peer_id']
+        else:
+            namespace_peer_id = None
+         
+       conflicts = Persons(self.api, {'email':email,'peer_id':namespace_peer_id}) 
+       
+       for person in conflicts:
             if 'person_id' not in self or self['person_id'] != person['person_id']:
                 raise PLCInvalidArgument, "E-mail address already in use"
 
index 597077a..9100ce1 100644 (file)
@@ -5,7 +5,7 @@
 # Mark Huang <mlhuang@cs.princeton.edu>
 # Copyright (C) 2006 The Trustees of Princeton University
 #
-# $Id$
+# $Id: PostgreSQL.py,v 1.15 2007/02/12 18:41:27 mlhuang Exp $
 #
 
 import psycopg2
index 3c1543e..b470c96 100644 (file)
@@ -1,9 +1,12 @@
+from types import StringTypes
 import random
 import base64
 import time
 
 from PLC.Faults import *
 from PLC.Parameter import Parameter
+from PLC.Filter import Filter
+from PLC.Debug import profile
 from PLC.Table import Row, Table
 from PLC.Persons import Person, Persons
 from PLC.Nodes import Node, Nodes
@@ -61,14 +64,22 @@ class Sessions(Table):
     Representation of row(s) from the session table in the database.
     """
 
-    def __init__(self, api, session_ids = None, expires = int(time.time())):
+    def __init__(self, api, session_filter = None, expires = int(time.time())):
        Table.__init__(self, api, Session)
 
         sql = "SELECT %s FROM view_sessions WHERE True" % \
               ", ".join(Session.fields)
 
-        if session_ids:
-            sql += " AND session_id IN (%s)" % ", ".join(map(api.db.quote, session_ids))
+       if session_filter is not None:
+           if isinstance(session_filter, (list, tuple, set)):
+               # Separate the list into integers and strings
+                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")
+           elif isinstance(session_filter, dict):
+               session_filter = Filter(Session.fields, session_filter)
+               sql += " AND (%s)" % session_filter.sql(api, "AND")
 
         if expires is not None:
             if expires >= 0:
index 6e4a77b..6782fff 100644 (file)
@@ -5,7 +5,7 @@
 # Mark Huang <mlhuang@cs.princeton.edu>
 # Copyright (C) 2005 The Trustees of Princeton University
 #
-# $Id$
+# $Id: Shell.py,v 1.5 2007/02/08 21:49:24 mlhuang Exp $
 #
 
 import os
index d3b6f78..d8962c4 100644 (file)
@@ -8,7 +8,7 @@ from PLC.Filter import Filter
 from PLC.Debug import profile
 from PLC.Table import Row, Table
 from PLC.SliceInstantiations import SliceInstantiation, SliceInstantiations
-from PLC.Nodes import Node, Nodes
+from PLC.Nodes import Node
 from PLC.Persons import Person, Persons
 
 class Slice(Row):
@@ -21,7 +21,7 @@ class Slice(Row):
 
     table_name = 'slices'
     primary_key = 'slice_id'
-    join_tables = ['slice_node', 'slice_person', 'slice_attribute', 'peer_slice']
+    join_tables = ['slice_node', 'slice_person', 'slice_attribute', 'peer_slice', 'node_slice_whitelist']
     fields = {
         'slice_id': Parameter(int, "Slice identifier"),
         'site_id': Parameter(int, "Identifier of the site to which this slice belongs"),
@@ -94,6 +94,9 @@ class Slice(Row):
     add_node = Row.add_object(Node, 'slice_node')
     remove_node = Row.remove_object(Node, 'slice_node')
 
+    add_to_node_whitelist = Row.add_object(Node, 'node_slice_whitelist')
+    delete_from_node_whitelist = Row.remove_object(Node, 'node_slice_whitelist')
+
     def sync(self, commit = True):
         """
         Add or update a slice.
index 0b8f86c..6701045 100644 (file)
@@ -74,6 +74,7 @@ rm -rf $RPM_BUILD_ROOT
 %{_bindir}/plcsh
 %{php_extension_dir}/xmlrpc.so
 %{_sysconfdir}/php.d/xmlrpc.ini
+%{_bindir}/refresh-peer.py
 
 %changelog
 * Fri Oct 27 2006 Mark Huang <mlhuang@CS.Princeton.EDU> - 
index 91f0ff4..7867e47 100755 (executable)
@@ -6,7 +6,7 @@
 # Mark Huang <mlhuang@cs.princeton.edu>
 # Copyright (C) 2006 The Trustees of Princeton University
 #
-# $Id$
+# $Id: DocBook.py,v 1.4 2007/02/19 18:02:39 mlhuang Exp $
 #
 
 import xml.dom.minidom
index f14d403..3bd82fa 100644 (file)
@@ -9,7 +9,7 @@
 --
 -- Copyright (C) 2006 The Trustees of Princeton University
 --
--- $Id$
+-- $Id: planetlab4.sql,v 1.79 2007/07/12 17:48:19 tmack Exp $
 --
 
 SET client_encoding = 'UNICODE';
@@ -295,6 +295,22 @@ array_accum(node_id) AS node_ids
 FROM nodes
 GROUP BY site_id;
 
+-- slice whitelist on nodes
+CREATE TABLE node_slice_whitelist (
+    node_id integer REFERENCES nodes NOT NULL, -- Node id of whitelist
+    slice_id integer REFERENCES slices NOT NULL, -- Slice id thats allowd on this node
+    PRIMARY KEY (node_id, slice_id)
+) WITH OIDS;
+CREATE INDEX node_slice_whitelist_node_id_idx ON node_slice_whitelist (node_id);
+CREATE INDEX node_slice_whitelist_slice_id_idx ON node_slice_whitelist (slice_id);
+
+-- Slices on each node
+CREATE VIEW node_slices_whitelist AS
+SELECT node_id, 
+array_accum(slice_id) AS slice_ids_whitelist
+FROM node_slice_whitelist
+GROUP BY node_id;
+
 --------------------------------------------------------------------------------
 -- Node groups
 --------------------------------------------------------------------------------
@@ -509,6 +525,7 @@ CREATE TABLE slice_instantiations (
 INSERT INTO slice_instantiations (instantiation) VALUES ('not-instantiated'); -- Placeholder slice
 INSERT INTO slice_instantiations (instantiation) VALUES ('plc-instantiated'); -- Instantiated by Node Manager
 INSERT INTO slice_instantiations (instantiation) VALUES ('delegated'); -- Manually instantiated
+INSERT INTO slice_instantiations (instantiation) VALUES ('nm-controller'); -- NM Controller
 
 -- Slices
 CREATE TABLE slices (
@@ -881,6 +898,7 @@ peer_node.peer_node_id,
 COALESCE((SELECT nodenetwork_ids FROM node_nodenetworks WHERE node_nodenetworks.node_id = nodes.node_id), '{}') AS nodenetwork_ids,
 COALESCE((SELECT nodegroup_ids FROM node_nodegroups WHERE node_nodegroups.node_id = nodes.node_id), '{}') AS nodegroup_ids,
 COALESCE((SELECT slice_ids FROM node_slices WHERE node_slices.node_id = nodes.node_id), '{}') AS slice_ids,
+COALESCE((SELECT slice_ids_whitelist FROM node_slices_whitelist WHERE node_slices_whitelist.node_id = nodes.node_id), '{}') AS slice_ids_whitelist,
 COALESCE((SELECT pcu_ids FROM node_pcus WHERE node_pcus.node_id = nodes.node_id), '{}') AS pcu_ids,
 COALESCE((SELECT ports FROM node_pcus WHERE node_pcus.node_id = nodes.node_id), '{}') AS ports,
 COALESCE((SELECT conf_file_ids FROM node_conf_files WHERE node_conf_files.node_id = nodes.node_id), '{}') AS conf_file_ids,
diff --git a/plcsh b/plcsh
index 10944b0..54fc0b9 100755 (executable)
--- a/plcsh
+++ b/plcsh
@@ -5,7 +5,7 @@
 # Mark Huang <mlhuang@cs.princeton.edu>
 # Copyright (C) 2005 The Trustees of Princeton University
 #
-# $Id$
+# $Id: plcsh,v 1.6 2007/02/08 21:49:41 mlhuang Exp $
 #
 
 import os
index ae38841..484d257 100644 (file)
@@ -1,5 +1,5 @@
 #!/usr/bin/env plcsh
-# $Id: refresh-peer.py 154 2007-03-28 14:15:55Z thierry $
+# $Id: refresh-peer.py,v 1.1 2007/07/02 19:27:43 tmack Exp $
 
 import sys,os,time