def start(self): if self.config.input_ports.webserver_config.webserver_type == "apache": self.ctx.r(apache_utils.start_apache, self.ctx.props.input_ports.webserver_config) else: # need to start the development webserver if not os.path.exists(self.config.gunicorn_django_exe): raise UserError(errors[ERR_NO_GUNICORN_SCRIPT], msg_args={"file":self.config.gunicorn_django_exe, "appname":self.config.app_short_ename}) with open(self.config.output_ports.django.layout_cfg_file, "rb") as f: file_layout = create_file_layout_from_json(json.load(f)) log_file = os.path.join(self.config.config_port.log_directory, self.config.app_short_name + ".log") bind_addr = "%s:%d" % \ (self.config.input_ports.webserver_config.listen_host, self.config.input_ports.webserver_config.listen_port) prog_and_args = [self.config.gunicorn_django_exe, "--log-level", "debug", "--log-file", log_file, "-w", "4", "--pid", self.get_pid_file_path(), "--pythonpath", file_layout.get_python_path(), "--settings", file_layout.get_deployed_settings_module(), "-b", bind_addr, "--daemon"] env = file_layout.get_django_env_vars() try: iuprocess.run_and_log_program(prog_and_args, env, logger, cwd=file_layout.get_settings_file_directory()) except Exception, e: logger.exception("Django startup failed: %s" % e) raise UserError(errors[ERR_DJANGO_STARTUP], msg_args={"appname":self.config.app_short_name}, developer_msg="script %s, error was %s" % (self.config.gunicorn_django_exe, e))
def register(mgt_info, sudo_password=None, upgrade=False): mgt_info = mgt_info.with_only_pidfile_services() # first copy the monitrc.template to deployment_home monit_substitutions = { 'monitinterval' : 120, 'monitstartdelay' : 60, 'monitlogfile' : os.path.join(mgt_info.deployment_home, 'log/monit.log'), 'monitemailalertsto' : '*****@*****.**', 'monithost' : 'localhost', 'monitadmin' : 'admin', 'monitadminpassword' : 'engage_monit' } monitrc_template_file = os.path.join(os.path.dirname(__file__), 'data/monitrc.template') monitrc_file = os.path.join(mgt_info.deployment_home, 'monitrc') iufile.instantiate_template_file(monitrc_template_file, monitrc_file, monit_substitutions) with open(monitrc_file, 'a') as f: for svc in mgt_info.services: monitor = generate_monitrc(mgt_info.svcctl_exe, svc) f.write(monitor) os.chmod(monitrc_file, 0600) # now start monit iuprocess.run_and_log_program( [monit_exe, '-c', monitrc_file], {}, logger) print 'monit started'
def _install_patch(self, target_package_dir): assert self.metadata.properties.has_key(u"patch_resource_key") key = self.metadata.properties[u"patch_resource_key"] self.logger.debug("%s: Installing patch %s", self.package_name, key.__repr__()) patch_metadata = resource_metadata.ResourceMD(self.metadata.id + "-patch", key) patch_entry = self.install_context.package_library.get_entry(patch_metadata) assert patch_entry != None package = patch_entry.get_package() assert package != None patch_parent_dir = tempfile.mkdtemp(key[u"name"]) patch_dir = package.extract(patch_parent_dir) base_name = os.path.basename(patch_dir) assert base_name[-6:]=="-patch" # truncate -patch off directory name to get basename for patch file patchfile = base_name[0:-6] + ".diff" patch_file = os.path.join(patch_parent_dir, os.path.join(patch_dir, patchfile)) if not os.path.exists(patch_file): raise PatchInstallError("Unable to find patch file %s" % patch_file) if not (os.path.exists(target_package_dir) and os.path.isdir(target_package_dir)): raise PatchInstallError("Unable to find target package directory %s" % target_package_dir) cmd = ["/usr/bin/patch", "-p1", "-i", patch_file] rc = run_and_log_program(cmd, {}, self.logger, cwd=target_package_dir) if rc != 0: raise PatchInstallError("Error in running patch") shutil.rmtree(patch_parent_dir) self.logger.info("Applied patch to %s" % self.package_name)
def run_config_engine(installer_file_layout, install_spec_file): ifl = installer_file_layout config_error_file = get_config_error_file(installer_file_layout) preprocess_resources.validate_install_spec(install_spec_file) install_script_file = ifl.get_install_script_file() if os.path.exists(install_script_file): logger.debug("moving old %s to %s before running config engine" % (install_script_file, install_script_file + ".prev")) os.rename(install_script_file, install_script_file + ".prev") # we run the config engine from the same directory as where we want # the install script file, as it write the file to the current # directory. rc = procutils.run_and_log_program([ifl.get_configurator_exe(), ifl.get_preprocessed_resource_file(), install_spec_file], None, logger, cwd=os.path.dirname(install_script_file)) if rc != 0: logger.error("Config engine returned %d" % rc) if os.path.exists(config_error_file): # if the config engine wrote an error file, we parse that # error and raise it. try: with open(config_error_file, "rb") as f: ue = parse_user_error(json.load(f), component=AREA_CONFIG) raise ue except UserErrorParseExc, e: logger.exception("Unable to parse user error file %s" % config_error_file) raise Exception("Configuration engine returned an error")
def run_compileall(python_exe, directory, logger): """(re-)compile all the python files under the specified directory """ rc = run_and_log_program([python_exe, "-mcompileall", directory], {}, logger) if rc != 0: raise CompileAllError("Python compile-all packages failed for directory '%s'" % directory)
def run(self, library_package, env_mapping={}): p = self.ctx.props cmd = self._get_cmdline(library_package) rc = iuproc.run_and_log_program(cmd, env_mapping, self.ctx.logger, cwd=os.path.dirname(p.input_ports.setuptools.easy_install)) if rc != 0: raise UserError(errors[ERR_PKG_INSTALL], {"pkg":package.__repr__(), "id":p.id}, developer_msg="return code was %d" % rc)
def is_installed(self): if not os.path.exists(self.config.home_path): return False rc = iuprocess.run_and_log_program([self.config.input_ports.python.home, "-c", "import gearman"], {}, logger) if rc == 0: return True else: logger.debug("%s: directory %s exists, but gearman package not found" % (self.id, self.config.home_path)) return False
def _run_setup_script(self, script_path, args, input=None): prog_and_args = [script_path] + args rc = iuprocess.run_and_log_program(prog_and_args, {}, logger, cwd=self.config.home_path, input=input) if rc != 0: raise MysqlError(ERR_SETUP_SCRIPT, "Install", self.config, {"script":os.path.abspath(script_path), "rc":rc})
def _run_admin_script(self, action): if not os.path.exists(self.config.gearman_admin_script): raise UserError(errors[ERR_NO_GEARMAN_SCRIPT], msg_args={"file": self.config.gearman_admin_script}) prog_and_args = [self.config.gearman_admin_script, action] rc = iuprocess.run_and_log_program(prog_and_args, {}, logger) if rc != 0: raise UserError( errors[ERR_GEARMAN_SCRIPT_FAILED], msg_args={"action": action}, developer_msg="script %s, rc was %d" % (self.config.gearman_admin_script, rc), )
def test_mongodb_connection(self, python_exe, connectTimeoutMS=1000): """To see if mongodb is really responding to client connections we create a pymongo connection. Unfortunately, this has to be done in the python virtualenv where we've installed pymongo as a dependency. To do this, we run the script as a subprocess and check the return code. """ rc = run_and_log_program([python_exe, "-c", "import pymongo.connection; pymongo.connection.Connection(connectTimeoutMS=%d)" % connectTimeoutMS], None, self.ctx.logger, cwd=os.path.dirname(python_exe)) return rc == 0
def install(self, package): # if this is a linux system, we need to make sure that uuid/uuid.h is present if self.config.input_ports.host.os_type == "linux": if not os.path.exists("/usr/include/uuid/uuid.h"): aptget.apt_get_install(["uuid-dev"], self._get_sudo_password()) base_name = os.path.basename(self.config.home_path) parent_dir = os.path.dirname(self.config.home_path) extracted_dir = package.extract(parent_dir) assert extracted_dir == base_name # configure with prefix self.confg.home_path, make and make install logger.info("Building gearman daemon") rc = iuprocess.run_and_log_program( ["/usr/bin/make", "all"], {"PATH": "/usr/bin:/bin:/usr/sbin"}, logger, cwd=self.config.home_path ) if rc != 0: raise UserError(errors[ERR_GEARMAN_BUILD_FAILED]) gearman_pyclient_dir = os.path.join(os.path.join(self.config.home_path, "src"), "gearman-1.5.0") logger.info("Installing gearman python client") # TODO: this should really be done using easy_install. Even better, # we should upgrade to the latest version of Gearman and install the # version of the client on PyPi. rc = iuprocess.run_and_log_program( [self.config.input_ports.python.home, "setup.py", "install"], {}, logger, cwd=gearman_pyclient_dir ) if rc != 0: raise UserError(errors[ERR_GEARMAN_PY_SETUP_FAILED]) # instantiate the startup/shutdown script for gearmand script_tmpl_path = iufile.get_data_file_path(__file__, "gearmand.sh.tmpl") iufile.instantiate_template_file( script_tmpl_path, self.config.gearman_admin_script, {"gearman_home": self.config.home_path, "log_dir": self.config.log_dir, "pid_file": self.config.pid_file}, logger=logger, ) # check that everything is now in place self.validate_post_install()
def install(self, download_url): logger.debug("Installing AccountManagerPlugin from %s" % download_url.location ) install_prefix = string.join(["--prefix",self.config.genforma_home], '=') # XXX this needs to be in the resource defs! install_dir = "--install-dir=" + self.config.PYTHONPATH install_cmd = self.config.easy_install rc = iuprocess.run_and_log_program([install_cmd, install_prefix, install_dir, download_url.location], {}, logger, None, None) if rc != 0: raise UserError(errors[ERR_TRAC]) logger.debug("Done installing AccountManagerPlugin")
def _run_python_script(self, script_name, arglist, file_layout, input=None): script_path = iufile.get_data_file_path(__file__, script_name) prog_and_args = [self.config.input_ports.python.home, script_path] + arglist rc = iuprocess.run_and_log_program(prog_and_args, file_layout.get_django_env_vars(), logger, cwd=file_layout.get_settings_file_directory(), input=input, hide_input=True) if rc != 0: raise UserError(errors[ERR_DJANGO_PYTHON_SCRIPT_FAILED], msg_args={"appname":self.config.app_short_name, "script":script_name}, developer_msg="return code was %d, script at %s" % (rc, script_path))
def run_admin_command(self, command, arglist, cwd=None): """Run a command of the django-admin.py script """ prog_and_args = [self.django_admin_py, command] + arglist if not cwd: cwd = self.settings_file_directory rc = iuprocess.run_and_log_program(prog_and_args, self.get_django_env_vars(), logger, cwd=cwd) if rc != 0: raise UserError(errors[ERR_DJANGO_ADMIN_CMD_FAILED], msg_args={"cmd":' '.join([command]+arglist)}, developer_msg="return code was %d, PYTHONPATH was %s, DJANGO_SETTINGS_MODULE was %s, current working directory was %s" % (rc, self.python_path_directory, self.deployed_settings_module, cwd))
def _install_pip_requirements(self, requirements_file_path): prog_and_args = [self.config.input_ports.pip.pipbin, "install", "--use-mirrors", "--timeout=%d" % PIP_TIMEOUT, "--requirement=%s" % requirements_file_path] env = {} if os.path.exists(self.config.package_cache_dir): env['PIP_DOWNLOAD_CACHE'] = self.config.package_cache_dir rc = iuprocess.run_and_log_program(prog_and_args, env, logger, cwd=os.path.dirname(self.config.input_ports.pip.pipbin)) if rc == 0: logger.info("Successful installed requirements from file %s" % requirements_file_path) else: raise UserError(errors[ERR_REQUIREMENTS_INSTALL_FAILED], msg_args={"file":requirements_file_path}, developer_msg="return code was %d" % rc)
def run(self, user, password, command_text, command_text_for_logging=None): p = self.ctx.props cmd = [self.mysql_client_exe, "-u", user, "--password=%s" % password] self.ctx.logger.debug(' '.join([self.mysql_client_exe, "-u", "root", "--password=****"])) rc = procutils.run_and_log_program(cmd, None, self.ctx.logger, input=command_text, hide_command=True, hide_input=True) if rc!=0: raise UserError(errors[ERR_MYSQL_CLIENT], msg_args={"id":p.id, "cmd":' '.join(cmd)}, developer_msg="rc was %d, command was: '%s'" % (rc, command_text))
def run(self, mysql_admin_props, mysql_admin_password_value, command_and_args): p = mysql_admin_props self._check_admin_props(p) cmd = [p.mysqladmin_exe, "-u", "root", "--password=%s" % mysql_admin_password_value] + \ command_and_args self.ctx.logger.debug(' '.join([p.mysqladmin_exe, "-u", "root", "--password=****"] + command_and_args)) rc = procutils.run_and_log_program(cmd, None, self.ctx.logger, hide_command=True) if rc!=0: raise UserError(errors[ERR_MYSQL_ADMIN], msg_args={"id":p.id, "cmd":' '.join(command_and_args)}, developer_msg="rc was %d" % rc)
def call_mysql(config, user, pwd, input, continue_on_error=False): cfg_filename = iufile.make_temp_config_file( "[mysql]\nuser=%s\npassword=%s\nport=%d\n" % (user, pwd, config.input_ports.mysql.port), dir=config.home_path ) defaults_file = "--defaults-file=%s" % cfg_filename socket_file = "--socket=%s" % config.socket_file try: rc = iuprocess.run_and_log_program( [config.mysql_path, defaults_file, socket_file], {}, logger, cwd=config.home_path, input=input ) finally: os.remove(cfg_filename) if rc != 0 and not continue_on_error: raise AgilefantError( ERR_CALL_MYSQL, "Install", config, developer_msg="Return code: '%d', Input: '%s'" % (rc, input) ) return rc
def run(self, password_file, username, password, apache_config): class LogProxy: """We need to wrap the logger and capture any action events, as those may contain the password. """ def __init__(self, logger): #Set attribute. self._logger = logger def __getattr__(self, attrib): if attrib == "action": return self.action else: return getattr(self._logger, attrib) def action(self, msg): pass htpasswd_exe = apache_config.htpasswd_exe action._check_file_exists(htpasswd_exe, self) if os.path.exists(password_file): cmd = [htpasswd_exe, "-b", password_file, username, password] else: cmd = [htpasswd_exe, "-b", "-c", password_file, username, password] if self.ctx._get_sudo_password(self)==None or iuprocess.is_running_as_root(): self.ctx.logger.action("%s <password>" % " ".join(cmd[0:-1])) rc = iuprocess.run_and_log_program(cmd, {}, LogProxy(self.ctx.logger)) if rc != 0: raise UserError(errors[ERR_APACHE_HTPASSWD], msg_args={"exe": htpasswd_exe, "file": password_file, "id":self.ctx.props.id}, developer_msg="return code was %d" % rc) else: try: logger.action("sudo %s <password>" % " ".join(cmd[0:-1])) iuprocess.run_sudo_program(cmd, self.ctx._get_sudo_password(self), LogProxy(self.ctx.logger)) except Exception, e: exc_info = sys.exc_info() logger.exception("exception in htpasswd: %s, resource %s" % (e.__repr__(), ctx.props.id)) raise convert_exc_to_user_error(exc_info, errors[ERR_APACHE_HTPASSWD], msg_args={"exe": htpasswd_exe, "file": password_file, "id":self.ctx.props.id}, developer_msg="exception" % e.__repr__())
def install(self, package): logger.debug("Installing GitPlugin") #wget http://trac-hacks.org/changeset/latest/gitplugin?old_path=/&filename=gitplugin&format=zip extracted_dir = package.extract(self.config.genforma_home) logger.debug("Extracted directory is: " + extracted_dir) #extract zip file #python setup.py install --prefix=pythonpath setup_script_dir = iupath.join_list([self.config.genforma_home, extracted_dir, "0.11"]) setup_script = os.path.join(setup_script_dir, "setup.py") # must run setup from the setup script directory rc = iuprocess.run_and_log_program([self.config.input_ports.python.home, setup_script, "install"], {}, logger, cwd=setup_script_dir) if rc != 0: raise UserError(errors[ERR_GITPLUGIN], developer_msg="Python setup failed"); logger.debug("Done installing GitPlugin")
def shutdown(config, root_pw=None): """Shutdown the mysql server using mysqladmin. Doesn't check whether it was running. Returns True if successful, False otherwise. """ if root_pw==None: root_pw = config.admin_password cfg_filename = _make_config_file("mysqladmin", None, root_pw, config.port) args = [config.mysqladmin_path, "--defaults-file=%s" % cfg_filename, "--socket=%s" % config.socket_file, "shutdown"] try: rc = iuprocess.run_and_log_program(args, None, logger, cwd=config.home_path) finally: os.remove(cfg_filename) if rc!=0: return False else: return True
def _do_query(query_str, config, action, root_pw=None): if root_pw==None: root_pw = config.admin_password cfg_filename = _make_config_file("mysql", config.bin_dir, root_pw, config.port) mysql = os.path.join(config.bin_dir, "mysql") defaults_file = "--defaults-file=%s" % cfg_filename socket = "--socket=%s" % config.socket_file try: logger.debug("Running query '%s'" % query_str) rc = iuprocess.run_and_log_program([mysql, defaults_file, socket], {}, logger, cwd=config.home_path, input=query_str) finally: os.remove(cfg_filename) if rc!=0: raise MysqlError(ERR_MYSQL_QUERY, action, config, {"rc":rc})
def check_if_module_installed(python_exe, module_name, python_path_var=None): """Utility function to see if a python module is installed by trying to import it. """ env = copy.deepcopy(os.environ) if python_path_var: env["PYTHONPATH"] = python_path_var # to ensure consistent results, we run with a working directory # equal to the directory containing the python executable. This # ensures that we don't accidentally pick up modules in the current # directory. cwd = os.path.dirname(python_exe) rc = procutils.run_and_log_program([python_exe, "-c", "import %s" % module_name], env, logger, cwd=cwd) if rc==0: logger.debug("Python module %s is installed" % module_name) return True else: logger.debug("Python module %s not found" % module_name) return False
def install(self, download_url): logger.debug("installing trac %s" % download_url.location ) print self.config.home install_prefix = string.join(["--prefix",self.config.home], '=') # XXX this needs to be in the resource defs! install_dir = "--install-dir=" + self.config.input_ports.python.PYTHONPATH install_cmd = self.config.input_ports.setuptools.easy_install rc = iuprocess.run_and_log_program([install_cmd, install_prefix, install_dir, download_url.location], {}, logger, None, None) if rc != 0: raise UserError(errors[ERR_TRAC]) if self._has_patch(): patch_dir = os.path.join(self.config.input_ports.python.PYTHONPATH, TRAC_EGG_DIRNAME) self._install_patch(patch_dir) # we need to recompile the python files after applying the patch run_compileall(self.config.input_ports.python.home, patch_dir, logger)
def setup_slave_host(resource, master_deployment_home, password_file, password_salt_file): bootstrap_script = os.path.abspath(os.path.join(master_deployment_home, "engage/bootstrap.py")) assert os.path.exists(bootstrap_script), "Can't find bootstrap script %s" % \ bootstrap_script python_exe = find_python_executable(logger) dh = resource["config_port"]["genforma_home"] logger.info("Bootstrapping slave node %s" % resource["id"]) deployed_nodes_root = os.path.dirname(dh) if not os.path.exists(deployed_nodes_root): os.makedirs(deployed_nodes_root) try: rc = procutils.run_and_log_program([python_exe, bootstrap_script, "-p", python_exe, dh], None, logger, cwd=os.path.dirname(bootstrap_script)) except Exception, e: logger.exception("Error in slave bootstrap for %s: %s" % (e, resource["id"])) raise UserError(errors[ERR_SLAVE_BOOTSTRAP], msg_args={"host":resource["id"]}, developer_msg="deployment home was %s" % dh)
def install(self, package): logger.debug("Installing %s" % self.package_name) extracted_dir = package.extract(self.config.genforma_home) logger.debug("Extracted directory is: " + extracted_dir) # if there is a patch, install it now if self._has_patch(): self._install_patch(os.path.join(self.config.genforma_home, extracted_dir)) #python setup.py install --prefix=pythonpath setup_script_dir = iupath.join_list([self.config.genforma_home, extracted_dir, self.trac_version]) setup_script = os.path.join(setup_script_dir, "setup.py") args = [self.config.input_ports.python.home, setup_script, "install"] # must run setup from the setup script directory rc = iuprocess.run_and_log_program(args, {},logger, cwd=setup_script_dir) if rc != 0: raise UserError(errors[ERR_TRAC_PLUGIN_SETUP], msg_args={'plugin': self.package_name}, developer_msg=' '.join(args)) logger.debug("Done installing %s" % self.package_name)
def run(self, user, password, script_file, database=None): p = self.ctx.props _check_file_exists(script_file, self) cmd = [p.input_ports.mysql_admin.mysql_client_exe, "-u", user, "--password=%s" % password] if database: cmd.extend(["-D", database]) # make a version of cmd safe for logging no_pw_cmd = copy.copy(cmd) no_pw_cmd[3] = "--password=****" self.ctx.logger.debug(' '.join(no_pw_cmd)) with open(script_file, "r") as sf: input_data = sf.read() rc = procutils.run_and_log_program(cmd, None, self.ctx.logger, input=input_data, hide_command=True, hide_input=True) if rc!=0: raise UserError(errors[ERR_MYSQL_SCRIPT], msg_args={"id":p.id, "cmd":' '.join(cmd), "script":script_file}, developer_msg="rc was %d, command was: '%s'" % (rc, command_text))
def is_database_installed(self, psql_exe, database_name, database_user): _check_file_exists(psql_exe, self) rc = procutils.run_and_log_program([psql_exe, '-d', database_name, '-U', database_user, '-c', r'\d'], None, self.ctx.logger, os.path.dirname(psql_exe)) return rc==0
def install(self, download_url): logger.debug("installing trac project %s" % self.config.projectname ) # get the passwords that we will need from the repository sudo_password = \ install_context.password_repository.get_value(self.config.sudo_password) admin_password = \ install_context.password_repository.get_value(self.config.admin_password) try: trac_admin_exe = os.path.join(self.config.trachome, "bin/trac-admin") rc = iuprocess.run_and_log_program([trac_admin_exe, self.config.projecthome, "initenv", self.config.projectname, self.config.projectdb, self.config.version_control, self.config.repository], {}, logger, None, None) if rc != 0: raise UserError(errors[ERR_TRACADMIN_FAILURE]) logger.debug("trac-admin ran successfully.") permissions = [ "BROWSER_VIEW", "CHANGESET_VIEW", "FILE_VIEW", "LOG_VIEW", "MILESTONE_VIEW", "REPORT_SQL_VIEW", "REPORT_VIEW", "ROADMAP_VIEW", "SEARCH_VIEW", "TICKET_CREATE", "TICKET_APPEND", "TICKET_MODIFY", "TICKET_VIEW", "TIMELINE_VIEW", "WIKI_CREATE", "WIKI_MODIFY", "WIKI_DELETE", "WIKI_VIEW" ] # drop permissions for anonymous rc = iuprocess.run_and_log_program([trac_admin_exe, self.config.projecthome, "permission", "remove", "anonymous"] + permissions, {}, logger, None, None) if rc != 0: raise UserError(errors[ERR_TRACADMIN_FAILURE]) logger.debug("trac-admin removed permissions for anonymous.") # add permissions for authenticated rc = iuprocess.run_and_log_program([trac_admin_exe, self.config.projecthome, "permission", "remove", "authenticated", '*'], {}, logger, None, None) rc = iuprocess.run_and_log_program([trac_admin_exe, self.config.projecthome, "permission", "add", "authenticated"] + permissions, {}, logger, None, None) if rc != 0: raise UserError(errors[ERR_TRACADMIN_FAILURE]) logger.debug("trac-admin added permissions for authenticated.") # now add permission for admin user rc = iuprocess.run_and_log_program([trac_admin_exe, self.config.projecthome, "permission", "add", self.config.administrator, "TRAC_ADMIN"], {}, logger, None, None) logger.debug("trac-admin added permissions successfully.") if os.path.exists(self.config.password_file) == False: # set up the password file and add admin with initial password logger.debug("about to make password file") # TODO: htpasswd_exe is the program installed with Apache to create/update passwords. # This causes us to have an implicit dependency on apache. Need to figure out # a way to remove this dependency. Perhaps we can provide generic methods on the webserver # service class or in the engage.utils package. htpasswd_exe = self.config.input_ports.webserver.htpasswd_exe rc = iuprocess.run_and_log_program([htpasswd_exe, "-cbm", self.config.password_file, self.config.administrator, admin_password], {}, logger, None, None) else: pass # XXX: check user administrator exists trac_ini_file = os.path.abspath(os.path.join(self.config.projecthome, "conf/trac.ini")) logger.debug("Looking for ini file " + trac_ini_file) if os.path.exists(trac_ini_file) == False: raise UserError(errors[ERR_TRAC_INI_NOT_FOUND]) # now hack the trac.ini file for git plugin if self.config.version_control == "git": trac_ini_file_changed = trac_ini_file + ".changed" git_bin = self.config.input_ports.repository.git_exe escaped_git_bin = string.replace(git_bin, "/", "\/") logger.debug("git path is " + git_bin) f = open(trac_ini_file, "r") (tmpf, tmpn) = tempfile.mkstemp() for line in f : cline = line.replace("cached_repository = false", "cached_repository = true") cline = cline.replace("persistent_cache = false", "persistent_cache = true") cline = re.sub("git_bin = .*$", "git_bin = " + git_bin, cline) os.write(tmpf, cline) os.write(tmpf, "[components]\ntracext.git.* = enabled\n"); f.close() os.close(tmpf) shutil.copyfile(tmpn, trac_ini_file) cfg = TracConfig(trac_ini_file) # basic setup # set base_url cfg.update("trac", "base_url", self.config.get_base_url()) # set up notification # By default, use SMTP # See http://trac.edgewall.org/wiki/TracNotification notification_string = self.config.get_smtp_notification_string() cfg.set_config(json.loads(notification_string)) #plugins logger.debug(self.config.acctmgrconf) conf = json.loads((self.config.acctmgrconf).__str__()) logger.debug(conf) cfg.set_config(conf) cfg.update("account-manager", "password_file", self.config.password_file) # disable new users registering on the web cfg.update("components", "acct_mgr.web_ui.registrationmodule", "disabled") logger.debug(self.config.gitpluginconf) conf = json.loads((self.config.gitpluginconf).__str__()) cfg.set_config(conf) logger.debug(self.config.iniadminconf) conf = json.loads((self.config.iniadminconf).__str__()) cfg.set_config(conf) logger.debug(self.config.themeengineconf) conf = json.loads((self.config.themeengineconf).__str__()) cfg.set_config(conf) logger.debug(self.config.gfappconf) conf = json.loads((self.config.gfappconf).__str__()) cfg.set_config(conf) cfg.update("gfapp", "tracbin", self.config.trachome) cfg.update("gfapp", "trachome", self.config.projecthome) logger.debug(self.config.permredirectconf) conf = json.loads((self.config.permredirectconf).__str__()) cfg.set_config(conf) logger.debug(self.config.gfdownloadconf) conf = json.loads((self.config.gfdownloadconf).__str__()) cfg.set_config(conf) # enable logging cfg.update("logging", "log_file", os.path.join(self.config.projecthome, "trac.log")) cfg.update("logging", "log_type", "file") cfg.update("logging", "log_level", "DEBUG") cfg.update("trac", "mainnav", "wiki,genforma,search") menu_string = self.config.get_menu_string() menu_f = cStringIO.StringIO(menu_string) menu_cfg = ConfigParser.SafeConfigParser() menu_cfg.readfp(menu_f) menu_f.close() for section in menu_cfg.sections(): for (menuname, menuval) in menu_cfg.items(section): cfg.update(section, menuname, menuval) cfg.writeback() logger.debug("Done updating trac.ini file") # upgrade trac environment rc = iuprocess.run_and_log_program([trac_admin_exe, self.config.projecthome, "upgrade"], {}, logger, None, None) if rc != 0: raise UserError(errors[ERR_TRAC_DEPLOY]) # set up Apache + Fastcgi if self.config.webserver == "apache-fastcgi" : logger.debug("setting up apache fastcgi") # trac deploy # make fastcgi config file rc = iuprocess.run_and_log_program([trac_admin_exe, self.config.projecthome, "deploy", os.path.join(self.config.projecthome, "www")], {}, logger, None, None) if rc != 0: raise UserError(errors[ERR_TRAC_DEPLOY]) fcgi_config_file_path = os.path.join(self.config.additional_config_dir, self.config.projectname + ".conf") if os.path.exists(fcgi_config_file_path): logger.warn("Apache configuration file already exists. Will be overwritten.") httpd_config_string = self.config.get_httpd_config_string([("TRAC_ENV", self.config.projecthome), ("TRAC_ENV_PARENT_DIR", "%s/../" % self.config.projecthome)]) (tmpf, tmpn) = tempfile.mkstemp() os.write(tmpf, httpd_config_string) if self.config.protocol == "https": https_config_string = self.config.get_https_config_string() os.write(tmpf, https_config_string) os.close(tmpf) iuprocess.sudo_copy([tmpn, fcgi_config_file_path], sudo_password, logger) self._update_and_copy_fcgi_file(sudo_password) # make sure the project directory is writeable by apache user iuprocess.sudo_chown(self.config.input_ports.webserver.apache_user, [self.config.projecthome], sudo_password, logger, recursive=True) # XXX: hack: need to fix. tracd runs as current user and needs access to log directory # but apache does not iuprocess.sudo_chown(os.environ["LOGNAME"], [self.config.logdir], sudo_password, logger, recursive=True) logger.debug("Done installing httpd configuration files") except iuprocess.SudoError, e: exc_info = sys.exc_info() sys.exc_clear() raise convert_exc_to_user_error(exc_info, errors[ERR_TRAC_SUDO_CALL], nested_exc_info=e.get_nested_exc_info())