Remove now useless comment.
[slapos.git] / slapos / recipe / softwaretype.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
28 import os
29 import sys
30 import copy
31 from ConfigParser import ConfigParser
32 import json
33 import subprocess
34 import slapos.slap
35 import netaddr
36 import logging
37
38 import zc.buildout
39
40 class Recipe:
41
42 def __init__(self, buildout, name, options):
43 self.buildout = buildout
44 self.options = options
45 self.name = name
46 self.logger = logging.getLogger(self.name)
47
48 def _getIpAddress(self, test_method):
49 """Internal helper method to fetch ip address"""
50 if not 'ip_list' in self.parameter_dict:
51 raise AttributeError
52 for name, ip in self.parameter_dict['ip_list']:
53 if test_method(ip):
54 return ip
55 raise AttributeError
56
57 def getLocalIPv4Address(self):
58 """Returns local IPv4 address available on partition"""
59 # XXX: Lack checking for locality of address
60 return self._getIpAddress(netaddr.valid_ipv4)
61
62 def getGlobalIPv6Address(self):
63 """Returns global IPv6 address available on partition"""
64 # XXX: Lack checking for globality of address
65 return self._getIpAddress(netaddr.valid_ipv6)
66
67 def getNetworkInterface(self):
68 """Returns the network interface available on partition"""
69 if not 'ip_list' in self.parameter_dict:
70 raise AttributeError
71 for name, ip in self.parameter_dict['ip_list']:
72 if name:
73 return name
74 raise AttributeError, "Not network interface found"
75
76 def install(self):
77 slap = slapos.slap.slap()
78 slap_connection = self.buildout['slap_connection']
79 computer_id = slap_connection['computer_id']
80 computer_partition_id = slap_connection['partition_id']
81 server_url = slap_connection['server_url']
82 key_file = slap_connection.get('key_file')
83 cert_file = slap_connection.get('cert_file')
84 slap.initializeConnection(server_url, key_file, cert_file)
85 self.computer_partition = slap.registerComputerPartition(
86 computer_id,
87 computer_partition_id)
88 self.parameter_dict = self.computer_partition.getInstanceParameterDict()
89 software_type = self.parameter_dict['slap_software_type']
90
91 # Raise if request software_type does not exist ...
92 if software_type not in self.options:
93 # ... Except for backward compatibility. Then use "default".
94 if software_type in ['RootSoftwareInstance']:
95 software_type = 'default'
96 else:
97 raise zc.buildout.UserError("This software type (%s) isn't mapped." % \
98 software_type)
99
100 instance_file_path = self.options[software_type]
101
102 if not os.path.exists(instance_file_path):
103 raise zc.buildout.UserError("The specified buildout config file %r does "
104 "not exist." % instance_file_path)
105
106 buildout = ConfigParser()
107 with open(instance_file_path) as instance_path:
108 buildout.readfp(instance_path)
109
110 buildout.set('buildout', 'installed', '.installed-%s.cfg' % self.name)
111
112 if not buildout.has_section('slap-parameter'):
113 buildout.add_section('slap-parameter')
114 for parameter, value in self.parameter_dict.items():
115 # All parameters evaluating to False are... False, and shouldn't
116 # convey any information.
117 # Here, all those parameters are simply ignored.
118 if value:
119 if isinstance(value, str):
120 buildout.set('slap-parameter', parameter, value)
121 else:
122 buildout.set('slap-parameter', parameter, json.dumps(value))
123
124 buildout.add_section('slap-network-information')
125 buildout.set('slap-network-information', 'local-ipv4',
126 self.getLocalIPv4Address())
127 buildout.set('slap-network-information', 'global-ipv6',
128 self.getGlobalIPv6Address())
129 buildout.set('slap-network-information', 'network-interface',
130 self.getNetworkInterface())
131
132 # Copy/paste slap_connection
133 buildout.add_section('slap-connection')
134 for key, value in self.buildout['slap_connection'].iteritems():
135 # XXX: Waiting for SlapBaseRecipe to use dash instead of underscores
136 buildout.set('slap-connection', key.replace('_', '-'), value)
137 # XXX: Needed for lxc. Use non standard API
138 buildout.set('slap-connection', 'requested', self.computer_partition._requested_state)
139
140 work_directory = os.path.abspath(self.buildout['buildout'][
141 'directory'])
142 buildout_filename = os.path.join(work_directory,
143 'buildout-%s.cfg' % self.name)
144 with open(buildout_filename, 'w') as buildout_file:
145 buildout.write(buildout_file)
146
147 # XXX-Antoine: We gotta find a better way to do this. I tried to check
148 # out how slapgrid-cp was running buildout. But it is worse than that.
149 command_line_args = copy.copy(sys.argv) + ['-c', buildout_filename]
150
151 self.logger.info("Invoking commandline : '%s'",
152 ' '.join(command_line_args))
153
154 subprocess.check_call(command_line_args, cwd=work_directory,
155 env=os.environ.copy())
156 return []
157 update = install