+++ /dev/null
-#
-# Thierry Parmentelat - INRIA
-#
-import time
-
-from types import StringTypes
-
-from PLC.Table import Row, Table
-from PLC.Parameter import Parameter
-from PLC.Filter import Filter
-
-class ForeignNode (Row) :
- """
- This object stores information about nodes hosted on
- other peering instances of myplc
- """
-
- table_name = 'nodes'
- primary_key = 'node_id'
-
- fields = {
- 'node_id': Parameter (int, "Node Id"),
- 'hostname': Parameter (str, "Node name"),
- 'peer_id': Parameter (str, "Peer id"),
- 'boot_state' : Parameter (str, "Boot state, see Node"),
- 'model' : Parameter (str,"Model, see Node"),
- 'version' : Parameter (str,"Version, see Node"),
- 'date_created': Parameter(int, "Creation time, see Node"),
- 'last_updated': Parameter(int, "Update time, see Node"),
- 'slice_ids': Parameter([int], "List of slices on this node"),
- }
-
- def __init__(self,api,fields={},uptodate=True):
- Row.__init__(self,api,fields)
- self.uptodate=uptodate
-
- def validate_date_created(self,timestamp):
- return time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime(timestamp))
-
- def validate_last_updated(self,timestamp):
- return time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime(timestamp))
-
- def purge_peer_node (self,commit=True):
- sql = "DELETE FROM peer_node WHERE node_id=%d"%self['node_id']
- self.api.db.do(sql)
- if commit:
- self.api.db.commit()
-
- def delete (self, commit=True):
- """
- Delete existing foreign node.
- """
- self.purge_peer_node()
- self['deleted']=True
- self.sync(commit)
-
-class ForeignNodes (Table):
- def __init__ (self, api, foreign_node_filter = None, columns = None):
- Table.__init__(self, api, ForeignNode, columns)
-
- sql = ""
- sql += "SELECT %s FROM view_foreign_nodes " % ", ".join(self.columns)
- sql += "WHERE deleted IS False "
-
- if foreign_node_filter is not None:
- if isinstance(foreign_node_filter, (list, tuple, set)):
- # Separate the list into integers and strings
- ints = filter(lambda x: isinstance(x, (int, long)), foreign_node_filter)
- strs = filter(lambda x: isinstance(x, StringTypes), foreign_node_filter)
- foreign_node_filter = Filter(ForeignNode.fields, {'node_id': ints, 'hostname': strs})
- sql += " AND (%s)" % foreign_node_filter.sql(api, "OR")
- elif isinstance(foreign_node_filter, dict):
- foreign_node_filter = Filter(ForeignNode.fields, foreign_node_filter)
- sql += " AND (%s)" % foreign_node_filter.sql(api, "AND")
-
- self.selectall(sql)
-
+++ /dev/null
-#
-# Thierry Parmentelat - INRIA
-#
-import time
-
-from types import StringTypes
-
-from PLC.Table import Row, Table
-from PLC.Parameter import Parameter
-from PLC.Filter import Filter
-
-class ForeignSlice (Row) :
- """
- This object stores information about slices hosted on
- other peering instances of myplc
- """
-
- table_name = 'slices'
- primary_key = 'slice_id'
-
- fields = {
- 'slice_id': Parameter (int, "Slice Id"),
- 'name' : Parameter (str, "Slice name"),
- 'peer_id': Parameter (str, "Peer id"),
- 'instantiation': Parameter(str, "Slice instantiation state"),
- 'url': Parameter(str, "URL further describing this slice", max = 254, nullok = True),
- 'description': Parameter(str, "Slice description", max = 2048, nullok = True),
- 'max_nodes': Parameter(int, "Maximum number of nodes that can be assigned to this slice"),
- '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"),
- }
-
- def __init__(self,api,fields={},uptodate=True):
- Row.__init__(self,api,fields)
- self.uptodate=uptodate
-
- def validate_created(self,timestamp):
- return time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime(timestamp))
-
- def validate_expires(self,timestamp):
- return time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime(timestamp))
-
- def purge_peer_slice (self,commit=True):
- sql = "DELETE FROM peer_slice WHERE slice_id=%d"%self['slice_id']
- self.api.db.do(sql)
- if commit:
- self.api.db.commit()
-
- def purge_slice_node (self,commit=True):
- sql = "DELETE FROM slice_node WHERE slice_id=%d"%self['slice_id']
- self.api.db.do(sql)
- if commit:
- self.api.db.commit()
-
- def add_slice_nodes (self, node_ids, commit=True):
- slice_id = self['slice_id']
- ### xxx needs to be optimized
- ### tried to figure a way to use a single sql statement
- ### like: insert into table (x,y) values (1,2),(3,4);
- ### but apparently this is not supported under postgresql
- for node_id in node_ids:
- sql="INSERT INTO slice_node VALUES (%d,%d)"%(slice_id,node_id)
- self.api.db.do(sql)
- if commit:
- self.api.db.commit()
-
- def update_slice_nodes (self, node_ids):
- # xxx to be optimized
- # we could compute the (set) difference between
- # current and updated set of node_ids
- # and invoke the DB only based on that
- #
- # for now : clean all entries for this slice
- self.purge_slice_node()
- # and re-install new list
- self.add_slice_nodes (node_ids)
-
- def delete (self, commit=True):
- """
- Delete existing foreign slice.
- """
- self.purge_peer_slice()
- self['is_deleted']=True
- self.sync(commit)
-
-
-class ForeignSlices (Table):
- def __init__ (self, api, foreign_slice_filter = None, columns = None):
- Table.__init__(self, api, ForeignSlice, columns)
-
- sql = ""
- sql += "SELECT %s FROM view_foreign_slices " % ", ".join(self.columns)
- sql += "WHERE is_deleted IS False "
-
- if foreign_slice_filter is not None:
- if isinstance(foreign_slice_filter, (list, tuple, set)):
- # Separate the list into integers and strings
- ints = filter(lambda x: isinstance(x, (int, long)), foreign_slice_filter)
- strs = filter(lambda x: isinstance(x, StringTypes), foreign_slice_filter)
- foreign_slice_filter = Filter(ForeignSlice.fields, {'slice_id': ints, 'name': strs})
- sql += " AND (%s)" % foreign_slice_filter.sql(api, "OR")
- elif isinstance(foreign_slice_filter, dict):
- foreign_slice_filter = Filter(ForeignSlice.fields, foreign_slice_filter)
- sql += " AND (%s)" % foreign_slice_filter.sql(api, "AND")
-
- self.selectall(sql)
-
node = Node(self.api, node_fields)
node['site_id'] = site['site_id']
+ # xxx temporary, until I figure a way to get local/foreign nodes
+ # so far I cannot seem to use a filter/dict like {'~peer_id':None}
+ # node['peer_id'] = 0
node.sync()
self.object_ids = [site['site_id'], node['node_id']]
from PLC.Method import Method
from PLC.Parameter import Parameter, Mixed
from PLC.Nodes import Node, Nodes
-from PLC.ForeignNodes import ForeignNode, ForeignNodes
from PLC.Slices import Slice, Slices
from PLC.Auth import Auth
class AddSliceToNodes(Method):
"""
Adds the specified slice to the specified nodes.
- Nodes can be either regular (local) nodes as returned by GetNodes
- or foreign nodes as returned by GetForeignNodes
+ Nodes can be either local or foreign nodes, as returned by GetNodes
If the slice is
already associated with a node, no errors are returned.
# Get specified nodes, add them to the slice
nodes = Nodes(self.api, node_id_or_hostname_list)
- foreign_nodes = ForeignNodes (self.api, node_id_or_hostname_list)
- all_nodes = nodes+foreign_nodes;
- for node in all_nodes:
+ for node in nodes:
if slice['slice_id'] not in node['slice_ids']:
slice.add_node(node, commit = False)
slice.sync()
- self.object_ids = [node['node_id'] for node in all_nodes]
+ self.object_ids = [node['node_id'] for node in nodes]
return 1
from PLC.Method import Method
from PLC.Parameter import Parameter, Mixed
from PLC.Nodes import Node, Nodes
-from PLC.ForeignNodes import ForeignNode, ForeignNodes
from PLC.Slices import Slice, Slices
from PLC.Auth import Auth
# Get specified nodes
nodes = Nodes(self.api, node_id_or_hostname_list)
- foreign_nodes = ForeignNodes(self.api, node_id_or_hostname_list)
- all_nodes = nodes+foreign_nodes;
- for node in all_nodes:
+ for node in nodes:
if slice['slice_id'] in node['slice_ids']:
slice.remove_node(node, commit = False)
slice.sync()
- self.object_ids = [node['node_id'] for node in all_nodes]
+ self.object_ids = [node['node_id'] for node in nodes]
return 1
+++ /dev/null
-#
-# Thierry Parmentelat - INRIA
-#
-
-from PLC.Faults import *
-from PLC.Method import Method
-from PLC.Parameter import Parameter, Mixed
-from PLC.Filter import Filter
-from PLC.Auth import Auth
-
-from PLC.ForeignNodes import ForeignNode, ForeignNodes
-
-class GetForeignNodes(Method):
- """
- Returns an array of structs containing details about foreign
- nodes. If foreign_node_filter is specified and is an array of
- foreign node identifiers or hostnames, or a struct of foreign node
- attributes, only foreign nodes matching the filter will be
- returned. If return_fields is specified, only the specified
- details will be returned.
- """
-
- roles = ['admin']
-
- accepts = [
- Auth(),
- Mixed([Mixed(ForeignNode.fields['node_id'],
- ForeignNode.fields['hostname'])],
- Filter(ForeignNode.fields)),
- Parameter([str], "List of fields to return", nullok = True)
- ]
-
- returns = [ForeignNode.fields]
-
- def call(self, auth, foreign_node_filter = None, return_fields = None):
- return ForeignNodes(self.api, foreign_node_filter, return_fields)
+++ /dev/null
-#
-# Thierry Parmentelat - INRIA
-#
-
-from PLC.Faults import *
-from PLC.Method import Method
-from PLC.Parameter import Parameter, Mixed
-from PLC.Filter import Filter
-from PLC.Auth import Auth
-
-from PLC.ForeignSlices import ForeignSlice, ForeignSlices
-
-class GetForeignSlices(Method):
- """
- Returns an array of structs containing details about foreign
- slices. If foreign_slice_filter is specified and is an array of
- foreign slice identifiers or names, or a struct of foreign slice
- attributes, only foreign slices matching the filter will be
- returned. If return_fields is specified, only the specified
- details will be returned.
- """
-
- roles = ['admin']
-
- accepts = [
- Auth(),
- Mixed([Mixed(ForeignSlice.fields['slice_id'],
- ForeignSlice.fields['name'])],
- Filter(ForeignSlice.fields)),
- Parameter([str], "List of fields to return", nullok = True)
- ]
-
- returns = [ForeignSlice.fields]
-
- def call(self, auth, foreign_slice_filter = None, return_fields = None):
- return ForeignSlices(self.api, foreign_slice_filter, return_fields)
Mixed([Mixed(Node.fields['node_id'],
Node.fields['hostname'])],
Filter(Node.fields)),
- Parameter([str], "List of fields to return", nullok = True)
+ Parameter([str], "List of fields to return", nullok = True),
+ Parameter(str,"scope string, can be either 'all', 'local' or 'foreign'"),
]
returns = [Node.fields]
- def call(self, auth, node_filter = None, return_fields = None):
+ def call(self, auth, node_filter = None, return_fields = None, scope = 'all'):
# Get node information
- nodes = Nodes(self.api, node_filter, return_fields)
+ nodes = Nodes(self.api, node_filter, return_fields, scope)
# Remove admin only fields
if 'admin' not in self.caller['roles']:
from PLC.NodeGroups import NodeGroup, NodeGroups
from PLC.ConfFiles import ConfFile, ConfFiles
from PLC.Slices import Slice, Slices
-from PLC.ForeignSlices import ForeignSlice, ForeignSlices
+#from PLC.ForeignSlices import ForeignSlice, ForeignSlices
from PLC.Persons import Person, Persons
from PLC.Keys import Key, Keys
from PLC.SliceAttributes import SliceAttribute, SliceAttributes
all_nodes = {self.caller['node_id']: self.caller}
else:
all_nodes = Nodes(self.api, node_filter).dict()
- # XXX Add foreign nodes
# Get default slices
system_slice_attributes = SliceAttributes(self.api, {'name': 'system', 'value': '1'}).dict()
# Get slice information
all_slices = Slices(self.api, all_slice_ids).dict()
- # XXX Merge in foreign slices
- all_slices.update(ForeignSlices(self.api, all_slice_ids).dict())
person_ids = set()
slice_attribute_ids = set()
from PLC.Peers import Peer, Peers
from PLC.Persons import Person, Persons
-##from PLC.ForeignNodes import ForeignNode, ForeignNodes
class RefreshPeer(Method):
## connect to the peer's API
url=peer['peer_url']
- print 'url=',url
- apiserver = xmlrpclib.Server (url)
- print 'auth=',auth
+ apiserver = xmlrpclib.ServerProxy (url,allow_none=True)
- peer_get_nodes = apiserver.GetNodes(auth)
- nb_new_nodes = peer.refresh_nodes(peer_get_nodes)
+ peer_local_nodes = apiserver.GetNodes(auth,None,None,'local')
+ nb_new_nodes = peer.refresh_nodes(peer_local_nodes)
# rough and temporary
- peer_foreign_nodes = apiserver.GetForeignNodes(auth)
- peer_get_slices = apiserver.GetSlices(auth)
- nb_new_slices = peer.refresh_slices(peer_get_slices,peer_foreign_nodes)
+ peer_foreign_nodes = apiserver.GetNodes(auth,None,None,'foreign')
+ peer_local_slices = apiserver.GetSlices(auth,{'peer_id':None})
+ nb_new_slices = peer.refresh_slices(peer_local_slices,peer_foreign_nodes)
return {'plcname':self.api.config.PLC_NAME,
'new_nodes':nb_new_nodes,
# Mark Huang <mlhuang@cs.princeton.edu>
# Copyright (C) 2006 The Trustees of Princeton University
#
-# $Id: Nodes.py,v 1.19 2006/11/09 03:07:42 mlhuang Exp $
+# $Id: Nodes.py,v 1.20 2006/11/09 19:43:55 mlhuang Exp $
#
from types import StringTypes
'node_id': Parameter(int, "Node identifier"),
'hostname': Parameter(str, "Fully qualified hostname", max = 255),
'site_id': Parameter(int, "Site at which this node is located"),
+ 'peer_id': Parameter(int, "Peer at which this node is managed", nullok = True),
'boot_state': Parameter(str, "Boot state", max = 20),
'model': Parameter(str, "Make and model of the actual machine", max = 255, nullok = True),
'boot_nonce': Parameter(str, "(Admin only) Random value generated by the node at last boot", max = 128),
'ports': Parameter([int], "List of PCU ports that this node is connected to"),
}
+ # foreign attributes management
+ # the key to track remote objects
+ foreign_key = 'hostname'
+ # the fields that get verbatim copied from foreign objects
+ foreign_fields = ['boot_state','model','version','date_created','last_updated']
+
def validate_hostname(self, hostname):
if not valid_hostname(hostname):
raise PLCInvalidArgument, "Invalid hostname"
self['deleted'] = True
self.sync(commit)
+
class Nodes(Table):
"""
Representation of row(s) from the nodes table in the
database.
"""
- def __init__(self, api, node_filter = None, columns = None):
+ def __init__(self, api, node_filter = None, columns = None, scope = 'all'):
Table.__init__(self, api, Node, columns)
sql = "SELECT %s FROM view_nodes WHERE deleted IS False" % \
node_filter = Filter(Node.fields, node_filter)
sql += " AND (%s)" % node_filter.sql(api, "AND")
+ if scope == 'local':
+ sql += " AND (peer_id is NULL) "
+ elif scope == 'foreign':
+ sql += " AND (peer_id is NOT NULL) "
+
self.selectall(sql)
+
from PLC.Table import Row, Table
from PLC.Nodes import Nodes,Node
-from PLC.ForeignNodes import ForeignNodes,ForeignNode
-from PLC.ForeignSlices import ForeignSlices,ForeignSlice
+from PLC.Slices import Slices,Slice
class Peer (Row):
"""
assert 'peer_id' in self
# remove nodes depending on this peer
- for foreign_node_id in self.get_foreign_nodes():
- try:
- foreign_node = ForeignNodes(self.api,[foreign_node_id])[0]
- foreign_node.delete(commit)
- except:
- print "Glitch : a foreign node instance was uncleanly deleted"
+ for foreign_node in Nodes (self.api, self.get_node_ids()):
+ foreign_node.delete(commit)
# remove the peer
self['deleted'] = True
self.sync(commit)
- def get_foreign_nodes (self):
+ def get_node_ids (self):
"""
- returns a list of the foreign nodes in this peer
+ returns a list of the node ids in this peer
"""
sql="SELECT node_ids FROM peer_nodes WHERE peer_id=%d"%self['peer_id']
node_ids = self.api.db.selectall(sql)
return node_ids[0]['node_ids']
- def manage_node (self, foreign_node, add_if_true, commit=True):
- """
- associate/dissociate a foreign node to/from a peer
- foreign_node is a local object that describes a remote node
- convention is:
- if add_if_true is None : performs dissociation
- otherwise: performs association
- """
-
- assert 'peer_id' in self
- assert 'node_id' in foreign_node
-
- peer_id = self['peer_id']
- node_id = foreign_node ['node_id']
-
- if add_if_true:
- ### ADDING
- sql = "INSERT INTO peer_node VALUES (%d,%d)" % (peer_id,node_id)
- self.api.db.do(sql)
- if self['node_ids'] is None:
- self['node_ids']=[node_id,]
- else:
- self['node_ids'].append(node_id)
- ### DELETING
- else:
- sql = "DELETE FROM peer_node WHERE peer_id=%d AND node_id=%d" % (peer_id,node_id)
- self.api.db.do(sql)
- self['node_ids'].remove(node_id)
-
- if commit:
- self.api.db.commit()
-
- def manage_slice (self, foreign_slice, add_if_true, commit=True):
- """
- associate/dissociate a foreign node to/from a peer
- foreign_slice is a local object that describes a remote slice
- alien_id is the unique id as provided by the remote peer
- convention is:
- if add_if_true is None : performs dissociation
- otherwise: performs association
- """
-
- assert 'peer_id' in self
- assert 'slice_id' in foreign_slice
-
- peer_id = self['peer_id']
- slice_id = foreign_slice ['slice_id']
-
- if add_if_true:
- ### ADDING
- sql = "INSERT INTO peer_slice VALUES (%d,%d)" % (peer_id,slice_id)
- self.api.db.do(sql)
- if self['slice_ids'] is None:
- self['slice_ids']=[slice_id,]
- else:
- self['slice_ids'].append(slice_id)
- ### DELETING
- else:
- sql = "DELETE FROM peer_slice WHERE peer_id=%d AND slice_id=%d" % (peer_id,slice_id)
- self.api.db.do(sql)
- self['slice_ids'].remove(slice_id)
-
- if commit:
- self.api.db.commit()
-
def refresh_nodes (self, peer_get_nodes):
"""
refreshes the foreign_nodes and peer_node tables
# we get the whole table just in case
# a host would have switched from one plc to the other
- local_foreign_nodes = ForeignNodes (self.api)
+ local_foreign_nodes = Nodes (self.api,None,None,'foreign')
+
# index it by hostname for searching later
- local_foreign_nodes_index = local_foreign_nodes.dict('hostname')
+ #local_foreign_nodes_index=local_foreign_nodes.dict('hostname')
+ local_foreign_nodes_index={}
+ for node in local_foreign_nodes:
+ local_foreign_nodes_index[node['hostname']]=node
### mark entries for this peer outofdate
old_count=0;
try:
foreign_node = local_foreign_nodes_index[hostname]
if foreign_node['peer_id'] != peer_id:
- ### the node has changed its plc, needs to update peer_node
- old_peer_id = foreign_node['peer_id']
- old_peers=Peers(self.api,[peer_id])
- assert old_peer[0]
- # remove from previous peer
- old_peers[0].manage_node(foreign_node,False,False)
- # add to new peer
- self.manage_node(foreign_node,True,True)
+# ### the node has changed its plc
foreign_node['peer_id'] = peer_id
### update it anyway: copy other relevant fields
for field in remote_fields:
foreign_node.uptodate=True
foreign_node.sync()
except:
- new_foreign_node = ForeignNode(self.api, {'hostname':hostname})
+ new_foreign_node = Node(self.api, {'hostname':hostname})
+ new_foreign_node['peer_id']=peer_id
for field in remote_fields:
new_foreign_node[field]=node[field]
### need to sync so we get a node_id
new_foreign_node.sync()
new_foreign_node.uptodate = True
- self.manage_node(new_foreign_node,True,True)
+# self.manage_node(new_foreign_node,True,True)
local_foreign_nodes_index[hostname]=new_foreign_node
### delete entries that are not uptodate
# we get the whole table just in case
# a host would have switched from one plc to the other
- local_foreign_slices = ForeignSlices (self.api)
+ local_foreign_slices = Slices (self.api,{'~peer_id':None})
# index it by name for searching later
local_foreign_slices_index = local_foreign_slices.dict('name')
### scan the new entries, and mark them uptodate
new_count=0
for slice in peer_get_slices:
+
### ignore system-wide slices
if slice['creator_person_id'] == 1:
continue
try:
foreign_slice = local_foreign_slices_index[name]
if foreign_slice['peer_id'] != peer_id:
- ### the slice has changed its plc, needs to update peer_slice
- old_peer_id = foreign_slice['peer_id']
- old_peers=Peers(self.api,[peer_id])
- assert old_peer[0]
- # remove from previous peer
- old_peers[0].manage_slice(foreign_slice,False,False)
- # add to new peer
- self.manage_slice(foreign_slice,True,True)
- foreign_slice['peer_id'] = peer_id
+ # more suspucious ? - the slice moved on another peer
+ foreign_slice['peer_id'] = peer_id;
except:
- foreign_slice = ForeignSlice(self.api, {'name':name})
+ foreign_slice = Slice(self.api, {'name':name})
+ foreign_slice['peer_id']=self['peer_id']
# ### xxx temporary
# foreign_slice['site_id']=1
### need to sync so we get a slice_id
foreign_slice.sync()
- self.manage_slice(foreign_slice,True,True)
# insert in index
local_foreign_slices_index[name]=foreign_slice
updated_node_ids = []
for alien_node_id in slice['node_ids']:
try:
- local_node_id=self.locate_alien_node_id_in_foreign_nodes(peer_foreign_nodes_dict,alien_node_id)
+ local_node_id=self.locate_alien_node_id_in_foreign_nodes(peer_foreign_nodes_dict,
+ alien_node_id)
updated_node_ids.append(local_node_id)
except:
# this node_id is not in our scope
from PLC.Table import Row, Table
from PLC.SliceInstantiations import SliceInstantiations
from PLC.Nodes import Node, Nodes
-from PLC.ForeignNodes import ForeignNode, ForeignNodes
import PLC.Persons
class Slice(Row):
fields = {
'slice_id': Parameter(int, "Slice identifier"),
'site_id': Parameter(int, "Identifier of the site to which this slice belongs"),
+ 'peer_id': Parameter(int, "Peer at which this slice was created", nullok = True),
'name': Parameter(str, "Slice name", max = 32),
'instantiation': Parameter(str, "Slice instantiation state"),
'url': Parameter(str, "URL further describing this slice", max = 254, nullok = True),
"""
assert 'slice_id' in self
- assert isinstance(node, (Node,ForeignNode))
+ assert isinstance(node, Node)
assert 'node_id' in node
slice_id = self['slice_id']
"""
assert 'slice_id' in self
- assert isinstance(node, (Node,ForeignNode))
+ assert isinstance(node, Node)
assert 'node_id' in node
slice_id = self['slice_id']
self['node_ids'].remove(node_id)
node['slice_ids'].remove(slice_id)
+ ########## for foreign slices update, from ForeignSlices
+ def purge_slice_node (self,commit=True):
+ sql = "DELETE FROM slice_node WHERE slice_id=%d"%self['slice_id']
+ self.api.db.do(sql)
+ if commit:
+ self.api.db.commit()
+
+ def add_slice_nodes (self, node_ids, commit=True):
+ slice_id = self['slice_id']
+ ### xxx needs to be optimized
+ ### tried to figure a way to use a single sql statement
+ ### like: insert into table (x,y) values (1,2),(3,4);
+ ### but apparently this is not supported under postgresql
+ for node_id in node_ids:
+ sql="INSERT INTO slice_node VALUES (%d,%d)"%(slice_id,node_id)
+ self.api.db.do(sql)
+ if commit:
+ self.api.db.commit()
+
+ def update_slice_nodes (self, node_ids):
+ # xxx to be optimized
+ # we could compute the (set) difference between
+ # current and updated set of node_ids
+ # and invoke the DB only based on that
+ #
+ # for now : clean all entries for this slice
+ self.purge_slice_node()
+ # and re-install new list
+ self.add_slice_nodes (node_ids)
+
+ ##########
def sync(self, commit = True):
"""
Add or update a slice.
global number_nodes, number_slices
number_nodes=nodes
number_slices=slices
+
+def fast():
+ define_test(1,1)
define_test (nodes=5,slices=3)
for i in args:
url=plc[i]['url-format']%plc[i]['hostname']
plc[i]['url']=url
- s[i]=xmlrpclib.Server(url)
+ s[i]=xmlrpclib.ServerProxy(url,allow_none=True)
print 'initializing s[%d]'%i,url
aa[i]={'Username':plc[i]['builtin_admin_id'],
'AuthMethod':'password',
def check_nodes (en,ef,args=[1,2]):
global plc,s,a
for i in args:
- n=len(s[i].GetNodes(a[i]))
- f=len(s[i].GetForeignNodes(a[i]))
+ # use a single request and sort afterwards for efficiency
+ # could have used GetNodes's scope as well
+ all_nodes = s[i].GetNodes(a[i])
+ n = len ([ x for x in all_nodes if x['peer_id'] is None])
+ f = len ([ x for x in all_nodes if x['peer_id'] is not None])
print '%02d: Checking nodes: got %d local (e=%d) & %d foreign (e=%d)'%(i,n,en,f,ef)
assert n==en
assert f==ef
def check_slices (els,efs,args=[1,2]):
global plc,s,a
for i in args:
- ls=len(s[i].GetSlices(a[i]))
- fs=len(s[i].GetForeignSlices(a[i]))
+ ls=len(s[i].GetSlices(a[i],{'peer_id':None}))
+ fs=len(s[i].GetSlices(a[i],{'~peer_id':None}))
print '%02d: Checking slices: got %d local (e=%d) & %d foreign (e=%d)'%(i,ls,els,fs,efs)
assert els==ls
assert efs==fs
def show_nodes (i,node_ids):
- for message,nodes in [ ['LOC',s[i].GetNodes(a[i],node_ids)],
- ['FOR',s[i].GetForeignNodes(a[i],node_ids)] ]:
+ # same as above
+ all_nodes = s[i].GetNodes(a[i],node_ids)
+ loc_nodes = filter (lambda n: n['peer_id'] is None, all_nodes)
+ for_nodes = filter (lambda n: n['peer_id'] is not None, all_nodes)
+
+ for message,nodes in [ ['LOC',loc_nodes], ['FOR',for_nodes] ] :
if nodes:
print '[%s:%d] : '%(message,len(nodes)),
for node in nodes:
peer=peer_index(i)
if is_local_slice:
sname=slice_name(i,ns)
- slice=s[i].GetSlices(a[i],[sname])[0]
+ slice=s[i].GetSlices(a[i],{'name':[sname],'peer_id':None})[0]
message='local'
else:
sname=slice_name(peer,ns)
- slice=s[i].GetForeignSlices(a[i],[sname])[0]
+ slice=s[i].GetSlices(a[i],{'name':[sname],'~peer_id':None})[0]
message='foreign'
print '%02d: %s slice %s (e=%d) '%(i,message,sname,expected_nodes),
slice_node_ids=slice['node_ids']
def check_slivers_n (nn,esn,args=[1,2]):
global plc,s,a
for i in args:
- nodename=node_name(i,i)
+ nodename=node_name(i,nn)
ndict= s[i].GetSlivers(a[i],[nodename])[0]
assert ndict['hostname'] == nodename
slivers = ndict['slivers']
print 'got ',retcod
####################
-def get_node_id(i,nodename):
- return s[i].GetNodes(a[i],[nodename])[0]['node_id']
+# retrieves node_id from hostname - checks for local nodes only
+def get_local_node_id(i,nodename):
+ return s[i].GetNodes(a[i],[nodename],None,'local')[0]['node_id']
+# clean all local nodes - foreign nodes are not supposed to be cleaned up manually
def clean_all_nodes (args=[1,2]):
global plc,s,a
for i in args:
print '%02d: Cleaning all nodes'%i
- for node in s[i].GetNodes(a[i]):
+ loc_nodes = s[i].GetNodes(a[i],None,None,'local')
+ for node in loc_nodes:
print '%02d: > Cleaning node %d'%(i,node['node_id'])
s[i].DeleteNode(a[i],node['node_id'])
for i in args:
nodename = node_name(i,nn)
try:
- get_node_id(i,nodename)
+ get_local_node_id(i,nodename)
except:
n=s[i].AddNode(a[i],1,{'hostname': nodename})
print '%02d: Added node %d %s'%(i,n,node_name(i,i))
global plc,s,a
for i in args:
nodename = node_name(i,nn)
- node_id = get_node_id (i,nodename)
+ node_id = get_local_node_id (i,nodename)
retcod=s[i].DeleteNode(a[i],nodename)
print '%02d: Deleted node %d, returns %s'%(i,node_id,retcod)
global plc,s,a
for i in args:
print '%02d: Cleaning all slices'%i
- for slice in s[i].GetSlices(a[i]):
+ for slice in s[i].GetSlices(a[i],{'peer_id':None}):
slice_id = slice['slice_id']
if slice_id not in system_slices_ids:
print '%02d: > Cleaning slice %d'%(i,slice_id)
s[i].DeleteSlice(a[i],slice_id)
-def get_slice_id (i,name):
- return s[i].GetSlices(a[i],[name])[0]['slice_id']
+def get_local_slice_id (i,name):
+ return s[i].GetSlices(a[i],{'name':[name],'peer_id':None})[0]['slice_id']
def test03_slice (args=[1,2]):
for n in myrange(number_slices):
global plc,s,a
for i in args:
peer=peer_index(i)
- slice_id = get_slice_id (i,slice_name (i,ns))
+ slice_id = get_local_slice_id (i,slice_name (i,ns))
if is_local:
hostnames=[node_name(i,nn) for nn in nnl]
test01_refresh ()
check_nodes (number_nodes,number_nodes,)
+def populate ():
+ test02_node()
+ test03_slice([1])
+ test01_refresh ([1])
+ test04_slice_add_lnode([1])
+ test04_slice_add_fnode([1])
+ test01_refresh()
+
def test_all_addslices ():
# reset
@echo 'Restarting PLC'
@chroot $(CHROOT) service plc restart
+http:
+ @echo 'Restarting httpd'
+ @chroot $(CHROOT) /etc/plc.d/httpd stop ; chroot $(CHROOT) /etc/plc.d/httpd start
+
####################
UPGRADE=down up reconfig restart
cp TestPeers.out TestPeers.ref
#######
-HELP=rpm db-dump
+HELP=rpm db-dump http
help:
@echo known targets:
--
-- Copyright (C) 2006 The Trustees of Princeton University
--
--- $Id: planetlab4.sql,v 1.40 2006/11/17 10:43:17 thierry Exp $
+-- $Id: planetlab4.sql,v 1.41 2006/11/17 19:31:08 tmack Exp $
--
--------------------------------------------------------------------------------
-- Mandatory
node_id serial PRIMARY KEY, -- Node identifier
hostname text NOT NULL, -- Node hostname
- site_id integer REFERENCES sites, -- At which site (clause NOT NULL removed for foreign_nodes)
+ -- temporarily removed NOT NULL clause for foreign_nodes
+ site_id integer REFERENCES sites, -- At which site
+ -- may be NULL for local_nodes
+ peer_id integer REFERENCES peers, -- From which peer
+
boot_state text REFERENCES boot_states NOT NULL DEFAULT 'inst', -- Node boot state
deleted boolean NOT NULL DEFAULT false, -- Is deleted
FROM nodes
GROUP BY site_id;
--- Nodes - peers relationship
-CREATE TABLE peer_node (
- peer_id integer REFERENCES peers NOT NULL, -- Peer identifier
- node_id integer REFERENCES nodes NOT NULL, -- (Local) node identifier
- PRIMARY KEY (peer_id, node_id),
- UNIQUE (node_id) -- Nodes can only be at one peer
-) WITH OIDS;
-CREATE INDEX peer_node_peer_id_idx ON peer_node (peer_id);
-
-- Nodes at each peer
CREATE VIEW peer_nodes AS
SELECT peer_id,
array_accum(node_id) AS node_ids
-FROM peer_node
+FROM nodes
GROUP BY peer_id;
--------------------------------------------------------------------------------
slice_id serial PRIMARY KEY, -- Slice identifier
-- xxx temporarily remove the NOT NULL constraint
site_id integer REFERENCES sites, -- Site identifier
+ peer_id integer REFERENCES peers, -- on which peer
+
name text NOT NULL, -- Slice name
instantiation text REFERENCES slice_instantiations NOT NULL DEFAULT 'plc-instantiated', -- Slice state, e.g. plc-instantiated
url text, -- Project URL
WHERE is_deleted is false
GROUP BY site_id;
--- Slices - peer relationship
-CREATE TABLE peer_slice (
- peer_id integer REFERENCES peers NOT NULL, -- peer primary key
- slice_id integer REFERENCES slices NOT NULL, -- node primary key
- PRIMARY KEY (peer_id, slice_id)
-) WITH OIDS;
-CREATE INDEX peer_slice_peer_id_idx ON peer_slice (peer_id);
-CREATE INDEX peer_slice_slice_id_idx ON peer_slice (slice_id);
-
CREATE VIEW peer_slices AS
SELECT peer_id,
array_accum(slice_id) AS slice_ids
-FROM peer_slice
+FROM slices
GROUP BY peer_id;
-- Slice membership
LEFT JOIN person_keys USING (person_id)
LEFT JOIN person_slices USING (person_id);
+CREATE VIEW view_peers AS
+SELECT
+peers.*,
+peer_nodes.node_ids,
+peer_slices.slice_ids
+FROM peers
+LEFT JOIN peer_nodes USING (peer_id)
+LEFT JOIN peer_slices USING (peer_id);
+
CREATE VIEW view_nodes AS
SELECT
nodes.node_id,
nodes.hostname,
nodes.site_id,
+nodes.peer_id,
nodes.boot_state,
nodes.deleted,
nodes.model,
COALESCE(node_conf_files.conf_file_ids, '{}') AS conf_file_ids,
node_session.session_id AS session
FROM nodes
-LEFT JOIN peer_node USING (node_id)
LEFT JOIN node_nodenetworks USING (node_id)
LEFT JOIN node_nodegroups USING (node_id)
LEFT JOIN node_slices USING (node_id)
LEFT JOIN node_pcus USING (node_id)
LEFT JOIN node_conf_files USING (node_id)
-LEFT JOIN node_session USING (node_id)
-WHERE peer_node.peer_id IS NULL;
-
-CREATE VIEW view_peers AS
-SELECT
-peers.*,
-peer_nodes.node_ids,
-peer_slices.slice_ids
-FROM peers
-LEFT JOIN peer_nodes USING (peer_id)
-LEFT JOIN peer_slices USING (peer_id);
-
-CREATE VIEW view_foreign_nodes AS
-SELECT
-nodes.node_id,
-nodes.hostname,
-peer_node.peer_id,
-nodes.boot_state,
-nodes.model,
-nodes.version,
-CAST(date_part('epoch', nodes.date_created) AS bigint) AS date_created,
-CAST(date_part('epoch', nodes.last_updated) AS bigint) AS last_updated,
-COALESCE(node_slices.slice_ids, '{}') AS slice_ids,
-nodes.deleted
-FROM nodes
-LEFT JOIN peer_node USING (node_id)
-LEFT JOIN node_slices USING (node_id)
-WHERE peer_node.peer_id IS NOT NULL;
+LEFT JOIN node_session USING (node_id);
CREATE VIEW view_nodegroups AS
SELECT
SELECT
slices.slice_id,
slices.site_id,
+slices.peer_id,
slices.name,
slices.instantiation,
slices.url,
COALESCE(slice_persons.person_ids, '{}') AS person_ids,
COALESCE(slice_attributes.slice_attribute_ids, '{}') AS slice_attribute_ids
FROM slices
-LEFT JOIN peer_slice USING (slice_id)
LEFT JOIN slice_nodes USING (slice_id)
LEFT JOIN slice_persons USING (slice_id)
-LEFT JOIN slice_attributes USING (slice_id)
-WHERE peer_slice.peer_id IS NULL
-AND slices.site_id IS NOT NULL
-AND slices.creator_person_id IS NOT NULL;
-
-CREATE VIEW view_foreign_slices AS
-SELECT
-slices.slice_id,
-slices.name,
-peer_slice.peer_id,
-slices.instantiation,
-slices.url,
-slices.description,
-slices.max_nodes,
-slices.is_deleted,
-CAST(date_part('epoch', slices.created) AS bigint) AS created,
-CAST(date_part('epoch', slices.expires) AS bigint) AS expires,
-COALESCE(slice_nodes.node_ids, '{}') AS node_ids
-FROM slices
-LEFT JOIN peer_slice USING (slice_id)
-LEFT JOIN slice_nodes USING (slice_id)
-WHERE peer_slice.peer_id IS NOT NULL;
+LEFT JOIN slice_attributes USING (slice_id);
--
CREATE VIEW view_slice_attributes AS