1 ##############################################################################
3 # Copyright (c) 2010 Vifib SARL and Contributors. All Rights Reserved.
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
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.
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.
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.
26 ##############################################################################
31 from ConfigParser
import ConfigParser
43 def __init__(self
, buildout
, name
, options
):
44 self
.buildout
= buildout
45 self
.options
= options
47 self
.logger
= logging
.getLogger(self
.name
)
49 def _getIpAddress(self
, test_method
):
50 """Internal helper method to fetch ip address"""
51 if not 'ip_list' in self
.parameter_dict
:
53 for name
, ip
in self
.parameter_dict
['ip_list']:
58 def _getTapIpAddressList(self
, test_method
):
59 """Internal helper method to fetch full ip address assigned for tap"""
60 if not 'full_ip_list' in self
.parameter_dict
:
62 for item
in self
.parameter_dict
['full_ip_list']:
64 tap
, ip
, gw
, mask
, net
= item
65 if tap
.startswith('route_') and test_method(ip
) and \
66 test_method(gw
) and test_method(mask
):
67 return (ip
, gw
, mask
, net
)
70 def getLocalIPv4Address(self
):
71 """Returns local IPv4 address available on partition"""
72 # XXX: Lack checking for locality of address
73 return self
._getIpAddress(netaddr
.valid_ipv4
)
75 def getGlobalIPv6Address(self
):
76 """Returns global IPv6 address available on partition"""
77 # XXX: Lack checking for globality of address
78 return self
._getIpAddress(netaddr
.valid_ipv6
)
80 def getLocalTapIPv4AddressList(self
):
81 """Returns global IPv6 address available for tap interface"""
82 # XXX: Lack checking for locality of address
83 return self
._getTapIpAddressList(netaddr
.valid_ipv4
)
85 def getNetworkInterface(self
):
86 """Returns the network interface available on partition"""
87 if not 'ip_list' in self
.parameter_dict
:
89 for name
, ip
in self
.parameter_dict
['ip_list']:
92 raise AttributeError, "Not network interface found"
94 def mkdir_p(self
, path
, mode
=0700):
96 Creates a directory and its parents, if needed.
97 NB: If the directory already exists, it does not change its permission.
101 os
.makedirs(path
, mode
)
102 except OSError as exc
:
103 if exc
.errno
== errno
.EEXIST
and os
.path
.isdir(path
):
109 slap
= slapos
.slap
.slap()
110 slap_connection
= self
.buildout
['slap_connection']
111 computer_id
= slap_connection
['computer_id']
112 computer_partition_id
= slap_connection
['partition_id']
113 server_url
= slap_connection
['server_url']
114 key_file
= slap_connection
.get('key_file')
115 cert_file
= slap_connection
.get('cert_file')
116 instance_root
= self
.buildout
['buildout']['directory']
117 storage_configuration_dict
= self
.buildout
.get('storage-configuration')
118 network_dict
= self
.buildout
.get('network-information')
120 global_ipv4_network
= ''
121 if storage_configuration_dict
:
122 storage_home
= storage_configuration_dict
.get('storage-home')
124 global_ipv4_network
= network_dict
.get('global-ipv4-network')
125 slap
.initializeConnection(server_url
, key_file
, cert_file
)
126 self
.computer_partition
= slap
.registerComputerPartition(
128 computer_partition_id
)
129 self
.parameter_dict
= self
.computer_partition
.getInstanceParameterDict()
130 software_type
= self
.parameter_dict
['slap_software_type']
132 # Raise if request software_type does not exist ...
133 if software_type
not in self
.options
:
134 # ... Except for backward compatibility. Then use "default".
135 if software_type
in ['RootSoftwareInstance']:
136 software_type
= 'default'
138 raise zc
.buildout
.UserError("This software type (%s) isn't mapped." % \
141 instance_file_path
= self
.options
[software_type
]
143 if not os
.path
.exists(instance_file_path
):
144 raise zc
.buildout
.UserError("The specified buildout config file %r does "
145 "not exist." % instance_file_path
)
147 buildout
= ConfigParser()
148 with
open(instance_file_path
) as instance_path
:
149 buildout
.readfp(instance_path
)
151 buildout
.set('buildout', 'installed', '.installed-%s.cfg' % self
.name
)
153 if not buildout
.has_section('slap-parameter'):
154 buildout
.add_section('slap-parameter')
155 for parameter
, value
in self
.parameter_dict
.items():
156 # All parameters evaluating to False are... False, and shouldn't
157 # convey any information.
158 # Here, all those parameters are simply ignored.
160 if isinstance(value
, str):
161 buildout
.set('slap-parameter', parameter
, value
)
163 buildout
.set('slap-parameter', parameter
, json
.dumps(value
))
165 buildout
.add_section('slap-network-information')
166 buildout
.set('slap-network-information', 'local-ipv4',
167 self
.getLocalIPv4Address())
168 buildout
.set('slap-network-information', 'global-ipv6',
169 self
.getGlobalIPv6Address())
170 buildout
.set('slap-network-information', 'network-interface',
171 self
.getNetworkInterface())
172 tap_ip_list
= self
.getLocalTapIPv4AddressList()
173 tap_ipv4
= tap_gateway
= tap_netmask
= tap_network
= ''
175 tap_ipv4
, tap_gateway
, tap_netmask
, tap_network
= tap_ip_list
176 buildout
.set('slap-network-information', 'tap-ipv4', tap_ipv4
)
177 buildout
.set('slap-network-information', 'tap-gateway', tap_gateway
)
178 buildout
.set('slap-network-information', 'tap-netmask', tap_netmask
)
179 buildout
.set('slap-network-information', 'tap-network', tap_network
)
180 buildout
.set('slap-network-information', 'global-ipv4-network',
183 # Copy/paste slap_connection
184 buildout
.add_section('slap-connection')
185 for key
, value
in self
.buildout
['slap_connection'].iteritems():
186 # XXX: Waiting for SlapBaseRecipe to use dash instead of underscores
187 buildout
.set('slap-connection', key
.replace('_', '-'), value
)
188 # XXX: Needed for lxc. Use non standard API
189 buildout
.set('slap-connection', 'requested', self
.computer_partition
._requested_state
)
191 # setup storage directory
192 buildout
.add_section('storage-configuration')
193 buildout
.set('storage-configuration', 'storage-home', storage_home
)
194 if storage_home
and os
.path
.exists(storage_home
) and \
195 os
.path
.isdir(storage_home
):
196 # Create folder instance_root/DATA/ if not exist
197 data_home
= os
.path
.join(instance_root
, 'DATA')
198 self
.mkdir_p(data_home
)
199 for filename
in os
.listdir(storage_home
):
200 storage_path
= os
.path
.join(storage_home
, filename
, computer_partition_id
)
201 if os
.path
.exists(storage_path
) and os
.path
.isdir(storage_path
):
202 storage_link
= os
.path
.join(data_home
, filename
)
203 if os
.path
.lexists(storage_link
):
204 if not os
.path
.islink(storage_link
):
205 raise zc
.buildout
.UserError(
206 'Target %r already exists but is not a link' % storage_link
)
207 #os.unlink(storage_link)
209 os
.symlink(storage_path
, storage_link
)
210 buildout
.set('storage-configuration', filename
, storage_link
)
212 work_directory
= os
.path
.abspath(self
.buildout
['buildout'][
214 buildout_filename
= os
.path
.join(work_directory
,
215 'buildout-%s.cfg' % self
.name
)
216 with
open(buildout_filename
, 'w') as buildout_file
:
217 buildout
.write(buildout_file
)
219 # XXX-Antoine: We gotta find a better way to do this. I tried to check
220 # out how slapgrid-cp was running buildout. But it is worse than that.
221 command_line_args
= copy
.copy(sys
.argv
) + ['-c', buildout_filename
]
223 self
.logger
.info("Invoking commandline : '%s'",
224 ' '.join(command_line_args
))
226 subprocess
.check_call(command_line_args
, cwd
=work_directory
,
227 env
=os
.environ
.copy())