Merge branch 'master' into erp5-component
[slapos.git] / slapos / recipe / request.py
1 ##############################################################################
2 #
3 # Copyright (c) 2010 Vifib SARL and Contributors. All Rights Reserved.
4 #
5 # WARNING: This program as such is intended to be used by professional
6 # programmers who take the whole responsibility of assessing all potential
7 # consequences resulting from its eventual inadequacies and bugs
8 # End users who are looking for a ready-to-use solution with commercial
9 # guarantees and support are strongly adviced to contract a Free Software
10 # Service Company
11 #
12 # This program is Free Software; you can redistribute it and/or
13 # modify it under the terms of the GNU General Public License
14 # as published by the Free Software Foundation; either version 3
15 # of the License, or (at your option) any later version.
16 #
17 # This program is distributed in the hope that it will be useful,
18 # but WITHOUT ANY WARRANTY; without even the implied warranty of
19 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 # GNU General Public License for more details.
21 #
22 # You should have received a copy of the GNU General Public License
23 # along with this program; if not, write to the Free Software
24 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 #
26 ##############################################################################
27 import logging
28
29 from slapos import slap as slapmodule
30
31 class Recipe(object):
32 """
33 Request a partition to a slap master.
34 Can provide parameters to that partition and fetches its connection
35 parameters.
36
37 Input:
38 server-url
39 key-file (optional)
40 cert-file (optional)
41 Used to contact slap master.
42
43 computer-id
44 partition-id
45 Current partition's identifiers.
46 Must match key's credentials if given.
47
48 name (optional, defaults to section name)
49 Name (reference) of requested partition.
50
51 software-url
52 URL of a software definition to request an instance of.
53
54 software-type
55 Software type of requested instance, among those provided by the
56 definition from software-url.
57
58 slave (optional, defaults to false)
59 Set to "true" when requesting a slave instance, ie just setting a set of
60 parameters in an existing instance.
61
62 sla (optional)
63 Whitespace-separated list of Service Level Agreement names.
64 Each name must correspond to a "sla-<name>" option.
65 Used to specify what a suitable partition would be.
66 Possible names depend on master's capabilities.
67
68 config (optional)
69 Whitespace-separated list of partition parameter names.
70 Each name must correspond to a "config-<name>" option.
71 Possible names depend on requested partition's software type.
72
73 return (optional)
74 Whitespace-separated list of expected partition-published value names.
75 Options will be created from them, in the form of "connection-<name>"
76 As long as requested partition doesn't publish all those values,
77 installation of request section will fail.
78 Possible names depend on requested partition's software type.
79
80 Output:
81 See "return" input key.
82 """
83 failed = None
84
85 def __init__(self, buildout, name, options):
86 logger = logging.getLogger(name)
87
88 slap = slapmodule.slap()
89
90 software_url = options['software-url']
91 name = options['name']
92
93 slap.initializeConnection(options['server-url'],
94 options.get('key-file'),
95 options.get('cert-file'),
96 )
97 request = slap.registerComputerPartition(
98 options['computer-id'], options['partition-id']).request
99
100 isSlave = options.get('slave', '').lower() in ['y', 'yes', 'true', '1']
101
102 return_parameters = []
103 if 'return' in options:
104 return_parameters = [str(parameter).strip()
105 for parameter in options['return'].split()]
106 else:
107 logger.debug("No parameter to return to main instance."
108 "Be careful about that...")
109
110 software_type = options.get('software-type', 'RootInstanceSoftware')
111
112 filter_kw = {}
113 if 'sla' in options:
114 for sla_parameter in options['sla'].split():
115 filter_kw[sla_parameter] = options['sla-%s' % sla_parameter]
116
117 partition_parameter_kw = {}
118 if 'config' in options:
119 for config_parameter in options['config'].split():
120 partition_parameter_kw[config_parameter] = \
121 options['config-%s' % config_parameter]
122
123 self.instance = instance = request(software_url, software_type,
124 name, partition_parameter_kw=partition_parameter_kw,
125 filter_kw=filter_kw, shared=isSlave)
126
127 for param in return_parameters:
128 try:
129 options['connection-%s' % param] = str(
130 instance.getConnectionParameter(param))
131 except slapmodule.NotFoundError:
132 options['connection-%s' % param] = ''
133 if self.failed is None:
134 self.failed = param
135
136 def install(self):
137 if self.failed is not None:
138 # Check instance status to know if instance has been deployed
139 try:
140 status = self.instance.getState()
141 except slapmodule.NotFoundError:
142 status = 'not ready yet, please try again'
143 except AttributeError:
144 status = 'unknown'
145 error_message = 'Connection parameter %s not found. '\
146 'Requested instance is currently %s. If this error persists, '\
147 'check status of this instance.' % (self.failed, status)
148 self.logger.error(error_message)
149 raise KeyError(error_message)
150 return []
151
152 update = install