From d1aa90df9b9dd21d774b7b92ba966d06bb3d9f85 Mon Sep 17 00:00:00 2001 From: Mark Huang Date: Mon, 2 Oct 2006 18:32:31 +0000 Subject: [PATCH] make read-only a Parameter attribute --- PLC/Nodes.py | 25 +++++------ PLC/Parameter.py | 28 ++++++++++-- PLC/Persons.py | 23 +++++----- PLC/Sites.py | 21 +++++---- PLC/Slices.py | 113 +++++++++++++++++++++++++++++++++++++++++++---- 5 files changed, 162 insertions(+), 48 deletions(-) diff --git a/PLC/Nodes.py b/PLC/Nodes.py index 35b1ab4..7930ab1 100644 --- a/PLC/Nodes.py +++ b/PLC/Nodes.py @@ -4,7 +4,7 @@ # Mark Huang # 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 @@ -33,16 +33,16 @@ class Node(Row): '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): @@ -99,11 +99,10 @@ class Node(Row): # 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() diff --git a/PLC/Parameter.py b/PLC/Parameter.py index 5dab363..5f573f8 100644 --- a/PLC/Parameter.py +++ b/PLC/Parameter.py @@ -4,7 +4,7 @@ # Mark Huang # 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: @@ -14,9 +14,29 @@ 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) diff --git a/PLC/Persons.py b/PLC/Persons.py index b549a94..ac97192 100644 --- a/PLC/Persons.py +++ b/PLC/Persons.py @@ -4,7 +4,7 @@ # Mark Huang # 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 @@ -42,13 +42,13 @@ class Person(Row): '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): @@ -242,11 +242,10 @@ class Person(Row): # 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() diff --git a/PLC/Sites.py b/PLC/Sites.py index d18dac3..2fbcd1b 100644 --- a/PLC/Sites.py +++ b/PLC/Sites.py @@ -28,15 +28,15 @@ class Site(Row): '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): @@ -145,11 +145,10 @@ class Site(Row): # 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() diff --git a/PLC/Slices.py b/PLC/Slices.py index 449fba1..1b6ee92 100644 --- a/PLC/Slices.py +++ b/PLC/Slices.py @@ -25,11 +25,11 @@ class Slice(Row): '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): @@ -69,6 +69,104 @@ class Slice(Row): 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. @@ -96,11 +194,10 @@ class Slice(Row): # 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() -- 2.43.0