+# $Id$
+# $URL$
+
"""Sliver manager API.
This module exposes an XMLRPC interface that allows PlanetLab users to
import logger
# TODO: These try/excepts are a hack to allow doc/DocBookLocal.py to
-# import this file in order to extrac the documentation from each
-# exported function. A better approach will involve more extensive code
-# splitting, I think.
+# import this file in order to extract the documentation from each
+# exported function.
+# A better approach will involve more extensive code splitting, I think.
try: import database
except: import logger as database
try: import sliver_vs
import ticket as ticket_module
import tools
-deliver_ticket = None # set in sm.py:start()
+deliver_ticket = None # set in slivermanager.start()
api_method_dict = {}
nargs_dict = {}
@export_to_api(0)
def Help():
"""Get a list of functions currently supported by the Node Manager API"""
- return ''.join([method.__doc__ + '\n' for method in api_method_dict.itervalues()])
+ names=api_method_dict.keys()
+ names.sort()
+ return ''.join(['**** ' + api_method_dict[name].__name__ + '\n' + api_method_dict[name].__doc__ + '\n'
+ for name in names])
@export_to_docbook(roles=['self'],
accepts=[Parameter(str, 'A ticket returned from GetSliceTicket()')],
actions are performed on a delegated slice (such as creation),
a controller slice must deliver a valid slice ticket to NM.
- This ticket is the value retured by PLC's GetSliceTicket() API call,
- """
+ This ticket is the value retured by PLC's GetSliceTicket() API call."""
try:
data = ticket_module.verify(ticket)
name = data['slivers'][0]['name']
if data != None:
deliver_ticket(data)
- logger.log('Ticket delivered for %s' % name)
+ logger.log('api_calls: Ticket delivered for %s' % name)
Create(database.db.get(name))
except Exception, err:
raise xmlrpclib.Fault(102, 'Ticket error: ' + str(err))
returns=Parameter(int, '1 if successful'))
@export_to_api(1)
def AdminTicket(ticket):
- """Admin interface to create slivers based on ticket returned by GetSlivers().
- """
+ """Admin interface to create slivers based on ticket returned by GetSlivers()."""
try:
data, = xmlrpclib.loads(ticket)[0]
name = data['slivers'][0]['name']
if data != None:
deliver_ticket(data)
- logger.log('Admin Ticket delivered for %s' % name)
+ logger.log('api_calls: Admin Ticket delivered for %s' % name)
Create(database.db.get(name))
except Exception, err:
raise xmlrpclib.Fault(102, 'Ticket error: ' + str(err))
def Create(sliver_name):
"""Create a non-PLC-instantiated sliver"""
rec = sliver_name
- if rec['instantiation'] == 'delegated': accounts.get(rec['name']).ensure_created(rec)
- else: raise Exception, "Only PLC can create non delegated slivers."
+ if rec['instantiation'] == 'delegated':
+ accounts.get(rec['name']).ensure_created(rec)
+ logger.log("api_calls: Create %s"%rec['name'])
+ else:
+ raise Exception, "Only PLC can create non delegated slivers."
@export_to_docbook(roles=['nm-controller', 'self'],
def Destroy(sliver_name):
"""Destroy a non-PLC-instantiated sliver"""
rec = sliver_name
- if rec['instantiation'] == 'delegated': accounts.get(rec['name']).ensure_destroyed()
- else: raise Exception, "Only PLC can destroy non delegated slivers."
+ if rec['instantiation'] == 'delegated':
+ accounts.get(rec['name']).ensure_destroyed()
+ logger.log("api_calls: Destroy %s"%rec['name'])
+ else:
+ raise Exception, "Only PLC can destroy non delegated slivers."
@export_to_docbook(roles=['nm-controller', 'self'],
"""Configure and start sliver."""
rec = sliver_name
accounts.get(rec['name']).start(rec)
+ logger.log("api_calls: Start %s"%rec['name'])
@export_to_docbook(roles=['nm-controller', 'self'],
"""Kill all processes belonging to the specified sliver"""
rec = sliver_name
accounts.get(rec['name']).stop()
+ logger.log("api_calls: Stop %s"%rec['name'])
@export_to_docbook(roles=['nm-controller', 'self'],
accounts.get(rec['name']).stop()
accounts.get(rec['name']).ensure_created(rec)
accounts.get(rec['name']).start(rec)
-
+ logger.log("api_calls: ReCreate %s"%rec['name'])
@export_to_docbook(roles=['nm-controller', 'self'],
accepts=[Parameter(str, 'A sliver/slice name.')],
rec = sliver_name
return rec.get('_loans', [])[:]
-def validate_loans(obj):
- """Check that <obj> is a valid loan specification."""
- def validate_loan(obj): return (type(obj)==list or type(obj)==tuple) and len(obj)==3 and type(obj[0])==str and type(obj[1])==str and obj[1] in database.LOANABLE_RESOURCES and type(obj[2])==int and obj[2]>=0
- return type(obj)==list and False not in map(validate_loan, obj)
+def validate_loans(loans):
+ """Check that <obj> is a list of valid loan specifications."""
+ def validate_loan(loan):
+ return (type(loan)==list or type(loan)==tuple) and len(loan)==3 \
+ and type(loan[0])==str and type(loan[1])==str and loan[1] in database.LOANABLE_RESOURCES and type(loan[2])==int and loan[2]>=0
+ return type(loans)==list and False not in [validate_loan(load) for loan in loans]
+
@export_to_docbook(roles=['nm-controller', 'self'],
- accepts=[ Parameter(str, 'A sliver/slice name.'),
- [Mixed(Parameter(str, 'recipient slice name'),
- Parameter(str, 'resource name'),
- Parameter(int, 'resource amount'))] ],
- returns=Parameter(int, '1 if successful'))
+ accepts=[ Parameter(str, 'A sliver/slice name.'),
+ [Mixed(Parameter(str, 'recipient slice name'),
+ Parameter(str, 'resource name'),
+ Parameter(int, 'resource amount'))], ],
+ returns=Parameter(int, '1 if successful'))
@export_to_api(2)
def SetLoans(sliver_name, loans):
"""Overwrite the list of loans made by the specified sliver.
RSpec is handed out, but it will silently discard those loans that would
put it over capacity. This behavior may be replaced with error semantics
in the future. As well, there is currently no asynchronous notification
- of loss of resources.
- """
+ of loss of resources."""
rec = sliver_name
- if not validate_loans(loans): raise xmlrpclib.Fault(102, 'Invalid argument: the second argument must be a well-formed loan specification')
+ if not validate_loans(loans):
+ raise xmlrpclib.Fault(102, 'Invalid argument: the second argument must be a well-formed loan specification')
rec['_loans'] = loans
database.db.sync()
+
+@export_to_docbook(roles=['nm-controller', 'self'],
+ returns=Parameter(dict, 'Record dictionary'))
+@export_to_api(0)
+def GetRecord(sliver_name):
+ """Return sliver record"""
+ rec = sliver_name
+ return rec