-#
-# 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
+can_update = lambda (field, value): field in \
+ ['peername', 'peer_url', 'key', 'cacert', 'shortname', 'hrn_root']
class UpdatePeer(Method):
"""
- Query a peer PLC for its list of nodes, and refreshes
- the local database accordingly
-
- Returns None
+ Updates a peer. Only the fields specified in peer_fields are
+ updated, all other fields are left untouched.
+
+ Returns 1 if successful, faults otherwise.
"""
-
+
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' }
+ peer_fields = dict(filter(can_update, Peer.fields.items()))
+
+ accepts = [
+ Auth(),
+ Mixed(Peer.fields['peer_id'],
+ Peer.fields['peername']),
+ peer_fields
+ ]
+
+ returns = Parameter(int, "1 if successful")
+
+ def call(self, auth, peer_id_or_name, peer_fields):
+ peer_fields = dict(filter(can_update, peer_fields.items()))
+
+ # Get account information
+ peers = Peers(self.api, [peer_id_or_name])
+ if not peers:
+ raise PLCInvalidArgument, "No such peer"
+ peer = peers[0]
- ## 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]
+ if isinstance(self.caller, Peer):
+ if self.caller['peer_id'] != peer['peer_id']:
+ raise PLCPermissionDenied, "Not allowed to update specified peer"
- ### 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
+ peer.update(peer_fields)
+ peer.sync()
- ### 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()
+ # Log affected objects
+ self.event_objects = {'Peer': [peer['peer_id']]}
- ### delete entries that are not uptodate
- [ x.delete() for x in foreign_nodes.values() if not x.uptodate ]
-
+ return 1