# Mark Huang <mlhuang@cs.princeton.edu>
# Copyright (C) 2006 The Trustees of Princeton University
#
-# $Id: Nodes.py,v 1.6 2006/10/02 15:21:03 mlhuang Exp $
+# $Id: Nodes.py,v 1.7 2006/10/02 16:04:42 mlhuang Exp $
#
from types import StringTypes
'boot_nonce': Parameter(str, "(Admin only) Random value generated by the node at last boot", max = 128),
'version': Parameter(str, "Apparent Boot CD version", max = 64),
'ssh_rsa_key': Parameter(str, "Last known SSH host key", max = 1024),
- 'date_created': Parameter(str, "Date and time when node entry was created"),
- 'last_updated': Parameter(str, "Date and time when node entry was created"),
+ 'date_created': Parameter(str, "Date and time when node entry was created", ro = True),
+ 'last_updated': Parameter(str, "Date and time when node entry was created", ro = True),
'key': Parameter(str, "(Admin only) Node key", max = 256),
'session': Parameter(str, "(Admin only) Node session value", max = 256),
- 'nodenetwork_ids': Parameter([int], "List of network interfaces that this node has"),
- 'nodegroup_ids': Parameter([int], "List of node groups that this node is in"),
- # '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"),
- # 'pcu_ids': Parameter([int], "List of PCUs that control this node"),
+ 'nodenetwork_ids': Parameter([int], "List of network interfaces that this node has", ro = True),
+ 'nodegroup_ids': Parameter([int], "List of node groups that this node is in", ro = True),
+ # 'conf_file_ids': Parameter([int], "List of configuration files specific to this node", ro = True),
+ # 'root_person_ids': Parameter([int], "(Admin only) List of people who have root access to this node", ro = True),
+ 'slice_ids': Parameter([int], "List of slices on this node", ro = True),
+ # 'pcu_ids': Parameter([int], "List of PCUs that control this node", ro = True),
}
def __init__(self, api, fields):
# Filter out fields that cannot be set or updated directly
nodes_fields = self.api.db.fields('nodes')
- fields = dict(filter(lambda (key, value): key in nodes_fields,
+ fields = dict(filter(lambda (key, value): \
+ key in nodes_fields and \
+ (key not in self.fields or not self.fields[key].ro),
self.items()))
- for ro_field in 'date_created', 'last_updated':
- if ro_field in fields:
- del fields[ro_field]
# Parameterize for safety
keys = fields.keys()
# Mark Huang <mlhuang@cs.princeton.edu>
# Copyright (C) 2006 The Trustees of Princeton University
#
-# $Id: Parameter.py,v 1.1 2006/09/06 15:36:07 mlhuang Exp $
+# $Id: Parameter.py,v 1.2 2006/09/08 19:45:04 mlhuang Exp $
#
class Parameter:
sub-parameters (i.e., dict fields).
"""
- def __init__(self, type, doc = "", min = None, max = None, optional = True, default = None):
- (self.type, self.doc, self.min, self.max, self.optional, self.default) = \
- (type, doc, min, max, optional, default)
+ def __init__(self, type, doc = "",
+ min = None, max = None,
+ optional = True, default = None,
+ ro = False):
+ # Basic type of the parameter. May be a builtin type or Mixed.
+ self.type = type
+
+ # Documentation string for the parameter
+ self.doc = doc
+
+ # Basic value checking. For numeric types, the minimum and
+ # maximum possible values, inclusive. For string types, the
+ # minimum and maximum possible UTF-8 encoded byte lengths.
+ self.min = min
+ self.max = max
+
+ # Whether the sub-parameter is optional or not. If optional,
+ # the default for the sub-parameter if not specified.
+ self.optional = optional
+ self.default = default
+
+ # Whether the DB field is read-only.
+ self.ro = ro
def __repr__(self):
return repr(self.type)
# Mark Huang <mlhuang@cs.princeton.edu>
# Copyright (C) 2006 The Trustees of Princeton University
#
-# $Id: Persons.py,v 1.5 2006/10/02 15:25:03 mlhuang Exp $
+# $Id: Persons.py,v 1.6 2006/10/02 16:04:22 mlhuang Exp $
#
from types import StringTypes
'bio': Parameter(str, "Biography", max = 254),
'enabled': Parameter(bool, "Has been enabled"),
'password': Parameter(str, "Account password in crypt() form", max = 254),
- 'last_updated': Parameter(str, "Date and time of last update"),
- 'date_created': Parameter(str, "Date and time when account was created"),
- 'role_ids': Parameter([int], "List of role identifiers"),
- 'roles': Parameter([str], "List of roles"),
- 'site_ids': Parameter([int], "List of site identifiers"),
- 'key_ids': Parameter([int], "List of key identifiers"),
- 'slice_ids': Parameter([int], "List of slice identifiers"),
+ 'last_updated': Parameter(str, "Date and time of last update", ro = True),
+ 'date_created': Parameter(str, "Date and time when account was created", ro = True),
+ 'role_ids': Parameter([int], "List of role identifiers", ro = True),
+ 'roles': Parameter([str], "List of roles", ro = True),
+ 'site_ids': Parameter([int], "List of site identifiers", ro = True),
+ 'key_ids': Parameter([int], "List of key identifiers", ro = True),
+ 'slice_ids': Parameter([int], "List of slice identifiers", ro = True),
}
def __init__(self, api, fields):
# Filter out fields that cannot be set or updated directly
persons_fields = self.api.db.fields('persons')
- fields = dict(filter(lambda (key, value): key in persons_fields,
+ fields = dict(filter(lambda (key, value): \
+ key in persons_fields and \
+ (key not in self.fields or not self.fields[key].ro),
self.items()))
- for ro_field in 'date_created', 'last_updated':
- if ro_field in fields:
- del fields[ro_field]
# Parameterize for safety
keys = fields.keys()
'latitude': Parameter(float, "Decimal latitude of the site", min = -90.0, max = 90.0),
'longitude': Parameter(float, "Decimal longitude of the site", min = -180.0, max = 180.0),
'url': Parameter(str, "URL of a page that describes the site", max = 254),
- 'date_created': Parameter(int, "Date and time when site entry was created, in seconds since UNIX epoch"),
- 'last_updated': Parameter(int, "Date and time when site entry was last updated, in seconds since UNIX epoch"),
+ 'date_created': Parameter(int, "Date and time when site entry was created, in seconds since UNIX epoch", ro = True),
+ 'last_updated': Parameter(int, "Date and time when site entry was last updated, in seconds since UNIX epoch", ro = True),
'max_slices': Parameter(int, "Maximum number of slices that the site is able to create"),
'max_slivers': Parameter(int, "Maximum number of slivers that the site is able to create"),
- 'person_ids': Parameter([int], "List of account identifiers"),
- 'slice_ids': Parameter([int], "List of slice identifiers"),
- 'address_ids': Parameter([int], "List of address identifiers"),
- # 'pcu_ids': Parameter([int], "List of PCU identifiers"),
- 'node_ids': Parameter([int], "List of site node identifiers"),
+ 'person_ids': Parameter([int], "List of account identifiers", ro = True),
+ 'slice_ids': Parameter([int], "List of slice identifiers", ro = True),
+ 'address_ids': Parameter([int], "List of address identifiers", ro = True),
+ # 'pcu_ids': Parameter([int], "List of PCU identifiers", ro = True),
+ 'node_ids': Parameter([int], "List of site node identifiers", ro = True),
}
def __init__(self, api, fields):
# Filter out fields that cannot be set or updated directly
sites_fields = self.api.db.fields('sites')
- fields = dict(filter(lambda (key, value): key in sites_fields,
+ fields = dict(filter(lambda (key, value): \
+ key in sites_fields and \
+ (key not in self.fields or not self.fields[key].ro),
self.items()))
- for ro_field in 'date_created', 'last_updated':
- if ro_field in fields:
- del fields[ro_field]
# Parameterize for safety
keys = fields.keys()
'description': Parameter(str, "Slice description", max = 2048),
'max_nodes': Parameter(int, "Maximum number of nodes that can be assigned to this slice"),
'creator_person_id': Parameter(int, "Identifier of the account that created this slice"),
- 'created': Parameter(int, "Date and time when slice was created, in seconds since UNIX epoch"),
+ 'created': Parameter(int, "Date and time when slice was created, in seconds since UNIX epoch", ro = True),
'expires': Parameter(int, "Date and time when slice expires, in seconds since UNIX epoch"),
- 'node_ids': Parameter([int], "List of nodes in this slice"),
- 'person_ids': Parameter([int], "List of accounts that can use this slice"),
- 'attribute_ids': Parameter([int], "List of slice attributes"),
+ 'node_ids': Parameter([int], "List of nodes in this slice", ro = True),
+ 'person_ids': Parameter([int], "List of accounts that can use this slice", ro = True),
+ 'attribute_ids': Parameter([int], "List of slice attributes", ro = True),
}
def __init__(self, api, fields):
return person_id
+ def add_person(self, person, commit = True):
+ """
+ Add person to existing slice.
+ """
+
+ assert 'slice_id' in self
+ assert isinstance(person, PLC.Persons.Person)
+ assert 'person_id' in person
+
+ slice_id = self['slice_id']
+ person_id = person['person_id']
+ self.api.db.do("INSERT INTO slice_person (person_id, slice_id)" \
+ " VALUES(%(person_id)d, %(slice_id)d)",
+ locals())
+
+ if commit:
+ self.api.db.commit()
+
+ if 'person_ids' in self and person_id not in self['person_ids']:
+ self['person_ids'].append(person_id)
+
+ if 'slice_ids' in person and slice_id not in person['slice_ids']:
+ person['slice_ids'].append(slice_id)
+
+ def remove_person(self, person, commit = True):
+ """
+ Remove person from existing slice.
+ """
+
+ assert 'slice_id' in self
+ assert isinstance(person, PLC.Persons.Person)
+ assert 'person_id' in person
+
+ slice_id = self['slice_id']
+ person_id = person['person_id']
+ self.api.db.do("DELETE FROM slice_person" \
+ " WHERE person_id = %(person_id)d" \
+ " AND slice_id = %(slice_id)d",
+ locals())
+
+ if commit:
+ self.api.db.commit()
+
+ if 'person_ids' in self and person_id in self['person_ids']:
+ self['person_ids'].remove(person_id)
+
+ if 'slice_ids' in person and slice_id in person['slice_ids']:
+ person['slice_ids'].remove(slice_id)
+
+ def add_node(self, node, commit = True):
+ """
+ Add node to existing slice.
+ """
+
+ assert 'slice_id' in self
+ assert isinstance(node, PLC.Nodes.Node)
+ assert 'node_id' in node
+
+ slice_id = self['slice_id']
+ node_id = node['node_id']
+ self.api.db.do("INSERT INTO slice_node (node_id, slice_id)" \
+ " VALUES(%(node_id)d, %(slice_id)d)",
+ locals())
+
+ if commit:
+ self.api.db.commit()
+
+ if 'node_ids' in self and node_id not in self['node_ids']:
+ self['node_ids'].append(node_id)
+
+ if 'slice_ids' in node and slice_id not in node['slice_ids']:
+ node['slice_ids'].append(slice_id)
+
+ def remove_node(self, node, commit = True):
+ """
+ Remove node from existing slice.
+ """
+
+ assert 'slice_id' in self
+ assert isinstance(node, PLC.Nodes.Node)
+ assert 'node_id' in node
+
+ slice_id = self['slice_id']
+ node_id = node['node_id']
+ self.api.db.do("DELETE FROM slice_node" \
+ " WHERE node_id = %(node_id)d" \
+ " AND slice_id = %(slice_id)d",
+ locals())
+
+ if commit:
+ self.api.db.commit()
+
+ if 'node_ids' in self and node_id in self['node_ids']:
+ self['node_ids'].remove(node_id)
+
+ if 'slice_ids' in node and slice_id in node['slice_ids']:
+ node['slice_ids'].remove(slice_id)
+
def sync(self, commit = True):
"""
Flush changes back to the database.
# Filter out fields that cannot be set or updated directly
slices_fields = self.api.db.fields('slices')
- fields = dict(filter(lambda (key, value): key in slices_fields,
+ fields = dict(filter(lambda (key, value): \
+ key in slices_fields and \
+ (key not in self.fields or not self.fields[key].ro),
self.items()))
- for ro_field in 'created',:
- if ro_field in fields:
- del fields[ro_field]
# Parameterize for safety
keys = fields.keys()