def check_mount_bind_bug(): """Check that is possible to perform "mount --bind" command. This bug appear on PCS containers with outdated systemd. It was fixed (POA-99460). """ # It reproducible only on containers with RHEL/CentOS 7.2, so we need to check this. if determinePlatform().osverfull[:2] != ('7', '2') or not os.path.isfile("/proc/user_beancounters"): return True # Trying to bindmount inner_dir to outer_dir, raising an error if "mount --bind" failed. outer_dir = "/root/bind_test_dir_outer" inner_dir = "/root/bind_test_dir_inner" uUtil.execCommand(["mkdir", outer_dir, inner_dir]) try: uLogging.debug("Testing execution of \"mount --bind\" command started. ") uUtil.execCommand(["mount", "--bind", outer_dir, inner_dir]) # Waiting 2 sec after mounting (as pointed out by Vasily Averin), # if inner_dir is absent in mtab, umount will return an error. time.sleep(2) uUtil.execCommand(["umount", inner_dir]) uUtil.execCommand(["rmdir", outer_dir, inner_dir]) uLogging.debug("Testing execution of \"mount --bind\" command successfully passed. ") return True except: uUtil.execCommand(["rmdir", outer_dir, inner_dir]) uLogging.err('Precheck error: "mount --bind" command executed idly.\n') import sys sys.tracebacklimit = 0 raise Exception('\nUnable to complete the installation. ' 'The precheck error occurred: "mount --bind" command executed idly. ' 'This functionality is critical for the named daemon. If you use Virtuozzo container, ' 'then probably the systemd version in your OS repository is outdated. In this case, ' 'you should update your systemd to the version "systemd-219-19.el7_2.3" or higher ' 'so the "mount --bind" can be executed correctly.')
def adjustMemSettings(product_name, mem): def edit_sysctl_conf(infile, outfile, invz, mem): changed_all = changed_max = False for ln in infile: l = ln.split('=', 1) if len(l) == 2: p, v = l p = p.strip() if p == 'kernel.shmall': print >> outfile, 'kernel.shmall = %s' % mem changed_all = True elif p == 'kernel.shmmax': print >> outfile, 'kernel.shmmax = %s' % mem changed_max = True elif invz and p == "net.ipv4.tcp_syncookies": print >> outfile, '#', ln.strip() else: outfile.write(ln) else: outfile.write(ln) if not changed_all or not changed_max: print >> outfile, "# Required by", product_name if not changed_all: print >> outfile, 'kernel.shmall = %s' % mem if not changed_max: print >> outfile, 'kernel.shmmax = %s' % mem uUtil.editFileSafe('/etc/sysctl.conf', edit_sysctl_conf, '/etc/sysctl.conf.pasave', inVZContainer(), mem) uUtil.execCommand(["sysctl", "-p"], [0, 255])
def installPOACoreBinaries(config, progress, build_rpms): uLogging.debug("Installing core RPM dependencies") uUtil.execCommand( ["yum", "-y", "-e", "0", "install", "libselinux-utils", "libgcc.x86_64", "glibc.x86_64", "libgcc.i686", "glibc.i686"]) uLogging.debug("Installing core RPM files") yum_local_install_package(build_rpms)
def configureSystem(config, progress): initSysLog(config) def setupService(name, binaryPath, displayName, description): nameQuoted = "\"%s\"" % name uUtil.execCommand("net stop %s" % nameQuoted, [0, 2]) # service name invalid uLogging.info("service %s stopped" % name) uUtil.execCommand("sc delete %s" % nameQuoted, [0, 1060]) # service not exist uLogging.info("service %s deleted" % name) uUtil.execCommand("sc create %s binPath= \"%s\" DisplayName= \"%s\" start= auto" % (nameQuoted, binaryPath, displayName)) uUtil.execCommand("sc description %s %s" % (nameQuoted, description)) uLogging.info("service %s created" % name) setupService("pleskd", os.path.join(config.rootpath, "bin", "watchdog.exe"), "PEM", "\"Operations Automation service\"") syslogdName = "PEM syslogd" setupService(syslogdName, os.path.join(config.rootpath, "syslog", "syslogd.exe") + " --service", syslogdName, "\"Operations Automation Syslog Service\"") uUtil.execCommand("net start \"%s\"" % syslogdName) uLogging.info("service %s started" % syslogdName) return
def deploy_file_for_test(self): uLogging.debug("Bloating dummy file for speed test in {deployed_path}".format(deployed_path=self.deployed_path)) uUtil.execCommand("dd if=/dev/zero of={deployed_path} bs=1M count={file_size_mb}".format( deployed_path=self.deployed_path, file_size_mb=self.file_size_mb)) uLogging.debug("Modifying magic number for recognizing fake file by processor for the 'fetch' HCL command.") with open(self.deployed_path, "r+b") as file_for_test: file_for_test.write(self.fake_magic_number)
def installPOACoreBinaries(config, progress, build_rpms): """ build_rpms needed just for keep the call signature build_rpms used in uLinux, where it's a list of new rpm's to install """ win_files_dir = os.path.abspath(os.path.join(config.source_dir, "os", Const.getDistribWinDir())) progress.set_progress(75, "Installing POA MSI") logfile = os.environ['SYSTEMDRIVE'] + "\\poacore-install.log" uUtil.execCommand(["msiexec", "/i", os.path.join(win_files_dir, "poa-core.msi"), "/l*v", logfile, "POA_INSTALL=1", "FULL_COMPUTER_NAME=" + config.hostname])
def update_java_tzdata(jdk_tzupdater_path): if os.path.isfile(jdk_tzupdater_path): # requested http://www.iana.org/time-zones/repository/tzdata-latest.tar.gz tzupdater = '%s -jar %s -l' % (get_java_binary(), jdk_tzupdater_path) uLogging.debug('Updating java time zones') uUtil.execCommand( tzupdater, valid_codes=1) # tolerate failure if no iana.org access else: uLogging.debug('%s not found, skipping time zone update' % jdk_tzupdater_path)
def create_ssl_proxy(config, port=9443): uLogging.info('Creating SSL proxy') uUtil.execCommand(["yum", "-y", "install", "mod_ssl"]) key, cert = create_ssl_cert(config) vh = ssl_proxy_vhost_template % { 'host': socket.gethostname(), 'port': port, 'ip': config.external_ip, 'key': key, 'cert': cert} conf_file = 'ppa_ssl_proxy.conf' f = open(os.path.join(httpd_conf_dir, conf_file), "w") f.write(vh) f.close() service_control('restart', 'httpd')
def update_essentials_billing(host_id, bm_packages): if filter(lambda x: not is_billing_package(x.package.name), bm_packages): raise Exception( "Following packages without \"bm\" prefix, but installing as billing packages: {0} " .format(str(bm_packages))) uLogging.debug("Stopping billing.") stop_pba() uLogging.debug("Updating billing packages.") uPEM.update_packages_on_host(host_id, bm_packages) # # Reloading all modules from billingToolsPath TODO: Right way, function stop_pba() is a crutch. # modules_for_reload = filter( # lambda x: x is not None and hasattr(x, "__file__") and billingToolsPath in x.__file__, # sys.modules.values()) # map(reload, modules_for_reload) sys.path.append(billingToolsPath) import pba import configure import configure_db sys.path.remove(billingToolsPath) uLogging_info = uLogging.info uLogging_debug = uLogging.debug uLogging_log = uLogging.log # Disable a lot of messages during billing update uLogging.debug = uLogging.log_func(None, uLogging.DEBUG) uLogging.info = uLogging.log_func(None, uLogging.INFO) uLogging.log = uLogging.log_func(None, None) uLogging_info("Starting configure billing. ") (configure_db.o, configure_db.args) = configure_db.getOptions(['--unattended', '--ppab']) configure_db.main(configure_db.o, configure_db.args) uLogging_info("BSS DB configuration has been successfully completed.") (configure.o, configure.args) = configure.getOptions(['--unattended']) configure.main(configure.o, configure.args) uLogging_info( "BSS Application configuration has been sucessfully completed.") uUtil.execCommand(['sh', '/usr/local/bm/templatestore/tools/configure.sh']) uLogging_info("BSS Store configuration has been successfully completed.") uLogging_info("Billing configuration has been successfully completed.") uLogging_debug("Starting billing.") pba.start()() # restoring uLogging.* functions uLogging.debug = uLogging_debug uLogging.info = uLogging_info uLogging.log = uLogging_log
def create_ssl_cert(config): uLogging.debug('Creating self-signed SSL certificate') ssl_path = os.path.join(config.rootpath, 'etc', 'ssl') if not os.path.exists(ssl_path): os.makedirs(ssl_path, 0755) key_file = os.path.join(ssl_path, 'ppa_ssl_proxy_key.pem') cert_file = os.path.join(ssl_path, 'ppa_ssl_proxy_cert.pem') cmd = '%s req -x509 -newkey rsa:2048 -keyout %s -out %s -days 366 -nodes -subj "/CN=%s"' % ( uCrypt._get_openssl_binary(), key_file, cert_file, config.external_ip) uUtil.execCommand(cmd) os.chmod(key_file, 0600) os.chmod(cert_file, 0600) return key_file, cert_file
def stopMN(minimal=False): if Const.isWindows(): # ignore 2 error code, because in 5.4 pem cannot be stopped properly uUtil.readCmd(['net', 'stop', 'pem'], valid_codes=[0, 2]) uUtil.readCmd(['net', 'stop', 'PAU'], valid_codes=[0, 1, 2]) else: if not minimal: # pem script actually returns 1 and 123 on valid stops uUtil.execCommand('service pa-agent stop', [0, 1, 123]) uUtil.execCommand('service pau stop', [0, 1, 5]) # In some mysterious cases "service pa-agent stop" doesn't work uUtil.readCmdExt(['killall', '-9', 'pa-agent']) uUtil.readCmdExt(['killall', '-9', 'SoLoader']) resetPIDs()
def setupService(name, binaryPath, displayName, description): nameQuoted = "\"%s\"" % name uUtil.execCommand("net stop %s" % nameQuoted, [0, 2]) # service name invalid uLogging.info("service %s stopped" % name) uUtil.execCommand("sc delete %s" % nameQuoted, [0, 1060]) # service not exist uLogging.info("service %s deleted" % name) uUtil.execCommand("sc create %s binPath= \"%s\" DisplayName= \"%s\" start= auto" % (nameQuoted, binaryPath, displayName)) uUtil.execCommand("sc description %s %s" % (nameQuoted, description)) uLogging.info("service %s created" % name)
def removePOACoreBinaries(): uUtil.execCommand(["yum", "-y", "-e", "0", "remove", "pleskd", "pa-agent", "poa-core", "pa-core"]) # in PPA, billing is on MN uUtil.execCommand(["yum", "-y", "-e", "0", "remove", "bm"]) uUtil.execCommand(["yum", "-y", "-e", "0", "remove", "poaupdater"]) service_control('stop', 'httpd', valid_codes=[0, 1]) uLogging.debug('Trying to remove /etc/httpd directory') shutil.rmtree('/etc/httpd', ignore_errors=True) uUtil.execCommand(["yum", "-y", "-e", "0", "reinstall", "httpd", "mod_ssl", "php"]) service_control('start', 'httpd') removeBilling()
def __yum_local_deploy_package(rpms, command, **kwargs): file_names = [] for rkey in rpms.keys(): if rkey == tuple([rpms[rkey]["info"].name, "RHEL", determinePlatform().osverfull[0]]): rpm_file = rpms[rkey]['path'] if not rpm_file: if 'strict' in kwargs and kwargs['strict'] is False: continue else: raise Exception('Unable to find rpm %s in distribution at %s' % (rpms[rkey]["info"].name, rpm_file)) file_names.append(rpm_file) if file_names: command = ["yum", "-y", "--nogpgcheck", command] + file_names try: uUtil.execCommand(command) except uUtil.ExecFailed as e: uLogging.err("""Failed to install [%s]:\n Command '%s' failed\n Check if YUM is properly installed and configured, note that you can use option --repo-base-url to customize Central PA YUM URL.""" % (' '.join(file_names), " ".join(command))) raise e
def updatePPMs(newest_packages): mirror = getMainMirror() host, path, host_id = mirror.hostname, mirror.localpath, mirror.host_id tarballs_to_copy = [] for pform in newest_packages: for ctype in newest_packages[pform]: tarballs_to_copy += [ x.tarball_location for x in newest_packages[pform][ctype].values() if x.tarball_location ] uAction.progress.do("updating packages at mirror '%s'", host) if host_id == 1: for fn in tarballs_to_copy: uUtil.ln_cp(fn, path) uLogging.debug("Copying %s to %s", fn, path) else: raise Exception("updateOneMirror is not implemented for host_id != 1") uUtil.execCommand("restorecon -R %s" % path) uAction.progress.done()
def startMN(minimal=False): resetPIDs() platform, root = getMNInfo() if Const.isWindows(): stopMN() # To ensure waitForJBossStarted will do correct from u import bootstrap os.remove(bootstrap.getJBossDir(root) + '\\standalone\\log\\standalone.log') uUtil.readCmd(['net', 'start', 'PAU']) # Service is stated as "started" before JBoss is actually started, need to wait waitForJBossStarted(root) uUtil.readCmd(['net', 'start', 'pem'], valid_codes=[0]) else: if minimal: env = dict() env.update(os.environ) pleskd_env = dict( LD_LIBRARY_PATH=str(os.path.join(root, "lib") + ":" + "/usr/pgsql-9.5/lib/"), SVC_CONF=str(os.path.join(root, "etc", "svc.conf")), PLESKD_PROPS=str(os.path.join(root, "etc", "pleskd.props")) ) env.update(pleskd_env) progname = os.path.join(root, "sbin", "pa-agent") cmd = [] cmd.append(progname) cmd.append("--props-file=" + os.path.join(root, "etc", "pleskd.props")) # LD_LIBRARY_PATH="/usr/local/pem/lib:/usr/pgsql-9.4/lib/" # PATH="${PATH}:/usr/local/pem/bin" /usr/local/pem/sbin/pleskd # --props-file /usr/local/pem/etc/pleskd.props --send-signal sp.Popen(cmd, env=env) else: uUtil.execCommand('service pau start', valid_codes=[0, 1]) uUtil.execCommand('service pa-agent start')
def stop_pba( ): # TODO: The right way is to use pba.stop()(). This is crutch for quick resolve PBA-74321. uUtil.execCommand(['service', 'pba', 'stop'], [0, 1]) service_list = [ 'scheduler', 'generic_worker', 'atm', 'logsrv', 'ssm', 'www', 'xmlrpcd' ] for service in service_list: try: uUtil.execCommand(['killall', service]) uUtil.execCommand(['killall', '-9', service]) except: pass
def removeBilling(): uLogging.debug('stopping billing, if any') service_control('stop', 'pba', valid_codes=[0, 1, 255]) billing_services = ['scheduler', 'generic_worker', 'atm', 'logsrv', 'ssm', 'www', 'xmlrpcd'] for service in billing_services: try: uUtil.execCommand(['killall', service]) uUtil.execCommand(['killall', '-9', service]) except: pass uLogging.debug('removing billing rpms, if any') uUtil.execCommand('yum -y -e 0 remove bm patools bm-*') bm_path='/usr/local/bm' if os.path.isdir(bm_path): uLogging.debug('Removing billing folder %s' % bm_path) shutil.rmtree(bm_path)
def restoreDB(config, path, askYesNo=uDialog.askYesNo): create_db(config, askYesNo, True) command_to_log = 'pg_restore --username=%s --host=%s --port=%s -Fc -n public -d %s %s' % (config.dsn_login, config.database_host, config.database_port, config.database_name, path) command = 'PGPASSWORD="******" %s ' % (config.dsn_passwd, command_to_log) uUtil.execCommand(command=command, command_to_log=command_to_log)
def removePkgFromRepo(pkg_id, nicename='package'): uAction.progress.do("removing %s (%s) from repository", nicename, pkg_id) uUtil.execCommand(ppm_ctl_cmd() + ['remove', 'pkg', str(pkg_id)]) uAction.progress.done()
def configureSystem(config, progress, PRODUCT): from poaupdater.uAction import retriable selinux_mode = uUtil.readCmd(['getenforce']).strip() uLogging.debug("SELinux is %s" % selinux_mode) progress.set_progress(1, "Adjusting kernel memory settings") all_mem, sh_mem = getMemTotal() adjustMemSettings(PRODUCT, all_mem) gname = config.sysgroup uname = config.sysuser progress.set_progress(2, "Creating group %s" % gname) try: grpinfo = grp.getgrnam(gname) except KeyError: retriable(uUtil.execCommand)(["groupadd", "-f", gname]) grpinfo = grp.getgrnam(gname) config.sysgroupid = grpinfo.gr_gid progress.set_progress(5, "Creating user %s" % uname) try: pwdinfo = pwd.getpwnam(uname) except KeyError: retriable(uUtil.execCommand)(["useradd", "-M", uname, "-g", gname, "-d", "/nonexistent", "-s", "/bin/false"]) pwdinfo = pwd.getpwnam(uname) config.sysuserid = pwdinfo.pw_uid config.sysgroupid = pwdinfo.pw_gid uLogging.debug("dump config after configureSystem: %s" % uUtil.stipPasswords(vars(config))) uLogging.debug("Setting hostname") hostname_line_pattern = re.compile(r"HOSTNAME=.*") def sysconfig_network(inf, outf): for ln in inf.readlines(): if hostname_line_pattern.match(ln): print >> outf, 'HOSTNAME="%(hostname)s"' % vars(config) else: outf.write(ln) uUtil.editFileSafe('/etc/sysconfig/network', sysconfig_network, '/etc/sysconfig/network.pemsave') uUtil.execCommand(["hostname", config.hostname]) #install httpd + modules httpd_rpms = ["httpd", "mod_ssl"] platform = determinePlatform() if platform.osver == "6": httpd_rpms.append("mod_proxy_wstunnel") # previous call resets hostname that triggers restarting Network Manager. /etc/resolv.conf content become not valid # for a moment. Reproduced sometimes on CentOS 7 VM in Azure IAAS uUtil.execCommand(["yum", "-y", "-e", "0", "install"] + httpd_rpms, retries=5) def tweak_httpd(inf, outf): conf_orig = inf.read() conf_1 = re.sub("ServerLimit.*10", "ServerLimit 256", conf_orig) conf_2 = re.sub("MaxClients.*10", "MaxClients 256", conf_1) outf.write(conf_2) prefork_conf = '/etc/httpd/conf/httpd.conf' if os.path.exists('/etc/httpd/conf.d/mpm_prefork.conf'): prefork_conf = '/etc/httpd/conf.d/mpm_prefork.conf' uUtil.editFileSafe(prefork_conf, tweak_httpd, prefork_conf + '.save') # drop the /icons/ alias; =<2.2.*: tweak httpd.conf, >=2.4.*: rename autoindex.conf if os.path.exists('/etc/httpd/conf.d/autoindex.conf'): uUtil.moveFile('/etc/httpd/conf.d/autoindex.conf', '/etc/httpd/conf.d/autoindex.conf.save') else: uUtil.replaceInFile('/etc/httpd/conf/httpd.conf', r'(?m)^\s*Alias\s+\/icons\/\s+', '#Alias /icons/ ', True) service_control('restart', 'httpd') service_autostart('httpd') if platform.osver == "7": def tweak_journald(inf, outf): conf_orig = inf.read() conf_1 = re.sub('#RateLimitInterval.*s', 'RateLimitInterval=0', conf_orig) conf_2 = re.sub('#Storage=auto', 'Storage=none', conf_1) conf_3 = re.sub('#ForwardToSyslog=no', 'ForwardToSyslog=yes', conf_2) outf.write(conf_3) journald_conf = '/etc/systemd/journald.conf' uUtil.editFileSafe(journald_conf, tweak_journald, journald_conf + '.save') def tweak_rsyslog(inf, outf): conf_orig = inf.read() conf_1 = re.sub('\$ModLoad imjournal', '#$ModLoad imjournal', conf_orig) conf_2 = re.sub('\$IMJournalStateFile imjournal.state', '#$IMJournalStateFile imjournal.state', conf_1) conf_3 = re.sub('\$OmitLocalLogging on', '$OmitLocalLogging off', conf_2) outf.write(conf_3) rsyslog_conf = '/etc/rsyslog.conf' uUtil.editFileSafe(rsyslog_conf, tweak_rsyslog, rsyslog_conf + '.save') def tweak_unix_datagram_query_len(inf, outf): """Tweak unix datagram query length for properly forwarding logs from journald to rsyslog""" conf_orig = inf.read() qlen_regex = re.compile('\nnet\.unix\.max_dgram_qlen.*') if qlen_regex.search(conf_orig): conf_modified = qlen_regex.sub('\nnet.unix.max_dgram_qlen=500', conf_orig) else: conf_modified = conf_orig + "\nnet.unix.max_dgram_qlen=500\n" outf.write(conf_modified) sysctl_conf = "/etc/sysctl.conf" uUtil.editFileSafe(sysctl_conf, tweak_unix_datagram_query_len, sysctl_conf + ".save") # Restart all tweaked services service_control('restart', 'systemd-journald') service_control('restart', 'rsyslog') uUtil.execCommand(["sysctl", "-p"], [0, 255])
def removePOACoreBinaries(): productId = getPOAProductId() uUtil.execCommand("cmd.exe /c start /wait msiexec /x %s /qn" % productId)
def configureODBC(config): c = """odbcconf /a {CONFIGSYSDSN "%s" "DSN=%s|Database=%s|Server=%s|Description=Primary POA DSN"}""" % ( config.database_odbc_driver, config.dsn, config.database_name, config.database_host) uLogging.debug("configuring ODBC with: %s" % c) uUtil.execCommand(c)
def installJDK(win_files_dir): fullPath = os.path.join(win_files_dir, "jdk-8u112.exe") runCmd = 'cmd.exe /c start "title" /wait "' + fullPath + '" /s ADDLOCAL="ToolsFeature"' uUtil.execCommand(runCmd)
def installWinFile(win_files_dir, file): uUtil.execCommand([os.path.join(win_files_dir, file), "/Q"])
def dumpDB(config, path): command_to_log = 'pg_dump --username=%s --host=%s --port=%s -Fc %s > %s' % (config.dsn_login, config.database_host, config.database_port, config.database_name, path) command = 'PGPASSWORD="******" %s ' % (config.dsn_passwd, command_to_log) uUtil.execCommand(command=command, command_to_log=command_to_log)
def service_autostart(name): if int(determinePlatform().osver) >= 7: c = "systemctl enable %s" % name else: c = "chkconfig --add {0}; chkconfig --levels 345 {0} on".format(name) uUtil.execCommand(c)
def service_control(command, name, valid_codes=None): if int(determinePlatform().osver) >= 7: c = "systemctl %s %s" % (command, name) else: c = "service %s %s" % (name, command) uUtil.execCommand(c, valid_codes)