other peering instances of myplc
"""
- table_name = 'foreign_nodes'
- primary_key = 'foreign_node_id'
+ table_name = 'nodes'
+ primary_key = 'node_id'
fields = {
- 'foreign_node_id': Parameter (int, "Foreign Node Id"),
+ 'node_id': Parameter (int, "Node Id"),
'hostname': Parameter (str, "Node name"),
- 'boot_state' : Parameter (str, "Boot state"),
'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"),
}
def __init__(self,api,fields={},uptodate=True):
Row.__init__(self,api,fields)
self.uptodate=uptodate
+ def delete (self, commit=True):
+ """
+ Delete existing foreign node.
+ """
+ print 'in ForeignNode::delete',self
+ self['deleted']=True
+ self.sync(commit)
+
+
class ForeignNodes (Table):
def __init__ (self, api, foreign_node_id_or_hostname_list=None):
self.api=api
sql =""
- sql += "SELECT %s FROM foreign_nodes " % ", ".join(ForeignNode.fields)
- sql += "WHERE foreign_nodes.deleted IS False "
+ sql += "SELECT %s FROM view_foreign_nodes " % ", ".join(ForeignNode.fields)
+ sql += "WHERE view_foreign_nodes.deleted IS False "
if foreign_node_id_or_hostname_list:
foreign_node_id_list = [ str(x) for x in foreign_node_id_or_hostname_list
if isinstance(x, StringTypes)]
sql += " AND (False"
if foreign_node_id_list:
- sql += " OR foreign_node_id in (%s)" % ", ".join(foreign_node_id_list)
+ sql += " OR node_id in (%s)" % ", ".join(foreign_node_id_list)
if hostname_list:
## figure how to retrieve peer_id from the hostname(s)
sql += " OR hostname IN (%s)" % ", ".join(api.db.quote(hostname_list))
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. If the slice is
+ 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
+
+ If the slice is
already associated with a node, no errors are returned.
Returns 1 if successful, faults otherwise.
slice = slices.values()[0]
- # Get specified nodes
- nodes = Nodes(self.api, node_id_or_hostname_list).values()
-
if 'admin' not in self.caller['roles']:
if self.caller['person_id'] in slice['person_ids']:
pass
+ # Thierry : I cannot figure out how this works
+ # how is having pi role related to being in a slice ?
elif 'pi' not in self.caller['roles']:
raise PLCPermissionDenied, "Not a member of the specified slice"
elif slice['site_id'] not in self.caller['site_ids']:
raise PLCPermissionDenied, "Specified slice not associated with any of your sites"
- # Add slice to all nodes found
+ # Get specified nodes, and them to the slice
+ nodes = Nodes(self.api, node_id_or_hostname_list).values()
for node in nodes:
if slice['slice_id'] not in node['slice_ids']:
slice.add_node(node, commit = False)
+ # the same for foreign_nodes
+ foreign_nodes = ForeignNodes (self.api, node_id_or_hostname_list).values()
+ for foreign_node in foreign_nodes:
+ if slice['slice_id'] not in foreign_node['slice_ids']:
+ slice.add_node (foreign_node, is_foreign_node=True, commit=False)
+
slice.sync()
self.object_ids = [node['node_id'] for node in nodes]
roles = ['admin']
accepts = [ Auth(),
- [ Mixed(ForeignNode.fields['foreign_node_id'],
+ [ Mixed(ForeignNode.fields['node_id'],
ForeignNode.fields['hostname'])]
]
--- /dev/null
+#
+# Thierry Parmentelat - INRIA
+#
+
+import xmlrpclib
+
+from PLC.Faults import *
+from PLC.Method import Method
+from PLC.Parameter import Parameter, Mixed
+from PLC.Auth import Auth
+
+from PLC.Peers import Peer, Peers
+from PLC.Persons import Person, Persons
+from PLC.ForeignNodes import ForeignNode, ForeignNodes
+
+
+class RefreshPeer(Method):
+ """
+ Query a peer PLC for its list of nodes, and refreshes
+ the local database accordingly
+
+ Returns None
+ """
+
+ roles = ['admin']
+
+ accepts = [ Auth(),
+ Parameter (int, "Peer id") ]
+
+ returns = None
+
+ def call (self, auth, peer_id):
+
+ ### retrieve peer info
+ peers = Peers (self.api)
+ peer = peers[peer_id]
+
+ ### retrieve account info
+ person_id = peer['person_id']
+ persons = Persons (self.api,[person_id])
+ person = persons[person_id]
+
+ ### build up foreign auth
+ auth={ 'Username': person['email'],
+ 'AuthMethod' : 'password',
+ 'AuthString' : person['password'],
+ 'Role' : 'admin' }
+
+ ## connect to the peer's API
+ apiserver = xmlrpclib.Server (peer['peer_url']+"/PLCAPI/")
+ print 'auth',auth
+ current_peer_nodes = apiserver.GetNodes(auth,[])
+
+ ## manual feed for tests
+# n1 = {'hostname': 'n1.plc', 'boot_state': 'inst'}
+# n2 = {'hostname': 'n2.plc', 'boot_state': 'inst'}
+# n3 = {'hostname': 'n3.plc', 'boot_state': 'inst'}
+ n11={'session': None, 'slice_ids': [], 'nodegroup_ids': [], 'last_updated': 1162884349, 'version': None, 'nodenetwork_ids': [], 'boot_state': 'inst', 'hostname': 'n11.plc1.org', 'site_id': 1, 'ports': None, 'pcu_ids': [], 'boot_nonce': None, 'node_id': 1, 'root_person_ids': [], 'key': None, 'date_created': 1162884349, 'model': None, 'conf_file_ids': [], 'ssh_rsa_key': None}
+ n12={'session': None, 'slice_ids': [], 'nodegroup_ids': [], 'last_updated': 1162884349, 'version': None, 'nodenetwork_ids': [], 'boot_state': 'inst', 'hostname': 'n12.plc1.org', 'site_id': 1, 'ports': None, 'pcu_ids': [], 'boot_nonce': None, 'node_id': 1, 'root_person_ids': [], 'key': None, 'date_created': 1162884349, 'model': None, 'conf_file_ids': [], 'ssh_rsa_key': None}
+ n21={'session': None, 'slice_ids': [], 'nodegroup_ids': [], 'last_updated': 1162884349, 'version': None, 'nodenetwork_ids': [], 'boot_state': 'boot', 'hostname': 'n21.plc2.org', 'site_id': 1, 'ports': None, 'pcu_ids': [], 'boot_nonce': None, 'node_id': 1, 'root_person_ids': [], 'key': None, 'date_created': 1162884349, 'model': None, 'conf_file_ids': [], 'ssh_rsa_key': None}
+ n22={'session': None, 'slice_ids': [], 'nodegroup_ids': [], 'last_updated': 1162884349, 'version': None, 'nodenetwork_ids': [], 'boot_state': 'boot', 'hostname': 'n22.plc2.org', 'site_id': 1, 'ports': None, 'pcu_ids': [], 'boot_nonce': None, 'node_id': 1, 'root_person_ids': [], 'key': None, 'date_created': 1162884349, 'model': None, 'conf_file_ids': [], 'ssh_rsa_key': None}
+
+# current_peer_nodes = [n21,n22]
+
+ ### now to the db
+ # we get the whole table just in case
+ # a host would have switched from one plc to the other
+ foreign_nodes = ForeignNodes (self.api)
+
+ ### mark entries for this peer outofdate
+ for foreign_node in foreign_nodes.values():
+ if foreign_node['peer_id'] == peer_id:
+ foreign_node.uptodate=False
+
+ ### these fields get copied through
+ remote_fields = ['boot_state','model','version','date_created','date_updated']
+
+ ### scan the new entries, and mark them uptodate
+ for node in current_peer_nodes:
+ hostname = node['hostname']
+ foreign_node = foreign_nodes.get(hostname)
+ if foreign_node:
+ ### update it anyway
+ foreign_node['cached'] = True
+ foreign_node['peer_id'] = peer_id
+ # copy other relevant fields
+ for field in remote_fields:
+ foreign_node[field]=node[field]
+ # this row is valid
+ foreign_node.uptodate = True
+ else:
+ foreign_nodes[hostname] = ForeignNode(self.api,
+ {'hostname':hostname,
+ 'cached':True,
+ 'peer_id':peer_id,})
+ for field in remote_fields:
+ foreign_nodes[hostname][field]=node[field]
+
+ foreign_nodes[hostname].sync()
+
+ ### delete entries that are not uptodate
+ [ x.delete() for x in foreign_nodes.values() if not x.uptodate ]
+
+++ /dev/null
-#
-# Thierry Parmentelat - INRIA
-#
-
-import xmlrpclib
-
-from PLC.Faults import *
-from PLC.Method import Method
-from PLC.Parameter import Parameter, Mixed
-from PLC.Auth import Auth
-
-from PLC.Peers import Peer, Peers
-from PLC.Persons import Person, Persons
-from PLC.ForeignNodes import ForeignNode, ForeignNodes
-
-
-class UpdatePeer(Method):
- """
- Query a peer PLC for its list of nodes, and refreshes
- the local database accordingly
-
- Returns None
- """
-
- roles = ['admin']
-
- accepts = [ Auth(),
- Parameter (int, "Peer id") ]
-
- returns = None
-
- def call (self, auth, peer_id):
-
- ### retrieve peer info
- peers = Peers (self.api)
- peer = peers[peer_id]
-
- ### retrieve account info
- person_id = peer['person_id']
- persons = Persons (self.api,[person_id])
- person = persons[person_id]
-
- ### build up foreign auth
- auth={ 'Username': person['email'],
- 'AuthMethod' : 'password',
- 'AuthString' : person['password'],
- 'Role' : 'admin' }
-
- ## connect to the peer's API
- apiserver = xmlrpclib.Server (peer['peer_url']+"/PLCAPI/")
- print 'auth',auth
- current_peer_nodes = apiserver.GetNodes(auth,[])
-
- ## manual feed for tests
-# n1 = {'hostname': 'n1.plc', 'boot_state': 'inst'}
-# n2 = {'hostname': 'n2.plc', 'boot_state': 'inst'}
-# n3 = {'hostname': 'n3.plc', 'boot_state': 'inst'}
-# current_peer_nodes = [n2,n3]
-
- ### now to the db
- # we get the whole table just in case
- # a host would have switched from one plc to the other
- foreign_nodes = ForeignNodes (self.api)
-
- ### mark entries for this peer outofdate
- for foreign_node in foreign_nodes.values():
- if foreign_node['peer_id'] == peer_id:
- foreign_node.uptodate=False
-
- ### scan the new entries, and mark them uptodate
- for node in current_peer_nodes:
- hostname = node['hostname']
- foreign_node = foreign_nodes.get(hostname)
- if foreign_node:
- ### update it anyway
- foreign_node['peer_id'] = peer_id
- foreign_node['boot_state'] = node['boot_state']
- foreign_node.uptodate = True
- else:
- foreign_nodes[hostname] = ForeignNode(self.api,
- {'hostname':hostname,
- 'boot_state':node['boot_state'],
- 'peer_id':peer_id})
- foreign_nodes[hostname].sync()
-
- ### delete entries that are not uptodate
- [ x.delete() for x in foreign_nodes.values() if not x.uptodate ]
-
# Mark Huang <mlhuang@cs.princeton.edu>
# Copyright (C) 2006 The Trustees of Princeton University
#
-# $Id: Nodes.py,v 1.15 2006/10/27 15:32:43 mlhuang Exp $
+# $Id: Nodes.py,v 1.16 2006/11/02 18:32:55 mlhuang Exp $
#
from types import StringTypes
def __init__(self, api, node_id_or_hostname_list = None):
self.api = api
- sql = "SELECT %s FROM view_nodes WHERE deleted IS False" % \
- ", ".join(Node.fields)
+ sql = ""
+ sql += "SELECT %s FROM view_nodes " % ", ".join(Node.fields)
+ sql += "WHERE deleted IS False"
if node_id_or_hostname_list:
# Separate the list into integers and strings
'peer_id' : Parameter (int, "Peer identifier"),
'peername' : Parameter (str, "Peer name"),
'peer_url' : Parameter (str, "Peer API url"),
- 'person_id' : Parameter (int, "person_id of the account used to log there"),
- 'foreign_node_ids' : Parameter ([int], "doc")
+ 'person_id' : Parameter (int, "Person_id of the account storing credentials - temporary"),
+ 'node_ids' : Parameter ([int], "This peer's nodes ids")
}
def validate_peer_url (self, url):
for row in rows:
self[row['peer_id']] = peer = Peer(api,row)
- for aggregate in ['foreign_node_ids']:
+ for aggregate in ['node_ids']:
if not peer.has_key(aggregate) or peer[aggregate] is None:
peer[aggregate] = []
else:
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):
self['person_ids'].remove(person_id)
person['slice_ids'].remove(slice_id)
- def add_node(self, node, commit = True):
+ def add_node(self, node, is_foreign_node = False, commit = True):
"""
Add node to existing slice.
"""
assert 'slice_id' in self
- assert isinstance(node, Node)
+ if not is_foreign_node:
+ assert isinstance(node, Node)
+ else:
+ assert isinstance(node, ForeignNode)
assert 'node_id' in node
slice_id = self['slice_id']
--
-- Copyright (C) 2006 The Trustees of Princeton University
--
--- $Id: planetlab4.sql,v 1.26 2006/11/03 16:05:20 mlhuang Exp $
+-- $Id: planetlab4.sql,v 1.27 2006/11/03 20:36:05 thierry Exp $
--
--------------------------------------------------------------------------------
INSERT INTO roles (role_id, name) VALUES (40, 'tech');
INSERT INTO roles (role_id, name) VALUES (1000, 'node');
INSERT INTO roles (role_id, name) VALUES (2000, 'anonymous');
+-- xxx not sure this us useful yet
+--INSERT INTO roles (role_id, name) VALUES (3000, 'peer');
CREATE TABLE person_role (
person_id integer REFERENCES persons NOT NULL, -- Account identifier
INSERT INTO boot_states (boot_state) VALUES ('rcnf');
INSERT INTO boot_states (boot_state) VALUES ('new');
+-- Peers
+CREATE TABLE peers (
+ peer_id serial PRIMARY KEY, -- identifier
+ peername text NOT NULL, -- free text
+ peer_url text NOT NULL, -- the url of that peer's API
+ person_id integer REFERENCES persons NOT NULL, -- the account we use for logging in
+
+ deleted boolean NOT NULL DEFAULT false
+) WITH OIDS;
+
+
-- Nodes
CREATE TABLE nodes (
-- Mandatory
node_id serial PRIMARY KEY, -- Node identifier
hostname text NOT NULL, -- Node hostname
- site_id integer REFERENCES sites NOT NULL, -- At which site
+ site_id integer REFERENCES sites, -- At which site (clause NOT NULL removed for foreign_nodes)
boot_state text REFERENCES boot_states NOT NULL DEFAULT 'inst', -- Node boot state
+ cached boolean NOT NULL DEFAULT false, -- is this entry cached from a peer ?
+ peer_id integer REFERENCES peers, -- if cached, then from what peer
deleted boolean NOT NULL DEFAULT false, -- Is deleted
-- Optional
FROM nodes
GROUP BY site_id;
+-- Nodes at each peer
+CREATE VIEW peer_nodes AS
+SELECT peer_id,
+array_to_string(array_accum(node_id), ',') AS node_ids
+FROM nodes
+GROUP BY peer_id;
+
+CREATE VIEW view_peers AS
+SELECT
+peers.*,
+peer_nodes.node_ids
+FROM peers
+LEFT JOIN peer_nodes USING (peer_id);
+
--------------------------------------------------------------------------------
-- Node groups
--------------------------------------------------------------------------------
nodes.hostname,
nodes.site_id,
nodes.boot_state,
-nodes.deleted,
nodes.model,
nodes.boot_nonce,
nodes.version,
node_pcus.pcu_ids,
node_pcus.ports,
node_conf_files.conf_file_ids,
-node_session.session_id AS session
+node_session.session_id AS session,
+nodes.deleted
FROM nodes
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);
+LEFT JOIN node_session USING (node_id)
+WHERE nodes.cached=False;
+
+CREATE VIEW view_foreign_nodes AS
+SELECT
+nodes.node_id,
+nodes.hostname,
+nodes.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,
+node_slices.slice_ids,
+nodes.deleted
+FROM nodes
+LEFT JOIN node_slices USING (node_id)
+WHERE nodes.cached=True AND nodes.deleted=False;
CREATE VIEW view_nodegroups AS
SELECT
('pl', 'PlanetLab Central', 'PLC', 100);
-- federation stuff starting here
-INSERT INTO roles (role_id, name) VALUES (3000, 'peer');
-CREATE TABLE peers (
- peer_id serial PRIMARY KEY, -- identifier
- peername text NOT NULL, -- free text
- peer_url text NOT NULL, -- the url of that peer's API
- person_id integer REFERENCES persons NOT NULL, -- the account we use for logging in
-
- deleted boolean NOT NULL DEFAULT false
-) WITH OIDS;
+--CREATE TABLE foreign_nodes (
+-- foreign_node_id serial PRIMARY KEY, -- identifier
+-- hostname text NOT NULL,
+-- boot_state text NOT NULL,
+-- peer_id integer REFERENCES peers NOT NULL,
+--
+-- deleted boolean NOT NULL DEFAULT false
+--) WITH OIDS;
-CREATE TABLE foreign_nodes (
- foreign_node_id serial PRIMARY KEY, -- identifier
- hostname text NOT NULL,
- boot_state text NOT NULL,
- peer_id integer REFERENCES peers NOT NULL,
-
- deleted boolean NOT NULL DEFAULT false
-) WITH OIDS;
+--CREATE VIEW peer_foreign_nodes AS
+--SELECT peer_id,
+--array_to_string(array_accum(foreign_node_id), ',') AS foreign_node_ids
+--FROM foreign_nodes
+--GROUP BY peer_id;
-CREATE VIEW peer_foreign_nodes AS
-SELECT peer_id,
-array_to_string(array_accum(foreign_node_id), ',') AS foreign_node_ids
-FROM foreign_nodes
-GROUP BY peer_id;
-CREATE VIEW view_peers AS
-SELECT
-peers.*,
-peer_foreign_nodes.foreign_node_ids
-FROM peers
-LEFT JOIN peer_foreign_nodes USING (peer_id);