c8cbb0af5153f04c3d21dc1f5b3353272ebe5a54
[sfa.git] / sfa / methods / Allocate.py
1 from sfa.util.faults import SfaInvalidArgument, InvalidRSpec, SfatablesRejected
2 from sfa.util.sfatime import datetime_to_string 
3 from sfa.util.xrn import Xrn, urn_to_hrn
4 from sfa.util.method import Method
5 from sfa.util.sfatablesRuntime import run_sfatables
6 from sfa.trust.credential import Credential
7 from sfa.storage.parameter import Parameter, Mixed
8 from sfa.rspecs.rspec import RSpec
9 from sfa.util.sfalogging import logger
10
11 class Allocate(Method):
12     """
13     Allocate resources as described in a request RSpec argument 
14     to a slice with the named URN. On success, one or more slivers 
15     are allocated, containing resources satisfying the request, and 
16     assigned to the given slice. This method returns a listing and 
17     description of the resources reserved for the slice by this 
18     operation, in the form of a manifest RSpec. Allocated slivers 
19     are held for an aggregate-determined period. Clients must Renew 
20     or Provision slivers before the expiration time (given in the 
21     return struct), or the aggregate will automatically Delete them.
22
23     @param slice_urn (string) URN of slice to allocate to
24     @param credentials (dict) of credentials
25     @param rspec (string) rspec to allocate
26     @param options (dict)
27
28     As of 3.1.16, the PL driver implements here an important option named
29     'pltags' that affects the management of slice tags.
30
31     This option can take 3 values
32       (*) options['pltags'] == 'ignore' (default)
33           This is the recommended mode; in this mode all slice tags passed 
34           here are ignore, which correspond to the <planetlab:attribute> XML tags in 
35           the <sliver_type> areas of incoming rspec to Allocate.
36           In other words you are guaranteed to leave slice tags alone.
37       (*) options['pltags'] == 'append'
38           All incoming slice tags are added to corresponding slivers, 
39           unless an exact match can be found in the PLC db
40       (*) options['pltags'] == 'sync'
41           The historical mode, that attempts to leave the PLC db in a state
42           in sync with the ones specified in incoming rspec.
43
44     See also http://svn.planet-lab.org/wiki/SFASliceTags
45
46     """
47     interfaces = ['aggregate', 'slicemgr']
48     accepts = [
49         Parameter(str, "Slice URN"),
50         Parameter(type([dict]), "List of credentials"),
51         Parameter(str, "RSpec"),
52         Parameter(dict, "options"),
53         ]
54     returns = Parameter(str, "Allocated RSpec")
55
56     def call(self, xrn, creds, rspec, options):
57         xrn = Xrn(xrn, type='slice')
58
59         # Find the valid credentials
60         valid_creds = self.api.auth.checkCredentialsSpeaksFor(creds, 'createsliver', xrn.get_hrn(), options=options)
61         the_credential = Credential(cred=valid_creds[0])
62
63         # use the expiration from the first valid credential to determine when 
64         # the slivers should expire.
65         expiration = datetime_to_string(the_credential.expiration)
66         
67         self.api.logger.debug("Allocate, received expiration from credential: %s"%expiration)
68
69 # turned off, as passing an empty rspec is indeed useful for cleaning up the slice
70 #        # make sure request is not empty
71 #        slivers = RSpec(rspec).version.get_nodes_with_slivers()
72 #        if not slivers:
73 #            raise InvalidRSpec("Missing <sliver_type> or <sliver> element. Request rspec must explicitly allocate slivers")    
74
75         # flter rspec through sfatables
76         if self.api.interface in ['aggregate']:
77             chain_name = 'INCOMING'
78         elif self.api.interface in ['slicemgr']:
79             chain_name = 'FORWARD-INCOMING'
80         self.api.logger.debug("Allocate: sfatables on chain %s"%chain_name)
81         actual_caller_hrn = the_credential.actual_caller_hrn()
82         self.api.logger.info("interface: %s\tcaller-hrn: %s\ttarget-hrn: %s\tmethod-name: %s"%(self.api.interface, actual_caller_hrn, xrn.get_hrn(), self.name)) 
83         rspec = run_sfatables(chain_name, xrn.get_hrn(), actual_caller_hrn, rspec)
84 # turned off, as passing an empty rspec is indeed useful for cleaning up the slice
85 #        slivers = RSpec(rspec).version.get_nodes_with_slivers()
86 #        if not slivers:
87 #            raise SfatablesRejected(slice_xrn)
88
89         # pass this to the driver code in case they need it
90         options['actual_caller_hrn'] = actual_caller_hrn
91         result = self.api.manager.Allocate(self.api, xrn.get_urn(), creds, rspec, expiration, options)
92         return result