def install(self): """ Fetches buildout configuration from the server, run buildout with it. If it fails, we notify the server. """ self.logger.info("Installing software release %s..." % self.url) root_stat_info = os.stat(self.software_root) os.environ = utils.getCleanEnvironment(pwd.getpwuid(root_stat_info.st_uid ).pw_dir) if not os.path.isdir(self.software_path): os.mkdir(self.software_path) extends_cache = tempfile.mkdtemp() if os.getuid() == 0: # In case when running as root copy ownership, to simplify logic for path in [self.software_path, extends_cache]: path_stat_info = os.stat(path) if root_stat_info.st_uid != path_stat_info.st_uid or\ root_stat_info.st_gid != path_stat_info.st_gid: os.chown(path, root_stat_info.st_uid, root_stat_info.st_gid) try: buildout_parameter_list = [ 'buildout:extends-cache=%s' % extends_cache, 'buildout:directory=%s' % self.software_path,] if self.signature_private_key_file or \ self.upload_cache_url or \ self.upload_dir_url is not None: buildout_parameter_list.append('buildout:networkcache-section=networkcache') for buildout_option, value in ( ('%ssignature-private-key-file=%s', self.signature_private_key_file), ('%supload-cache-url=%s', self.upload_cache_url), ('%supload-dir-url=%s', self.upload_dir_url), ('%sshacache-cert-file=%s', self.shacache_cert_file), ('%sshacache-key-file=%s', self.shacache_key_file), ('%sshadir-cert-file=%s', self.shadir_cert_file), ('%sshadir-key-file=%s', self.shadir_key_file), ): if value: buildout_parameter_list.append( \ buildout_option % ('networkcache:', value)) buildout_parameter_list.extend(['-c', self.url]) utils.bootstrapBuildout(self.software_path, self.buildout, additional_buildout_parametr_list=buildout_parameter_list, console=self.console) utils.launchBuildout(self.software_path, os.path.join(self.software_path, 'bin', 'buildout'), additional_buildout_parametr_list=buildout_parameter_list, console=self.console) finally: shutil.rmtree(extends_cache)
def install(self): """ Creates configuration file from template in software_path, then installs the software partition with the help of buildout """ # XXX: Shall be no op in case if revision had not changed # It requires implementation of revision on server self.logger.info("Installing Computer Partition %s..." \ % self.computer_partition.getId()) # Checks existence and permissions of Partition directory # Note : Partitions have to be created and configured before running slapgrid if not os.path.isdir(self.instance_path): raise PathDoesNotExistError('Please create partition directory %s' % self.instance_path) instance_stat_info = os.stat(self.instance_path) permission = oct(stat.S_IMODE(instance_stat_info.st_mode)) if permission != REQUIRED_COMPUTER_PARTITION_PERMISSION: raise WrongPermissionError('Wrong permissions in %s : actual ' \ 'permissions are : %s, wanted ' \ 'are %s' % (self.instance_path, permission, REQUIRED_COMPUTER_PARTITION_PERMISSION)) os.environ = utils.getCleanEnvironment(pwd.getpwuid( instance_stat_info.st_uid).pw_dir) # Generates buildout part from template # TODO how to fetch the good template? Naming conventions? template_location = os.path.join(self.software_path, 'template.cfg') config_location = os.path.join(self.instance_path, 'buildout.cfg') self.logger.debug("Coping %r to %r" % (template_location, config_location)) shutil.copy(template_location, config_location) # fill generated buildout with additional information buildout_text = open(config_location).read() buildout_text += '\n\n' + pkg_resources.resource_string(__name__, 'templates/buildout-tail.cfg.in') % dict( computer_id=self.computer_id, partition_id=self.partition_id, server_url=self.server_url, software_release_url=self.software_release_url, key_file=self.key_file, cert_file=self.cert_file ) open(config_location, 'w').write(buildout_text) os.chmod(config_location, 0640) # Try to find the best possible buildout: # *) if software_root/bin/bootstrap exists use this one to bootstrap # locally # *) as last resort fallback to buildout binary from software_path bootstrap_candidate_dir = os.path.abspath(os.path.join(self.software_path, 'bin')) if os.path.isdir(bootstrap_candidate_dir): bootstrap_candidate_list = [q for q in os.listdir(bootstrap_candidate_dir) if q.startswith('bootstrap')] else: bootstrap_candidate_list = [] uid, gid = self.getUserGroupId() os.chown(config_location, -1, int(gid)) if len(bootstrap_candidate_list) == 0: buildout_binary = os.path.join(self.software_path, 'bin', 'buildout') self.logger.warning("Falling back to default buildout %r" % buildout_binary) else: if len(bootstrap_candidate_list) != 1: raise ValueError('More then one bootstrap candidate found.') # Reads uid/gid of path, launches buildout with thoses privileges bootstrap_file = os.path.abspath(os.path.join(bootstrap_candidate_dir, bootstrap_candidate_list[0])) file = open(bootstrap_file, 'r') line = file.readline() file.close() invocation_list = [] if line.startswith('#!'): invocation_list = line[2:].split() invocation_list.append(bootstrap_file) self.logger.debug('Invoking %r in %r' % (' '.join(invocation_list), self.instance_path)) kw = dict() if not self.console: kw.update(stdout=subprocess.PIPE, stderr=subprocess.STDOUT) process_handler = utils.SlapPopen(invocation_list, preexec_fn=lambda: utils.dropPrivileges(uid, gid), cwd=self.instance_path, env=utils.getCleanEnvironment(pwd.getpwuid(uid).pw_dir), **kw) result_std = process_handler.communicate()[0] if self.console: result_std = 'Please consult messages above.' if process_handler.returncode is None or process_handler.returncode != 0: message = 'Failed to bootstrap buildout in %r:\n%s\n' % ( self.instance_path, result_std) raise BuildoutFailedError(message) buildout_binary = os.path.join(self.instance_path, 'sbin', 'buildout') if not os.path.exists(buildout_binary): # use own buildout generation utils.bootstrapBuildout(self.instance_path, self.buildout, ['buildout:bin-directory=%s'% os.path.join(self.instance_path, 'sbin')], console=self.console) buildout_binary = os.path.join(self.instance_path, 'sbin', 'buildout') # Launches buildout utils.launchBuildout(self.instance_path, buildout_binary, console=self.console) # Generates supervisord configuration file from template self.logger.info("Generating supervisord config file from template...") # check if CP/etc/run exists and it is a directory # iterate over each file in CP/etc/run # if at least one is not 0750 raise -- partition has something funny runner_list = [] if os.path.exists(self.run_path): if os.path.isdir(self.run_path): runner_list = os.listdir(self.run_path) if len(runner_list) == 0: self.logger.warning('No runners found for partition %r' % self.partition_id) if os.path.exists(self.supervisord_partition_configuration_path): os.unlink(self.supervisord_partition_configuration_path) else: partition_id = self.computer_partition.getId() program_partition_template = pkg_resources.resource_stream(__name__, 'templates/program_partition_supervisord.conf.in').read() group_partition_template = pkg_resources.resource_stream(__name__, 'templates/group_partition_supervisord.conf.in').read() partition_supervisor_configuration = group_partition_template % dict( instance_id=partition_id, program_list=','.join(['_'.join([partition_id, runner]) for runner in runner_list])) for runner in runner_list: partition_supervisor_configuration += '\n' + \ program_partition_template % dict( program_id='_'.join([partition_id, runner]), program_directory=self.instance_path, program_command=os.path.join(self.run_path, runner), program_name=runner, instance_path=self.instance_path, user_id=uid, group_id=gid, # As supervisord has no environment to inherit setup minimalistic one HOME=pwd.getpwuid(uid).pw_dir, USER=pwd.getpwuid(uid).pw_name, ) utils.updateFile(self.supervisord_partition_configuration_path, partition_supervisor_configuration) self.updateSupervisor()