# Mark Huang <mlhuang@cs.princeton.edu>
#
# Copyright (C) 2004-2006 The Trustees of Princeton University
-# $Id: API.py,v 1.8 2007/01/05 16:09:09 tmack Exp $
+# $Id: API.py 5574 2007-10-25 20:33:17Z thierry $
#
import sys
# Mark Huang <mlhuang@cs.princeton.edu>
# Copyright (C) 2006 The Trustees of Princeton University
#
-# $Id: AddressTypes.py,v 1.8 2006/11/09 03:07:42 mlhuang Exp $
+# $Id: AddressTypes.py 5574 2007-10-25 20:33:17Z thierry $
#
from types import StringTypes
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)
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)
# Mark Huang <mlhuang@cs.princeton.edu>
# Copyright (C) 2006 The Trustees of Princeton University
#
-# $Id: Auth.py,v 1.18 2007/03/08 22:22:21 tmack Exp $
+# $Id: Auth.py 5574 2007-10-25 20:33:17Z thierry $
#
import crypt
# Mark Huang <mlhuang@cs.princeton.edu>
# Copyright (C) 2007 The Trustees of Princeton University
#
-# $Id$
+# $Id: Boot.py 5574 2007-10-25 20:33:17Z thierry $
#
from PLC.Faults import *
# Mark Huang <mlhuang@cs.princeton.edu>
# Copyright (C) 2006 The Trustees of Princeton University
#
-# $Id: BootStates.py,v 1.6 2006/10/24 20:02:22 mlhuang Exp $
+# $Id: BootStates.py 5574 2007-10-25 20:33:17Z thierry $
#
from PLC.Faults import *
# Mark Huang <mlhuang@cs.princeton.edu>
# Copyright (C) 2006 The Trustees of Princeton University
#
-# $Id: ConfFiles.py,v 1.9 2006/11/09 03:07:42 mlhuang Exp $
+# $Id: ConfFiles.py 5574 2007-10-25 20:33:17Z thierry $
#
from PLC.Faults import *
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)
# Mark Huang <mlhuang@cs.princeton.edu>
# Copyright (C) 2004-2006 The Trustees of Princeton University
#
-# $Id: Config.py,v 1.2 2006/09/06 19:15:59 mlhuang Exp $
+# $Id: Config.py 5574 2007-10-25 20:33:17Z thierry $
#
import os
# Tony Mack <tmack@cs.princeton.edu>
# Copyright (C) 2006 The Trustees of Princeton University
#
-# $Id: EventObjects.py,v 1.4 2007/09/12 17:52:27 tmack Exp $
+# $Id: EventObjects.py 5574 2007-10-25 20:33:17Z thierry $
#
from PLC.Faults import *
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)
# Tony Mack <tmack@cs.princeton.edu>
# Copyright (C) 2006 The Trustees of Princeton University
#
-# $Id: Events.py,v 1.13 2007/04/11 20:29:10 tmack Exp $
+# $Id: Events.py 5574 2007-10-25 20:33:17Z thierry $
#
from PLC.Faults import *
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)
# Mark Huang <mlhuang@cs.princeton.edu>
#
# Copyright (C) 2004-2006 The Trustees of Princeton University
-# $Id: Faults.py,v 1.2 2006/12/07 09:13:55 thierry Exp $
+# $Id: Faults.py 5574 2007-10-25 20:33:17Z thierry $
#
import xmlrpclib
"""
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"):
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
modifiers={'~' : False,
'<' : False, '>' : False,
'[' : False, ']' : False,
+ '-' : False,
}
for char in modifiers.keys():
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)
# Mark Huang <mlhuang@cs.princeton.edu>
# Copyright (C) 2006 The Trustees of Princeton University
#
-# $Id: GPG.py,v 1.6 2007/02/07 04:35:19 mlhuang Exp $
+# $Id: GPG.py 5574 2007-10-25 20:33:17Z thierry $
#
import os
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)
# Mark Huang <mlhuang@cs.princeton.edu>
# Copyright (C) 2006 The Trustees of Princeton University
#
-# $Id: KeyTypes.py,v 1.3 2006/10/24 20:02:22 mlhuang Exp $
+# $Id: KeyTypes.py 5574 2007-10-25 20:33:17Z thierry $
#
from PLC.Faults import *
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)
# Tony Mack <tmack@cs.princeton.edu>
# Copyright (C) 2006 The Trustees of Princeton University
#
-# $Id: Messages.py,v 1.4 2006/11/16 17:03:36 mlhuang Exp $
+# $Id: Messages.py 5574 2007-10-25 20:33:17Z thierry $
#
from PLC.Parameter import Parameter
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)
# Mark Huang <mlhuang@cs.princeton.edu>
# Copyright (C) 2006 The Trustees of Princeton University
#
-# $Id: Method.py,v 1.30 2007/09/12 17:52:27 tmack Exp $
+# $Id: Method.py 5574 2007-10-25 20:33:17Z thierry $
#
import xmlrpclib
# Mark Huang <mlhuang@cs.princeton.edu>
# Copyright (C) 2006 The Trustees of Princeton University
#
-# $Id: NetworkMethods.py,v 1.3 2006/10/24 20:02:22 mlhuang Exp $
+# $Id: NetworkMethods.py 5574 2007-10-25 20:33:17Z thierry $
#
from PLC.Faults import *
# Mark Huang <mlhuang@cs.princeton.edu>
# Copyright (C) 2006 The Trustees of Princeton University
#
-# $Id: NetworkTypes.py,v 1.3 2006/10/24 20:02:22 mlhuang Exp $
+# $Id: NetworkTypes.py 5574 2007-10-25 20:33:17Z thierry $
#
from PLC.Faults import *
# Mark Huang <mlhuang@cs.princeton.edu>
# Copyright (C) 2006 The Trustees of Princeton University
#
-# $Id: NodeGroups.py,v 1.18 2006/11/09 03:07:42 mlhuang Exp $
+# $Id: NodeGroups.py 5666 2007-11-06 21:52:21Z tmack $
#
from types import StringTypes
from PLC.Faults import *
-from PLC.Parameter import Parameter
+from PLC.Parameter import Parameter, Mixed
from PLC.Filter import Filter
from PLC.Debug import profile
from PLC.Table import Row, Table
'node_ids': Parameter([int], "List of nodes in this node group"),
'conf_file_ids': Parameter([int], "List of configuration files specific to this node group"),
}
+ related_fields = {
+ 'conf_files': [Parameter(int, "ConfFile identifier")],
+ 'nodes': [Mixed(Parameter(int, "Node identifier"),
+ Parameter(str, "Fully qualified hostname"))]
+ }
def validate_name(self, name):
# Make sure name is not blank
# Make sure node group does not alredy exist
conflicts = NodeGroups(self.api, [name])
- for nodegroup_id in conflicts:
- if 'nodegroup_id' not in self or self['nodegroup_id'] != nodegroup_id:
+ for nodegroup in conflicts:
+ if 'nodegroup_id' not in self or self['nodegroup_id'] != nodegroup['nodegroup_id']:
raise PLCInvalidArgument, "Node group name already in use"
return name
self['node_ids'].remove(node_id)
node['nodegroup_ids'].remove(nodegroup_id)
+ def associate_nodes(self, auth, field, value):
+ """
+ Adds nodes found in value list to this nodegroup (using AddNodeToNodeGroup).
+ Deletes nodes not found in value list from this slice (using DeleteNodeFromNodeGroup).
+ """
+
+ assert 'node_ids' in self
+ assert 'nodegroup_id' in self
+ assert isinstance(value, list)
+
+ (node_ids, hostnames) = self.separate_types(value)[0:2]
+
+ # Translate hostnames into node_ids
+ if hostnames:
+ nodes = Nodes(self.api, hostnames, ['node_id']).dict('node_id')
+ node_ids += nodes.keys()
+
+ # Add new ids, remove stale ids
+ if self['node_ids'] != node_ids:
+ from PLC.Methods.AddNodeToNodeGroup import AddNodeToNodeGroup
+ from PLC.Methods.DeleteNodeFromNodeGroup import DeleteNodeFromNodeGroup
+ new_nodes = set(node_ids).difference(self['node_ids'])
+ stale_nodes = set(self['node_ids']).difference(node_ids)
+
+ for new_node in new_nodes:
+ AddNodeToNodeGroup.__call__(AddNodeToNodeGroup(self.api), auth, new_node, self['nodegroup_id'])
+ for stale_node in stale_nodes:
+ DeleteNodeFromNodeGroup.__call__(DeleteNodeFromNodeGroup(self.api), auth, stale_node, self['nodegroup_id'])
+
+ def associate_conf_files(self, auth, field, value):
+ """
+ Add conf_files found in value list (AddConfFileToNodeGroup)
+ Delets conf_files not found in value list (DeleteConfFileFromNodeGroup)
+ """
+
+ assert 'conf_file_ids' in self
+ assert 'nodegroup_id' in self
+ assert isinstance(value, list)
+
+ conf_file_ids = self.separate_types(value)[0]
+
+ if self['conf_file_ids'] != conf_file_ids:
+ from PLC.Methods.AddConfFileToNodeGroup import AddConfFileToNodeGroup
+ from PLC.Methods.DeleteConfFileFromNodeGroup import DeleteConfFileFromNodeGroup
+ new_conf_files = set(conf_file_ids).difference(self['conf_file_ids'])
+ stale_conf_files = set(self['conf_file_ids']).difference(conf_file_ids)
+
+ for new_conf_file in new_conf_files:
+ AddConfFileToNodeGroup.__call__(AddConfFileToNodeGroup(self.api), auth, new_conf_file, self['nodegroup_id'])
+ for stale_conf_file in stale_conf_files:
+ DeleteConfFileFromNodeGroup.__call__(DeleteConfFileFromNodeGroup(self.api), auth, stale_conf_file, self['nodegroup_id'])
+
+
class NodeGroups(Table):
"""
Representation of row(s) from the nodegroups table in the
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)
#
# Thierry Parmentelat - INRIA
#
-# $Revision: 1.1 $
+# $Revision: 5574 $
#
from types import StringTypes
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
#
# Thierry Parmentelat - INRIA
#
-# $Revision: 1.1 $
+# $Revision: 5574 $
#
from PLC.Faults import *
from PLC.Parameter import Parameter
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)
# Mark Huang <mlhuang@cs.princeton.edu>
# Copyright (C) 2006 The Trustees of Princeton University
#
-# $Id: NodeNetworks.py,v 1.18 2007/09/12 17:52:27 tmack Exp $
+# $Id: NodeNetworks.py 5574 2007-10-25 20:33:17Z thierry $
#
from types import StringTypes
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)
# Mark Huang <mlhuang@cs.princeton.edu>
# Copyright (C) 2006 The Trustees of Princeton University
#
-# $Id: Nodes.py 800 2007-08-30 03:49:35Z thierry $
+# $Id: Nodes.py 5654 2007-11-06 03:43:55Z tmack $
#
from types import StringTypes
import re
from PLC.Faults import *
-from PLC.Parameter import Parameter
+from PLC.Parameter import Parameter, Mixed
from PLC.Filter import Filter
from PLC.Debug import profile
from PLC.Table import Row, Table
'peer_id': Parameter(int, "Peer to which this node belongs", nullok = True),
'peer_node_id': Parameter(int, "Foreign node identifier at peer", nullok = True),
}
-
+ related_fields = {
+ 'nodenetworks': [Mixed(Parameter(int, "NodeNetwork identifier"),
+ Filter(NodeNetwork.fields))],
+ 'nodegroups': [Mixed(Parameter(int, "NodeGroup identifier"),
+ Parameter(str, "NodeGroup name"))],
+ 'conf_files': [Parameter(int, "ConfFile identifier")],
+ 'slices': [Mixed(Parameter(int, "Slice identifier"),
+ Parameter(str, "Slice name"))],
+ 'slices_whitelist': [Mixed(Parameter(int, "Slice identifier"),
+ Parameter(str, "Slice name"))]
+ }
# for Cache
class_key = 'hostname'
foreign_fields = ['boot_state','model','version']
" where node_id = %d" % (self['node_id']) )
self.sync(commit)
+ def associate_nodenetworks(self, auth, field, value):
+ """
+ Delete nodenetworks not found in value list (using DeleteNodeNetwor)k
+ Add nodenetworks found in value list (using AddNodeNetwork)
+ Updates nodenetworks found w/ nodenetwork_id in value list (using UpdateNodeNetwork)
+ """
+
+ assert 'nodenetworkp_ids' in self
+ assert 'node_id' in self
+ assert isinstance(value, list)
+
+ (nodenetwork_ids, blank, nodenetworks) = self.separate_types(value)
+
+ if self['nodenetwork_ids'] != nodenetwork_ids:
+ from PLC.Methods.DeleteNodeNetwork import DeleteNodeNetwork
+
+ stale_nodenetworks = set(self['nodenetwork_ids']).difference(nodenetwork_ids)
+
+ for stale_nodenetwork in stale_nodenetworks:
+ DeleteNodeNetwork.__call__(DeleteNodeNetwork(self.api), auth, stale_nodenetwork['nodenetwork_id'])
+
+ def associate_nodegroups(self, auth, field, value):
+ """
+ Add node to nodegroups found in value list (AddNodeToNodegroup)
+ Delete node from nodegroup not found in value list (DeleteNodeFromNodegroup)
+ """
+
+ from PLC.NodeGroups import NodeGroups
+
+ assert 'nodegroup_ids' in self
+ assert 'node_id' in self
+ assert isinstance(value, list)
+
+ (nodegroup_ids, nodegroup_names) = self.separate_types(value)[0:2]
+
+ if nodegroup_names:
+ nodegroups = NodeGroups(self.api, nodegroup_names, ['nodegroup_id']).dict('nodegroup_id')
+ nodegroup_ids += nodegroups.keys()
+
+ if self['nodegroup_ids'] != nodegroup_ids:
+ from PLC.Methods.AddNodeToNodeGroup import AddNodeToNodeGroup
+ from PLC.Methods.DeleteNodeFromNodeGroup import DeleteNodeFromNodeGroup
+
+ new_nodegroups = set(nodegroup_ids).difference(self['nodegroup_ids'])
+ stale_nodegroups = set(self['nodegroup_ids']).difference(nodegroup_ids)
+
+ for new_nodegroup in new_nodegroups:
+ AddNodeToNodeGroup.__call__(AddNodeToNodeGroup(self.api), auth, self['node_id'], new_nodegroup)
+ for stale_nodegroup in stale_nodegroups:
+ DeleteNodeFromNodeGroup.__call__(DeleteNodeFromNodeGroup(self.api), auth, self['node_id'], stale_nodegroup)
+
+
+
+ def associate_conf_files(self, auth, field, value):
+ """
+ Add conf_files found in value list (AddConfFileToNode)
+ Delets conf_files not found in value list (DeleteConfFileFromNode)
+ """
+
+ assert 'conf_file_ids' in self
+ assert 'node_id' in self
+ assert isinstance(value, list)
+
+ conf_file_ids = self.separate_types(value)[0]
+
+ if self['conf_file_ids'] != conf_file_ids:
+ from PLC.Methods.AddConfFileToNode import AddConfFileToNode
+ from PLC.Methods.DeleteConfFileFromNode import DeleteConfFileFromNode
+ new_conf_files = set(conf_file_ids).difference(self['conf_file_ids'])
+ stale_conf_files = set(self['conf_file_ids']).difference(conf_file_ids)
+
+ for new_conf_file in new_conf_files:
+ AddConfFileToNode.__call__(AddConfFileToNode(self.api), auth, new_conf_file, self['node_id'])
+ for stale_conf_file in stale_conf_files:
+ DeleteConfFileFromNode.__call__(DeleteConfFileFromNode(self.api), auth, stale_conf_file, self['node_id'])
+
+
+ def associate_slices(self, auth, field, value):
+ """
+ Add slices found in value list to (AddSliceToNode)
+ Delete slices not found in value list (DeleteSliceFromNode)
+ """
+
+ from PLC.Slices import Slices
+
+ assert 'slice_ids' in self
+ assert 'node_id' in self
+ assert isinstance(value, list)
+
+ (slice_ids, slice_names) = self.separate_types(value)[0:2]
+
+ if slice_names:
+ slices = Slices(self.api, slice_names, ['slice_id']).dict('slice_id')
+ slice_ids += slices.keys()
+
+ if self['slice_ids'] != slice_ids:
+ from PLC.Methods.AddSliceToNodes import AddSliceToNodes
+ from PLC.Methods.DeleteSliceFromNodes import DeleteSliceFromNodes
+ new_slices = set(slice_ids).difference(self['slice_ids'])
+ stale_slices = set(self['slice_ids']).difference(slice_ids)
+
+ for new_slice in new_slices:
+ AddSliceToNodes.__call__(AddSliceToNodes(self.api), auth, new_slice, [self['node_id']])
+ for stale_slice in stale_slices:
+ DeleteSliceFromNodes.__call__(DeleteSliceFromNodes(self.api), auth, stale_slice, [self['node_id']])
+
+ def associate_slices_whitelist(self, auth, field, value):
+ """
+ Add slices found in value list to whitelist (AddSliceToNodesWhitelist)
+ Delete slices not found in value list from whitelist (DeleteSliceFromNodesWhitelist)
+ """
+
+ from PLC.Slices import Slices
+
+ assert 'slice_ids_whitelist' in self
+ assert 'node_id' in self
+ assert isinstance(value, list)
+
+ (slice_ids, slice_names) = self.separate_types(value)[0:2]
+
+ if slice_names:
+ slices = Slices(self.api, slice_names, ['slice_id']).dict('slice_id')
+ slice_ids += slices.keys()
+
+ if self['slice_ids_whitelist'] != slice_ids:
+ from PLC.Methods.AddSliceToNodesWhitelist import AddSliceToNodesWhitelist
+ from PLC.Methods.DeleteSliceFromNodesWhitelist import DeleteSliceFromNodesWhitelist
+ new_slices = set(slice_ids).difference(self['slice_ids_whitelist'])
+ stale_slices = set(self['slice_ids_whitelist']).difference(slice_ids)
+
+ for new_slice in new_slices:
+ AddSliceToNodesWhitelist.__call__(AddSliceToNodesWhitelist(self.api), auth, new_slice, [self['node_id']])
+ for stale_slice in stale_slices:
+ DeleteSliceFromNodesWhitelist.__call__(DeleteSliceFromNodesWhitelist(self.api), auth, stale_slice, [self['node_id']])
+
+
def delete(self, commit = True):
"""
Delete existing node.
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
--- /dev/null
+#
+# Functions for interacting with the pcu_type_port table in the database
+#
+# Mark Huang <mlhuang@cs.princeton.edu>
+# Copyright (C) 2006 The Trustees of Princeton University
+#
+# $Id:
+#
+
+from PLC.Faults import *
+from PLC.Parameter import Parameter
+from PLC.Table import Row, Table
+from PLC.Filter import Filter
+
+class PCUProtocolType(Row):
+ """
+ Representation of a row in the pcu_protocol_type table. To use,
+ instantiate with a dict of values.
+ """
+
+ table_name = 'pcu_protocol_type'
+ primary_key = 'pcu_protocol_type_id'
+ join_tables = []
+ fields = {
+ 'pcu_protocol_type_id': Parameter(int, "PCU protocol type identifier"),
+ 'pcu_type_id': Parameter(int, "PCU type identifier"),
+ 'port': Parameter(int, "PCU port", max = 254),
+ 'protocol': Parameter(str, "Protocol", max = 254),
+ 'supported': Parameter(bool, "Is the port/protocol supported by PLC")
+ }
+
+ def validate_port(self, port):
+ # make sure port is not blank
+
+ if not port:
+ raise PLCInvalidArgument, "Port must be specified"
+
+ return port
+
+ def validate_protocol(self, protocol):
+ # make sure port is not blank
+ if not len(protocol):
+ raise PLCInvalidArgument, "protocol must be specified"
+
+ return protocol
+
+class PCUProtocolTypes(Table):
+ """
+ Representation of the pcu_protocol_types table in the database.
+ """
+
+ def __init__(self, api, protocol_type_filter = None, columns = None):
+ Table.__init__(self, api, PCUProtocolType, columns)
+
+ sql = "SELECT %s FROM pcu_protocol_type WHERE True" % \
+ ", ".join(self.columns)
+
+ if protocol_type_filter is not None:
+ if isinstance(protocol_type_filter, (list, tuple, set)):
+ # Separate the list into integers and strings
+ ints = filter(lambda x: isinstance(x, (int, long)), protocol_type_filter)
+ protocol_type_filter = Filter(PCUProtocolType.fields, {'pcu_protocol_type_id': ints})
+ sql += " AND (%s) %s" % protocol_type_filter.sql(api, "OR")
+ elif isinstance(protocol_type_filter, dict):
+ protocol_type_filter = Filter(PCUProtocolType.fields, protocol_type_filter)
+ sql += " AND (%s) %s" % protocol_type_filter.sql(api, "AND")
+ elif isinstance (protocol_type_filter, int):
+ protocol_type_filter = Filter(PCUProtocolType.fields, {'pcu_protocol_type_id':[protocol_type_filter]})
+
+ sql += " AND (%s) %s" % protocol_type_filter.sql(api, "AND")
+ else:
+ raise PLCInvalidArgument, "Wrong pcu_protocol_type filter %r"%protocol_type_filter
+
+
+ self.selectall(sql)
--- /dev/null
+#
+# Functions for interacting with the pcu_types table in the database
+#
+# Mark Huang <mlhuang@cs.princeton.edu>
+# Copyright (C) 2006 The Trustees of Princeton University
+#
+# $Id:
+#
+from types import StringTypes
+
+from PLC.Faults import *
+from PLC.Parameter import Parameter
+from PLC.Table import Row, Table
+from PLC.Filter import Filter
+
+class PCUType(Row):
+ """
+ Representation of a row in the pcu_types table. To use,
+ instantiate with a dict of values.
+ """
+
+ table_name = 'pcu_types'
+ primary_key = 'pcu_type_id'
+ join_tables = ['pcu_port_type']
+ fields = {
+ 'pcu_type_id': Parameter(int, "PCU Type Identifier"),
+ 'model': Parameter(str, "PCU model", max = 254),
+ 'name': Parameter(str, "PCU full name", max = 254),
+ 'pcu_protocol_type_ids': Parameter([int], "PCU Protocol Type Identifiers"),
+ 'pcu_protocol_types': Parameter([dict], "PCU Protocol Type List")
+ }
+
+ def validate_model(self, model):
+ # Make sure name is not blank
+ if not len(model):
+ raise PLCInvalidArgument, "Model must be specified"
+
+ # Make sure boot state does not alredy exist
+ conflicts = PCUTypes(self.api, [model])
+ for pcu_type in conflicts:
+ if 'pcu_type_id' not in self or self['pcu_type_id'] != pcu_type['pcu_type_id']:
+ raise PLCInvalidArgument, "Model already in use"
+
+ return model
+
+class PCUTypes(Table):
+ """
+ Representation of the pcu_types table in the database.
+ """
+
+ def __init__(self, api, pcu_type_filter = None, columns = None):
+
+ # Remove pcu_protocol_types from query since its not really a field
+ # in the db. We will add it later
+ if columns == None:
+ columns = PCUType.fields.keys()
+ if 'pcu_protocol_types' in columns:
+ removed_fields = ['pcu_protocol_types']
+ columns.remove('pcu_protocol_types')
+ else:
+ removed_fields = []
+
+ Table.__init__(self, api, PCUType, columns)
+
+ sql = "SELECT %s FROM view_pcu_types WHERE True" % \
+ ", ".join(self.columns)
+
+ if pcu_type_filter is not None:
+ if isinstance(pcu_type_filter, (list, tuple, set)):
+ # Separate the list into integers and strings
+ ints = filter(lambda x: isinstance(x, (int, long)), pcu_type_filter)
+ strs = filter(lambda x: isinstance(x, StringTypes), pcu_type_filter)
+ pcu_type_filter = Filter(PCUType.fields, {'pcu_type_id': ints, 'model': strs})
+ sql += " AND (%s) %s" % pcu_type_filter.sql(api, "OR")
+ elif isinstance(pcu_type_filter, dict):
+ pcu_type_filter = Filter(PCUType.fields, pcu_type_filter)
+ sql += " AND (%s) %s" % pcu_type_filter.sql(api, "AND")
+ elif isinstance (pcu_type_filter, StringTypes):
+ pcu_type_filter = Filter(PCUType.fields, {'model':[pcu_type_filter]})
+ sql += " AND (%s) %s" % pcu_type_filter.sql(api, "AND")
+ elif isinstance (pcu_type_filter, int):
+ pcu_type_filter = Filter(PCUType.fields, {'pcu_type_id':[pcu_type_filter]})
+ sql += " AND (%s) %s" % pcu_type_filter.sql(api, "AND")
+ else:
+ raise PLCInvalidArgument, "Wrong pcu_type filter %r"%pcu_type_filter
+
+
+ self.selectall(sql)
+
+ # return a list of protocol type objects for each port type
+ if 'pcu_protocol_types' in removed_fields:
+ from PLC.PCUProtocolTypes import PCUProtocolTypes
+ protocol_type_ids = set()
+ for pcu_type in self:
+ protocol_type_ids.update(pcu_type['pcu_protocol_type_ids'])
+
+ protocol_return_fields = ['pcu_protocol_type_id', 'port', 'protocol', 'supported']
+ all_protocol_types = PCUProtocolTypes(self.api, list(protocol_type_ids), \
+ protocol_return_fields).dict('pcu_protocol_type_id')
+
+ for pcu_type in self:
+ pcu_type['pcu_protocol_types'] = []
+ for protocol_type_id in pcu_type['pcu_protocol_type_ids']:
+ pcu_type['pcu_protocol_types'].append(all_protocol_types[protocol_type_id])
# Mark Huang <mlhuang@cs.princeton.edu>
# Copyright (C) 2006 The Trustees of Princeton University
#
-# $Id: PCUs.py,v 1.9 2006/11/09 03:07:42 mlhuang Exp $
+# $Id: PCUs.py 5574 2007-10-25 20:33:17Z thierry $
#
from PLC.Faults import *
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)
# Mark Huang <mlhuang@cs.princeton.edu>
# Copyright (C) 2006 The Trustees of Princeton University
#
-# $Id: Parameter.py,v 1.6 2006/11/08 22:10:00 mlhuang Exp $
+# $Id: Parameter.py 5574 2007-10-25 20:33:17Z thierry $
#
from types import *
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)
# Mark Huang <mlhuang@cs.princeton.edu>
# Copyright (C) 2006 The Trustees of Princeton University
#
-# $Id: Persons.py,v 1.39 2007/10/01 20:51:46 tmack Exp $
+# $Id: Persons.py 5652 2007-11-06 03:42:57Z tmack $
#
from types import StringTypes
from PLC.Faults import *
from PLC.Debug import log
-from PLC.Parameter import Parameter
+from PLC.Parameter import Parameter, Mixed
from PLC.Filter import Filter
from PLC.Table import Row, Table
from PLC.Roles import Role, Roles
'peer_id': Parameter(int, "Peer to which this user belongs", nullok = True),
'peer_person_id': Parameter(int, "Foreign user identifier at peer", nullok = True),
}
+ related_fields = {
+ 'roles': [Mixed(Parameter(int, "Role identifier"),
+ Parameter(str, "Role name"))],
+ 'sites': [Mixed(Parameter(int, "Site identifier"),
+ Parameter(str, "Site name"))],
+ 'keys': [Mixed(Parameter(int, "Key identifier"),
+ Filter(Key.fields))],
+ 'slices': [Mixed(Parameter(int, "Slice identifier"),
+ Parameter(str, "Slice name"))]
+ }
+
+
# for Cache
class_key = 'email'
" where person_id = %d" % (self['person_id']) )
self.sync(commit)
+ def associate_roles(self, auth, field, value):
+ """
+ Adds roles found in value list to this person (using AddRoleToPerson).
+ Deletes roles not found in value list from this person (using DeleteRoleFromPerson).
+ """
+
+ assert 'role_ids' in self
+ assert 'person_id' in self
+ assert isinstance(value, list)
+
+ (role_ids, roles_names) = self.separate_types(value)[0:2]
+
+ # Translate roles into role_ids
+ if roles_names:
+ roles = Roles(self.api, role_names, ['role_id']).dict('role_id')
+ role_ids += roles.keys()
+
+ # Add new ids, remove stale ids
+ if self['role_ids'] != role_ids:
+ from PLC.Methods.AddRoleToPerson import AddRoleToPerson
+ from PLC.Methods.DeleteRoleFromPerson import DeleteRoleFromPerson
+ new_roles = set(role_ids).difference(self['role_ids'])
+ stale_roles = set(self['role_ids']).difference(role_ids)
+
+ for new_role in new_roles:
+ AddRoleToPerson.__call__(AddRoleToPerson(self.api), auth, new_role, self['person_id'])
+ for stale_role in stale_roles:
+ DeleteRoleFromPerson.__call__(DeleteRoleFromPerson(self.api), auth, stale_role, self['person_id'])
+
+
+ def associate_sites(self, auth, field, value):
+ """
+ Adds person to sites found in value list (using AddPersonToSite).
+ Deletes person from site not found in value list (using DeletePersonFromSite).
+ """
+
+ from PLC.Sites import Sites
+
+ assert 'site_ids' in self
+ assert 'person_id' in self
+ assert isinstance(value, list)
+
+ (site_ids, site_names) = self.separate_types(value)[0:2]
+
+ # Translate roles into role_ids
+ if site_names:
+ sites = Sites(self.api, site_names, ['site_id']).dict('site_id')
+ site_ids += sites.keys()
+
+ # Add new ids, remove stale ids
+ if self['site_ids'] != site_ids:
+ from PLC.Methods.AddPersonToSite import AddPersonToSite
+ from PLC.Methods.DeletePersonFromSite import DeletePersonFromSite
+ new_sites = set(site_ids).difference(self['site_ids'])
+ stale_sites = set(self['site_ids']).difference(site_ids)
+
+ for new_site in new_sites:
+ AddPersonToSite.__call__(AddPersonToSite(self.api), auth, self['person_id'], new_site)
+ for stale_site in stale_sites:
+ DeletePersonFromSite.__call__(DeletePersonFromSite(self.api), auth, self['person_id'], stale_site)
+
+
+ def associate_keys(self, auth, field, value):
+ """
+ Deletes key_ids not found in value list (using DeleteKey).
+ Adds key if key_fields w/o key_id is found (using AddPersonKey).
+ Updates key if key_fields w/ key_id is found (using UpdateKey).
+ """
+ assert 'key_ids' in self
+ assert 'person_id' in self
+ assert isinstance(value, list)
+
+ (key_ids, blank, keys) = self.separate_types(value)
+
+ if self['key_ids'] != key_ids:
+ from PLC.Methods.DeleteKey import DeleteKey
+ stale_keys = set(self['key_ids']).difference(key_ids)
+
+ for stale_key in stale_keys:
+ DeleteKey.__call__(DeleteKey(self.api), auth, stale_key)
+
+ if keys:
+ from PLC.Methods.AddPersonKey import AddPersonKey
+ from PLC.Methods.UpdateKey import UpdateKey
+ updated_keys = filter(lambda key: 'key_id' in key, keys)
+ added_keys = filter(lambda key: 'key_id' not in key, keys)
+
+ for key in added_keys:
+ AddPersonKey.__call__(AddPersonKey(self.api), auth, self['person_id'], key)
+ for key in updated_keys:
+ key_id = key.pop('key_id')
+ UpdateKey.__call__(UpdateKey(self.api), auth, key_id, key)
+
+
+ def associate_slices(self, auth, field, value):
+ """
+ Adds person to slices found in value list (using AddPersonToSlice).
+ Deletes person from slices found in value list (using DeletePersonFromSlice).
+ """
+
+ from PLC.Slices import Slices
+
+ assert 'slice_ids' in self
+ assert 'person_id' in self
+ assert isinstance(value, list)
+
+ (slice_ids, slice_names) = self.separate_types(value)[0:2]
+
+ # Translate roles into role_ids
+ if slice_names:
+ slices = Slices(self.api, slice_names, ['slice_id']).dict('slice_id')
+ slice_ids += slices.keys()
+
+ # Add new ids, remove stale ids
+ if self['slice_ids'] != slice_ids:
+ from PLC.Methods.AddPersonToSlice import AddPersonToSlice
+ from PLC.Methods.DeletePersonFromSlice import DeletePersonFromSlice
+ new_slices = set(slice_ids).difference(self['slice_ids'])
+ stale_slices = set(self['slice_ids']).difference(slice_ids)
+
+ for new_slice in new_slices:
+ AddPersonToSlice.__call__(AddPersonToSlice(self.api), auth, self['person_id'], new_slice)
+ for stale_slice in stale_slices:
+ DeletePersonFromSlice.__call__(DeletePersonFromSlice(self.api), auth, self['person_id'], stale_slice)
+
+
def delete(self, commit = True):
"""
Delete existing user.
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 = {}
# Mark Huang <mlhuang@cs.princeton.edu>
# Copyright (C) 2006 The Trustees of Princeton University
#
-# $Id: PostgreSQL.py,v 1.15 2007/02/12 18:41:27 mlhuang Exp $
+# $Id: PostgreSQL.py 5574 2007-10-25 20:33:17Z thierry $
#
import psycopg2
# Mark Huang <mlhuang@cs.princeton.edu>
# Copyright (C) 2006 The Trustees of Princeton University
#
-# $Id: PyCurl.py,v 1.3 2007/10/01 20:51:47 tmack Exp $
+# $Id: PyCurl.py 5574 2007-10-25 20:33:17Z thierry $
#
import os
# Mark Huang <mlhuang@cs.princeton.edu>
# Copyright (C) 2006 The Trustees of Princeton University
#
-# $Id: Roles.py,v 1.7 2006/11/08 23:02:01 mlhuang Exp $
+# $Id: Roles.py 5574 2007-10-25 20:33:17Z thierry $
#
from types import StringTypes
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)
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:
# Mark Huang <mlhuang@cs.princeton.edu>
# Copyright (C) 2005 The Trustees of Princeton University
#
-# $Id: Shell.py,v 1.5 2007/02/08 21:49:24 mlhuang Exp $
+# $Id: Shell.py 5574 2007-10-25 20:33:17Z thierry $
#
import os
import string
from PLC.Faults import *
-from PLC.Parameter import Parameter
+from PLC.Parameter import Parameter, Mixed
from PLC.Filter import Filter
from PLC.Debug import profile
from PLC.Table import Row, Table
'peer_site_id': Parameter(int, "Foreign site identifier at peer", nullok = True),
'ext_consortium_id': Parameter(int, "external consortium id", nullok = True)
}
-
+ related_fields = {
+ 'persons': [Mixed(Parameter(int, "Person identifier"),
+ Parameter(str, "Email address"))],
+ 'addresses': [Mixed(Parameter(int, "Address identifer"),
+ Filter(Address.fields))]
+ }
# for Cache
class_key = 'login_base'
foreign_fields = ['abbreviated_name', 'name', 'is_public', 'latitude', 'longitude',
" where site_id = %d" % (self['site_id']) )
self.sync(commit)
+
+ def associate_persons(self, auth, field, value):
+ """
+ Adds persons found in value list to this site (using AddPersonToSite).
+ Deletes persons not found in value list from this site (using DeletePersonFromSite).
+ """
+
+ assert 'person_ids' in self
+ assert 'site_id' in self
+ assert isinstance(value, list)
+
+ (person_ids, emails) = self.separate_types(value)[0:2]
+
+ # Translate emails into person_ids
+ if emails:
+ persons = Persons(self.api, emails, ['person_id']).dict('person_id')
+ person_ids += persons.keys()
+
+ # Add new ids, remove stale ids
+ if self['person_ids'] != person_ids:
+ from PLC.Methods.AddPersonToSite import AddPersonToSite
+ from PLC.Methods.DeletePersonFromSite import DeletePersonFromSite
+ new_persons = set(person_ids).difference(self['person_ids'])
+ stale_persons = set(self['person_ids']).difference(person_ids)
+
+ for new_person in new_persons:
+ AddPersonToSite.__call__(AddPersonToSite(self.api), auth, new_person, self['site_id'])
+ for stale_person in stale_persons:
+ DeletePersonFromSite.__call__(DeletePersonFromSite(self.api), auth, stale_person, self['site_id'])
+
+ def associate_addresses(self, auth, field, value):
+ """
+ Deletes addresses_ids not found in value list (using DeleteAddress).
+ Adds address if slice_fields w/o address_id found in value list (using AddSiteAddress).
+ Update address if slice_fields w/ address_id found in value list (using UpdateAddress).
+ """
+
+ assert 'address_ids' in self
+ assert 'site_id' in self
+ assert isinstance(value, list)
+
+ (address_ids, blank, addresses) = self.separate_types(value)
+
+ for address in addresses:
+ if 'address_id' in address:
+ address_ids.append(address['address_id'])
+
+ # Add new ids, remove stale ids
+ if self['address_ids'] != address_ids:
+ from PLC.Methods.DeleteAddress import DeleteAddress
+ stale_addresses = set(self['address_ids']).difference(address_ids)
+
+ for stale_address in stale_addresses:
+ DeleteAddress.__call__(DeleteAddress(self.api), auth, stale_address)
+
+ if addresses:
+ from PLC.Methods.AddSiteAddress import AddSiteAddress
+ from PLC.Methods.UpdateAddress import UpdateAddress
+
+ updated_addresses = filter(lambda address: 'address_id' in address, addresses)
+ added_addresses = filter(lambda address: 'address_id' not in address, addresses)
+
+ for address in added_addresses:
+ AddSiteAddress.__call__(AddSiteAddress(self.api), auth, self['site_id'], address)
+ for address in updated_addresses:
+ address_id = address.pop('address_id')
+ UpdateAddress.__call__(UpdateAddress(self.api), auth, address_id, address)
+
def delete(self, commit = True):
"""
Delete existing site.
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
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)
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)
# Mark Huang <mlhuang@cs.princeton.edu>
# Copyright (C) 2006 The Trustees of Princeton University
#
-# $Id: SliceInstantiations.py,v 1.2 2006/10/03 19:27:28 mlhuang Exp $
+# $Id: SliceInstantiations.py 5574 2007-10-25 20:33:17Z thierry $
#
from PLC.Faults import *
import re
from PLC.Faults import *
-from PLC.Parameter import Parameter
+from PLC.Parameter import Parameter, Mixed
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
from PLC.Persons import Person, Persons
+from PLC.SliceAttributes import SliceAttribute
class Slice(Row):
"""
'peer_id': Parameter(int, "Peer to which this slice belongs", nullok = True),
'peer_slice_id': Parameter(int, "Foreign slice identifier at peer", nullok = True),
}
+ related_fields = {
+ 'persons': [Mixed(Parameter(int, "Person identifier"),
+ Parameter(str, "Email address"))],
+ 'nodes': [Mixed(Parameter(int, "Node identifier"),
+ Parameter(str, "Fully qualified hostname"))]
+ }
# for Cache
class_key = 'name'
foreign_fields = ['instantiation', 'url', 'description', 'max_nodes', 'expires']
add_to_node_whitelist = Row.add_object(Node, 'node_slice_whitelist')
delete_from_node_whitelist = Row.remove_object(Node, 'node_slice_whitelist')
+ def associate_persons(self, auth, field, value):
+ """
+ Adds persons found in value list to this slice (using AddPersonToSlice).
+ Deletes persons not found in value list from this slice (using DeletePersonFromSlice).
+ """
+
+ assert 'person_ids' in self
+ assert 'slice_id' in self
+ assert isinstance(value, list)
+
+ (person_ids, emails) = self.separate_types(value)[0:2]
+
+ # Translate emails into person_ids
+ if emails:
+ persons = Persons(self.api, emails, ['person_id']).dict('person_id')
+ person_ids += persons.keys()
+
+ # Add new ids, remove stale ids
+ if self['person_ids'] != person_ids:
+ from PLC.Methods.AddPersonToSlice import AddPersonToSlice
+ from PLC.Methods.DeletePersonFromSlice import DeletePersonFromSlice
+ new_persons = set(person_ids).difference(self['person_ids'])
+ stale_persons = set(self['person_ids']).difference(person_ids)
+
+ for new_person in new_persons:
+ AddPersonToSlice.__call__(AddPersonToSlice(self.api), auth, new_person, self['slice_id'])
+ for stale_person in stale_persons:
+ DeletePersonFromSlice.__call__(DeletePersonFromSlice(self.api), auth, stale_person, self['slice_id'])
+
+ def associate_nodes(self, auth, field, value):
+ """
+ Adds nodes found in value list to this slice (using AddSliceToNodes).
+ Deletes nodes not found in value list from this slice (using DeleteSliceFromNodes).
+ """
+
+ from PLC.Nodes import Nodes
+
+ assert 'node_ids' in self
+ assert 'slice_id' in self
+ assert isinstance(value, list)
+
+ (node_ids, hostnames) = self.separate_types(value)[0:2]
+
+ # Translate hostnames into node_ids
+ if hostnames:
+ nodes = Nodes(self.api, hostnames, ['node_id']).dict('node_id')
+ node_ids += nodes.keys()
+
+ # Add new ids, remove stale ids
+ if self['node_ids'] != node_ids:
+ from PLC.Methods.AddSliceToNodes import AddSliceToNodes
+ from PLC.Methods.DeleteSliceFromNodes import DeleteSliceFromNodes
+ new_nodes = set(node_ids).difference(self['node_ids'])
+ stale_nodes = set(self['node_ids']).difference(node_ids)
+
+ if new_nodes:
+ AddSliceToNodes.__call__(AddSliceToNodes(self.api), auth, self['slice_id'], list(new_nodes))
+ if stale_nodes:
+ DeleteSliceFromNodes.__call__(DeleteSliceFromNodes(self.api), auth, self['slice_id'], list(stale_nodes))
+ def associate_slice_attributes(self, auth, fields, value):
+ """
+ Deletes slice_attribute_ids not found in value list (using DeleteSliceAttribute).
+ Adds slice_attributes if slice_fields w/o slice_id is found (using AddSliceAttribute).
+ Updates slice_attribute if slice_fields w/ slice_id is found (using UpdateSlceiAttribute).
+ """
+
+ assert 'slice_attribute_ids' in self
+ assert isinstance(value, list)
+
+ (attribute_ids, blank, attributes) = self.separate_types(value)
+
+ # There is no way to add attributes by id. They are
+ # associated with a slice when they are created.
+ # So we are only looking to delete here
+ if self['slice_attribute_ids'] != attribute_ids:
+ from PLC.Methods.DeleteSliceAttribute import DeleteSliceAttribute
+ stale_attributes = set(self['slice_attribute_ids']).difference(attribute_ids)
+
+ for stale_attribute in stale_attributes:
+ DeleteSliceAttribute.__call__(DeleteSliceAttribute(self.api), auth, stale_attribute['slice_attribute_id'])
+
+ # If dictionary exists, we are either adding new
+ # attributes or updating existing ones.
+ if attributes:
+ from PLC.Methods.AddSliceAttribute import AddSliceAttribute
+ from PLC.Methods.UpdateSliceAttribute import UpdateSliceAttribute
+
+ added_attributes = filter(lambda x: 'slice_attribute_id' not in x, attributes)
+ updated_attributes = filter(lambda x: 'slice_attribute_id' in x, attributes)
+
+ for added_attribute in added_attributes:
+ if 'attribute_type' in added_attribute:
+ type = added_attribute['attribute_type']
+ elif 'attribute_type_id' in added_attribute:
+ type = added_attribute['attribute_type_id']
+ else:
+ raise PLCInvalidArgument, "Must specify attribute_type or attribute_type_id"
+
+ if 'value' in added_attribute:
+ value = added_attribute['value']
+ else:
+ raise PLCInvalidArgument, "Must specify a value"
+
+ if 'node_id' in added_attribute:
+ node_id = added_attribute['node_id']
+ else:
+ node_id = None
+
+ if 'nodegroup_id' in added_attribute:
+ nodegroup_id = added_attribute['nodegroup_id']
+ else:
+ nodegroup_id = None
+
+ AddSliceAttribute.__call__(AddSliceAttribute(self.api), auth, self['slice_id'], type, value, node_id, nodegroup_id)
+ for updated_attribute in updated_attributes:
+ attribute_id = updated_attribute.pop('slice_attribute_id')
+ if attribute_id not in self['slice_attribute_ids']:
+ raise PLCInvalidArgument, "Attribute doesnt belong to this slice"
+ else:
+ UpdateSliceAttribute.__call__(UpdateSliceAttribute(self.api), auth, attribute_id, updated_attribute)
+
def sync(self, commit = True):
"""
Add or update a slice.
self['is_deleted'] = True
self.sync(commit)
+
class Slices(Table):
"""
Representation of row(s) from the slices table in the
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
if value is not None and hasattr(self, 'validate_' + key):
validate = getattr(self, 'validate_' + key)
self[key] = validate(value)
+
+ def separate_types(self, items):
+ """
+ Separate a list of different typed objects.
+ Return a list for each type (ints, strs and dicts)
+ """
+
+ if isinstance(items, (list, tuple, set)):
+ ints = filter(lambda x: isinstance(x, (int, long)), items)
+ strs = filter(lambda x: isinstance(x, StringTypes), items)
+ dicts = filter(lambda x: isinstance(x, dict), items)
+ return (ints, strs, dicts)
+ else:
+ raise PLCInvalidArgument, "Can only separate list types"
+
+
+ def associate(self, *args):
+ """
+ Provides a means for high lvl api calls to associate objects
+ using low lvl calls.
+ """
+
+ if len(args) < 3:
+ raise PLCInvalidArgumentCount, "auth, field, value must be specified"
+ elif hasattr(self, 'associate_' + args[1]):
+ associate = getattr(self, 'associate_'+args[1])
+ associate(*args)
+ else:
+ raise PLCInvalidArguemnt, "No such associate function associate_%s" % args[1]
def validate_timestamp(self, timestamp, check_future = False):
"""
# Mark Huang <mlhuang@cs.princeton.edu>
# Copyright (C) 2006 The Trustees of Princeton University
#
-# $Id: Test.py,v 1.3 2007/09/12 17:52:27 tmack Exp $
+# $Id: Test.py 5574 2007-10-25 20:33:17Z thierry $
#
from pprint import pprint
all = """
-API
-AddressTypes
Addresses
+AddressTypes
+API
Auth
Boot
BootStates
Filter
GPG
InitScripts
-KeyTypes
Keys
+KeyTypes
Messages
Method
NetworkMethods
NetworkTypes
NodeGroups
-NodeNetworkSettingTypes
NodeNetworkSettings
+NodeNetworkSettingTypes
NodeNetworks
Nodes
-PCUs
-POD
Parameter
+PCUProtocolTypes
+PCUs
+PCUTypes
Peers
Persons
+POD
PostgreSQL
PyCurl
Roles
+sendmail
Sessions
Shell
Sites
-SliceAttributeTypes
SliceAttributes
+SliceAttributeTypes
SliceInstantiations
Slices
Table
Test
-sendmail
""".split()