From 76bdf368d0d8dcd046476abe04392a73a0eaa6e0 Mon Sep 17 00:00:00 2001 From: Planet-Lab Support Date: Thu, 12 Jul 2007 18:09:11 +0000 Subject: [PATCH] This commit was manufactured by cvs2svn to create branch 'planetlab-4_0-branch'. --- PLC/Methods/AddSession.py | 37 +++++++ PLC/Methods/AddSliceToNodesWhitelist.py | 54 ++++++++++ PLC/Methods/DeleteSliceFromNodesWhitelist.py | 54 ++++++++++ PLC/Methods/GenerateNodeConfFile.py | 107 +++++++++++++++++++ PLC/Methods/GetSessions.py | 35 ++++++ refresh-peer.py | 38 +++++++ 6 files changed, 325 insertions(+) create mode 100644 PLC/Methods/AddSession.py create mode 100644 PLC/Methods/AddSliceToNodesWhitelist.py create mode 100644 PLC/Methods/DeleteSliceFromNodesWhitelist.py create mode 100644 PLC/Methods/GenerateNodeConfFile.py create mode 100644 PLC/Methods/GetSessions.py create mode 100644 refresh-peer.py diff --git a/PLC/Methods/AddSession.py b/PLC/Methods/AddSession.py new file mode 100644 index 0000000..6f5bc88 --- /dev/null +++ b/PLC/Methods/AddSession.py @@ -0,0 +1,37 @@ +import time + +from PLC.Method import Method +from PLC.Parameter import Parameter, Mixed +from PLC.Auth import Auth +from PLC.Sessions import Session, Sessions +from PLC.Persons import Person, Persons + +class AddSession(Method): + """ + Creates and returns a new session key for the specified user. + (Used for website 'user sudo') + """ + + roles = ['admin'] + accepts = [ + Auth(), + Mixed(Person.fields['person_id'], + Person.fields['email']) + ] + returns = Session.fields['session_id'] + + + def call(self, auth, person_id_or_email): + + persons = Persons(self.api, [person_id_or_email], ['person_id', 'email']) + + if not persons: + raise PLCInvalidArgument, "No such person" + + person = persons[0] + session = Session(self.api) + session['expires'] = int(time.time()) + (24 * 60 * 60) + session.sync(commit = False) + session.add_person(person, commit = True) + + return session['session_id'] diff --git a/PLC/Methods/AddSliceToNodesWhitelist.py b/PLC/Methods/AddSliceToNodesWhitelist.py new file mode 100644 index 0000000..a6b4bd1 --- /dev/null +++ b/PLC/Methods/AddSliceToNodesWhitelist.py @@ -0,0 +1,54 @@ +from PLC.Faults import * +from PLC.Method import Method +from PLC.Parameter import Parameter, Mixed +from PLC.Nodes import Node, Nodes +from PLC.Slices import Slice, Slices +from PLC.Auth import Auth + +class AddSliceToNodesWhitelist(Method): + """ + Adds the specified slice to the whitelist on the specified nodes. Nodes may be + either local or foreign nodes. + + If the slice is already associated with a node, no errors are + returned. + + Returns 1 if successful, faults otherwise. + """ + + roles = ['admin'] + + accepts = [ + Auth(), + Mixed(Slice.fields['slice_id'], + Slice.fields['name']), + [Mixed(Node.fields['node_id'], + Node.fields['hostname'])] + ] + + returns = Parameter(int, '1 if successful') + + def call(self, auth, slice_id_or_name, node_id_or_hostname_list): + # Get slice information + slices = Slices(self.api, [slice_id_or_name]) + if not slices: + raise PLCInvalidArgument, "No such slice" + slice = slices[0] + + if slice['peer_id'] is not None: + raise PLCInvalidArgument, "Not a local slice" + + # Get specified nodes, add them to the slice + nodes = Nodes(self.api, node_id_or_hostname_list) + for node in nodes: + if node['peer_id'] is not None: + raise PLCInvalidArgument, "%s not a local node" % node['hostname'] + if slice['slice_id'] not in node['slice_ids_whitelist']: + slice.add_to_node_whitelist(node, commit = False) + + slice.sync() + + self.event_objects = {'Node': [node['node_id'] for node in nodes], + 'Slice': [slice['slice_id']]} + + return 1 diff --git a/PLC/Methods/DeleteSliceFromNodesWhitelist.py b/PLC/Methods/DeleteSliceFromNodesWhitelist.py new file mode 100644 index 0000000..8899d88 --- /dev/null +++ b/PLC/Methods/DeleteSliceFromNodesWhitelist.py @@ -0,0 +1,54 @@ +from PLC.Faults import * +from PLC.Method import Method +from PLC.Parameter import Parameter, Mixed +from PLC.Nodes import Node, Nodes +from PLC.Slices import Slice, Slices +from PLC.Auth import Auth + +class DeleteSliceFromNodesWhitelist(Method): + """ + Deletes the specified slice from the whitelist on the specified nodes. Nodes may be + either local or foreign nodes. + + If the slice is already associated with a node, no errors are + returned. + + Returns 1 if successful, faults otherwise. + """ + + roles = ['admin'] + + accepts = [ + Auth(), + Mixed(Slice.fields['slice_id'], + Slice.fields['name']), + [Mixed(Node.fields['node_id'], + Node.fields['hostname'])] + ] + + returns = Parameter(int, '1 if successful') + + def call(self, auth, slice_id_or_name, node_id_or_hostname_list): + # Get slice information + slices = Slices(self.api, [slice_id_or_name]) + if not slices: + raise PLCInvalidArgument, "No such slice" + slice = slices[0] + + if slice['peer_id'] is not None: + raise PLCInvalidArgument, "Not a local slice" + + # Get specified nodes, add them to the slice + nodes = Nodes(self.api, node_id_or_hostname_list) + for node in nodes: + if node['peer_id'] is not None: + raise PLCInvalidArgument, "%s not a local node" % node['hostname'] + if slice['slice_id'] in node['slice_ids_whitelist']: + slice.delete_from_node_whitelist(node, commit = False) + + slice.sync() + + self.event_objects = {'Node': [node['node_id'] for node in nodes], + 'Slice': [slice['slice_id']]} + + return 1 diff --git a/PLC/Methods/GenerateNodeConfFile.py b/PLC/Methods/GenerateNodeConfFile.py new file mode 100644 index 0000000..0b5cf8e --- /dev/null +++ b/PLC/Methods/GenerateNodeConfFile.py @@ -0,0 +1,107 @@ +import random +import base64 + +from PLC.Faults import * +from PLC.Method import Method +from PLC.Parameter import Parameter, Mixed +from PLC.Nodes import Node, Nodes +from PLC.NodeNetworks import NodeNetwork, NodeNetworks +from PLC.Auth import Auth + +class GenerateNodeConfFile(Method): + """ + Creates a new node configuration file if all network settings are + present. This function will generate a new node key for the + specified node, effectively invalidating any old configuration + files. + + Non-admins can only generate files for nodes at their sites. + + Returns the contents of the file if successful, faults otherwise. + """ + + roles = ['admin', 'pi', 'tech'] + + accepts = [ + Auth(), + Mixed(Node.fields['node_id'], + Node.fields['hostname']), + Parameter(bool, "True if you want to regenerate node key") + ] + + returns = Parameter(str, "Node configuration file") + + def call(self, auth, node_id_or_hostname, regenerate_node_key = True): + # Get node information + nodes = Nodes(self.api, [node_id_or_hostname]) + if not nodes: + raise PLCInvalidArgument, "No such node" + node = nodes[0] + + if node['peer_id'] is not None: + raise PLCInvalidArgument, "Not a local node" + + # If we are not an admin, make sure that the caller is a + # member of the site at which the node is located. + if 'admin' not in self.caller['roles']: + if node['site_id'] not in self.caller['site_ids']: + raise PLCPermissionDenied, "Not allowed to generate a configuration file for that node" + + # Get node networks for this node + primary = None + nodenetworks = NodeNetworks(self.api, node['nodenetwork_ids']) + for nodenetwork in nodenetworks: + if nodenetwork['is_primary']: + primary = nodenetwork + break + if primary is None: + raise PLCInvalidArgument, "No primary network configured" + + # Split hostname into host and domain parts + parts = node['hostname'].split(".", 1) + if len(parts) < 2: + raise PLCInvalidArgument, "Node hostname is invalid" + host = parts[0] + domain = parts[1] + + if regenerate_node_key: + # Generate 32 random bytes + bytes = random.sample(xrange(0, 256), 32) + # Base64 encode their string representation + node['key'] = base64.b64encode("".join(map(chr, bytes))) + # XXX Boot Manager cannot handle = in the key + node['key'] = node['key'].replace("=", "") + # Save it + node.sync() + + # Generate node configuration file suitable for BootCD + file = "" + + file += 'NODE_ID="%d"\n' % node['node_id'] + file += 'NODE_KEY="%s"\n' % node['key'] + + if primary['mac']: + file += 'NET_DEVICE="%s"\n' % primary['mac'].lower() + + file += 'IP_METHOD="%s"\n' % primary['method'] + + if primary['method'] == 'static': + file += 'IP_ADDRESS="%s"\n' % primary['ip'] + file += 'IP_GATEWAY="%s"\n' % primary['gateway'] + file += 'IP_NETMASK="%s"\n' % primary['netmask'] + file += 'IP_NETADDR="%s"\n' % primary['network'] + file += 'IP_BROADCASTADDR="%s"\n' % primary['broadcast'] + file += 'IP_DNS1="%s"\n' % primary['dns1'] + file += 'IP_DNS2="%s"\n' % (primary['dns2'] or "") + + file += 'HOST_NAME="%s"\n' % host + file += 'DOMAIN_NAME="%s"\n' % domain + + for nodenetwork in nodenetworks: + if nodenetwork['method'] == 'ipmi': + file += 'IPMI_ADDRESS="%s"\n' % nodenetwork['ip'] + if nodenetwork['mac']: + file += 'IPMI_MAC="%s"\n' % nodenetwork['mac'].lower() + break + + return file diff --git a/PLC/Methods/GetSessions.py b/PLC/Methods/GetSessions.py new file mode 100644 index 0000000..a72553c --- /dev/null +++ b/PLC/Methods/GetSessions.py @@ -0,0 +1,35 @@ +from PLC.Faults import * +from PLC.Method import Method +from PLC.Parameter import Parameter, Mixed +from PLC.Filter import Filter +from PLC.Sessions import Session, Sessions +from PLC.Persons import Person, Persons +from PLC.Auth import Auth + +class GetSessions(Method): + """ + Returns an array of structs containing details about users sessions. If + session_filter is specified and is an array of user identifiers or + session_keys, or a struct of session attributes, only sessions matching the + filter will be returned. If return_fields is specified, only the + specified details will be returned. + + + """ + + roles = ['admin'] + + accepts = [ + Auth(), + Mixed([Mixed(Session.fields['person_id'], + Session.fields['session_id'])], + Filter(Session.fields)) + ] + + returns = [Session.fields] + + def call(self, auth, session_filter = None): + + sessions = Sessions(self.api, session_filter) + + return sessions diff --git a/refresh-peer.py b/refresh-peer.py new file mode 100644 index 0000000..ae38841 --- /dev/null +++ b/refresh-peer.py @@ -0,0 +1,38 @@ +#!/usr/bin/env plcsh +# $Id: refresh-peer.py 154 2007-03-28 14:15:55Z thierry $ + +import sys,os,time + +def Run (peername): + timestring=time.strftime("%Y-%m-%d-%H-%M-%S") + print 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',peername + print 'RefreshPeer on %s - starting on %s'%(peername,timestring) + print 'xxxxxxxxxx' + sys.stdout.flush() + start=time.time() + result=RefreshPeer(peername) + finish=time.time() + + print 'Total duration',finish-start + print 'xxxxxxxxxx timers:' + keys=result.keys() + keys.sort() + for key in keys: + print key,result[key] + sys.stdout.flush() + sys.stderr.flush() + +def RunInLog (peername): + logname="/var/log/refresh-peer-%s.log"%(peername) + sys.stdout=open(logname,'a') + sys.stderr=sys.stdout + Run(peername) + sys.stderr.close() + sys.stdout.close() + +if __name__ == "__main__": + + for peername in sys.argv[1:]: + RunInLog (peername) + + -- 2.43.0