1 # The software in this package is distributed under the GNU General
2 # Public License version 2 (with a special exception described below).
4 # A copy of GNU General Public License (GPL) is included in this distribution,
5 # in the file COPYING.GPL.
7 # As a special exception, if other files instantiate templates or use macros
8 # or inline functions from this file, or you compile this file and link it
9 # with other works to produce a work based on this file, this file
10 # does not by itself cause the resulting work to be covered
11 # by the GNU General Public License.
13 # However the source code for this file must still be made available
14 # in accordance with section (3) of the GNU General Public License.
16 # This exception does not invalidate any other reasons why a work based
17 # on this file might be covered by the GNU General Public License.
19 # Copyright (c) 2016-2018 Intra2net AG <info@intra2net.com>
24 ------------------------------------------------------
25 Guest utility to wrap arnied related functionality through python calls.
27 .. note:: Partially DEPRECATED! Use :py:mod:`pyi2ncommon.arnied_api` or
28 :py:mod:`pyi2ncommon.cnfvar` whenever possible. In particluar, do not
29 use or extend functionality regarding configuration (`get_cnf`,
32 Copyright: Intra2net AG
34 There are three types of setting some cnfvar configuration:
36 1) static (:py:class:`set_cnf`) - oldest method using a static preprocessed
37 config file without modifying its content in any way
38 2) semi-dynamic (:py:class:`set_cnf_semidynamic`) - old method also using
39 static file but rather as a template, replacing regex-matched values to
40 adapt it to different configurations
41 3) dynamic (:py:class:`set_cnf_dynamic`) - new method using dictionaries
42 and custom cnfvar classes and writing them into config files of a desired
43 format (json, cnf, or raw)
47 ------------------------------------------------------
59 log = logging.getLogger('pyi2ncommon.arnied_wrapper')
65 #: default set_cnf binary
66 BIN_SET_CNF = "/usr/intranator/bin/set_cnf"
67 #: default arnied_helper binary
68 BIN_ARNIED_HELPER = "/usr/intranator/bin/arnied_helper"
69 #: default location for template configuration files
71 #: default location for dumped configuration files
75 class ConfigError(Exception):
79 def run_cmd(cmd="", ignore_errors=False, vm=None, timeout=60):
81 Universal command run wrapper.
83 :param str cmd: command to run
84 :param bool ignore_errors: whether not to raise error on command failure
85 :param vm: vm to run on if running on a guest instead of the host
86 :type vm: :py:class:`virttest.qemu_vm.VM` or None
87 :param int timeout: amount of seconds to wait for the program to run
88 :returns: command result output where output (stdout/stderr) is bytes
89 (encoding dependent on environment and command given)
90 :rtype: :py:class:`subprocess.CompletedProcess`
91 :raises: :py:class:`OSError` if command failed and cannot be ignored
94 status, stdout = vm.session.cmd_status_output(cmd, timeout=timeout)
95 stdout = stdout.encode()
100 if not ignore_errors:
101 raise subprocess.CalledProcessError(status, cmd, stderr=stderr)
102 return subprocess.CompletedProcess(cmd, status,
103 stdout=stdout, stderr=stderr)
105 return subprocess.run(cmd, check=not ignore_errors, shell=True,
109 def verify_running(process='arnied', timeout=60, vm=None):
111 Verify if a given process is running via 'pgrep'.
113 :param str process: process to verify if running
114 :param int timeout: run verification timeout
115 :param vm: vm to run on if running on a guest instead of the host
116 :type vm: :py:class:`virttest.qemu_vm.VM` or None
117 :raises: :py:class:`RuntimeError` if process is not running
122 platform_str = " on %s" % vm.name
123 for i in range(timeout):
124 log.info("Checking whether %s is running%s (%i\%i)",
125 process, platform_str, i, timeout)
126 result = run_cmd(cmd="pgrep -l -x %s" % process,
127 ignore_errors=True, vm=vm)
128 if result.returncode == 0:
132 raise RuntimeError("Process %s does not seem to be running" % process)
135 # Basic functionality
138 def accept_licence(vm=None):
140 Accept the Intra2net license.
142 :param vm: vm to run on if running on a guest instead of the host
143 :type vm: :py:class:`virttest.qemu_vm.VM` or None
145 This is mostly useful for simplified webpage access.
147 cmd = 'echo "LICENSE_ACCEPTED,0: \\"1\\"" | set_cnf'
148 result = run_cmd(cmd=cmd, ignore_errors=True, vm=vm)
150 wait_for_generate(vm=vm)
153 def go_online(provider_id, wait_online=True, timeout=60, vm=None):
155 Go online with the given provider id.
157 :param provider_id: provider to go online with
158 :type provider_id: int
159 :param wait_online: whether to wait until online
160 :type wait_online: bool
161 :param int timeout: Seconds to wait in :py:func:`wait_for_online`
162 :param vm: vm to run on if running on a guest instead of the host
163 :type vm: :py:class:`virttest.qemu_vm.VM` or None
165 .. seealso:: :py:func:`go_offline`, :py:func:`wait_for_online`
167 log.info("Switching to online mode with provider %d", provider_id)
169 get_cnf_res = run_cmd(cmd='get_cnf PROVIDER %d' % provider_id, vm=vm)
170 if b'PROVIDER,' not in get_cnf_res.stdout:
171 log.warning('There is no PROVIDER %d on the vm. Skipping go_online.',
175 cmd = 'tell-connd --online P%i' % provider_id
176 result = run_cmd(cmd=cmd, vm=vm)
180 wait_for_online(provider_id, timeout=timeout, vm=vm)
183 def go_offline(wait_offline=True, vm=None):
187 :param wait_offline: whether to wait until offline
188 :type wait_offline: bool
189 :param vm: vm to run on if running on a guest instead of the host
190 :type vm: :py:class:`virttest.qemu_vm.VM` or None
192 .. seealso:: :py:func:`go_online`, :py:func:`wait_for_offline`
194 cmd = 'tell-connd --offline'
195 result = run_cmd(cmd=cmd, vm=vm)
199 if wait_offline is True:
200 wait_for_offline(vm=vm)
202 wait_for_offline(wait_offline, vm=vm)
205 def wait_for_offline(timeout=60, vm=None):
207 Wait for arnied to signal we are offline.
209 :param int timeout: maximum timeout for waiting
210 :param vm: vm to run on if running on a guest instead of the host
211 :type vm: :py:class:`virttest.qemu_vm.VM` or None
213 _wait_for_online_status('offline', None, timeout, vm)
216 def wait_for_online(provider_id, timeout=60, vm=None):
218 Wait for arnied to signal we are online.
220 :param provider_id: provider to go online with
221 :type provider_id: int
222 :param int timeout: maximum timeout for waiting
223 :param vm: vm to run on if running on a guest instead of the host
224 :type vm: :py:class:`virttest.qemu_vm.VM` or None
226 _wait_for_online_status('online', provider_id, timeout, vm)
229 def _wait_for_online_status(status, provider_id, timeout, vm):
230 # Don't use tell-connd --status here since the actual
231 # ONLINE signal to arnied is transmitted
232 # asynchronously via arnieclient_muxer.
234 if status == 'online':
235 expected_output = 'DEFAULT: 2'
236 set_status_func = lambda: go_online(provider_id, False, vm)
237 elif status == 'offline':
238 expected_output = 'DEFAULT: 0'
239 set_status_func = lambda: go_offline(False, vm)
241 raise ValueError('expect status "online" or "offline", not "{0}"!'
244 log.info("Waiting for arnied to be {0} within {1} seconds"
245 .format(status, timeout))
247 for i in range(timeout):
248 # arnied might invalidate the connd "connection barrier"
249 # after generate was running and switch to OFFLINE (race condition).
250 # -> tell arnied every ten seconds to go online again
251 if i % 10 == 0 and i != 0:
254 cmd = '/usr/intranator/bin/get_var ONLINE'
255 result = run_cmd(cmd=cmd, ignore_errors=True, vm=vm)
258 if expected_output in result.stdout.decode():
259 log.info("arnied is {0}. Continuing.".format(status))
264 raise RuntimeError("We didn't manage to go {0} within {1} seconds\n"
265 .format(status, timeout))
268 def disable_virscan(vm=None):
270 Disable virscan that could block GENERATE and thus all configurations.
272 :param vm: vm to run on if running on a guest instead of the host
273 :type vm: :py:class:`virttest.qemu_vm.VM` or None
275 log.info("Disabling virus database update")
276 unset_cnf("VIRSCAN_UPDATE_CRON", vm=vm)
278 cmd = "echo 'VIRSCAN_UPDATE_DNS_PUSH,0:\"0\"' |set_cnf"
279 result = run_cmd(cmd=cmd, vm=vm)
282 # TODO: this intervention should be solved in later arnied_helper tool
283 cmd = "rm -f /var/intranator/schedule/UPDATE_VIRSCAN_NODIAL*"
284 result = run_cmd(cmd=cmd, vm=vm)
286 log.info("Virus database update disabled")
289 def email_transfer(vm=None):
291 Transfer all the emails using the guest tool arnied_helper.
293 :param vm: vm to run on if running on a guest instead of the host
294 :type vm: :py:class:`virttest.qemu_vm.VM` or None
296 cmd = f"{BIN_ARNIED_HELPER} --transfer-mail"
297 result = run_cmd(cmd=cmd, vm=vm)
301 def wait_for_email_transfer(timeout=300, vm=None):
303 Wait until the mail queue is empty and all emails are sent.
305 :param int timeout: email transfer timeout
306 :param vm: vm to run on if running on a guest instead of the host
307 :type vm: :py:class:`virttest.qemu_vm.VM` or None
309 for i in range(timeout):
311 # Retrigger mail queue in case something is deferred
312 # by an amavisd-new reconfiguration
313 run_cmd(cmd='postqueue -f', vm=vm)
314 log.info('Waiting for SMTP queue to get empty (%i/%i s)',
316 if not run_cmd(cmd='postqueue -j', vm=vm).stdout:
317 log.debug('SMTP queue is empty')
320 log.warning('Timeout reached but SMTP queue still not empty after {} s'
324 def schedule(program, exec_time=0, optional_args="", vm=None):
326 Schedule a program to be executed at a given unix time stamp.
328 :param str program: program whose execution is scheduled
329 :param int exec_time: scheduled time of program's execution
330 :param str optional_args: optional command line arguments
331 :param vm: vm to run on if running on a guest instead of the host
332 :type vm: :py:class:`virttest.qemu_vm.VM` or None
334 log.info("Scheduling %s to be executed at %i", program, exec_time)
335 schedule_dir = "/var/intranator/schedule"
336 # clean previous schedules of the same program
337 files = vm.session.cmd("ls " + schedule_dir).split() if vm else os.listdir(schedule_dir)
338 for file_name in files:
339 if file_name.startswith(program.upper()):
340 log.debug("Removing previous scheduled %s", file_name)
342 vm.session.cmd("rm -f " + os.path.join(schedule_dir, file_name))
344 os.unlink(os.path.join(schedule_dir, file_name))
346 contents = "%i\n%s\n" % (exec_time, optional_args)
348 tmp_file = tempfile.NamedTemporaryFile(mode="w+",
349 prefix=program.upper() + "_",
352 log.debug("Created temporary file %s", tmp_file.name)
353 tmp_file.write(contents)
355 moved_tmp_file = os.path.join(schedule_dir, os.path.basename(tmp_file.name))
358 vm.copy_files_to(tmp_file.name, moved_tmp_file)
359 os.remove(tmp_file.name)
361 shutil.move(tmp_file.name, moved_tmp_file)
363 log.debug("Moved temporary file to %s", moved_tmp_file)
366 def wait_for_run(program, timeout=300, retries=10, vm=None):
368 Wait for a program using the guest arnied_helper tool.
370 :param str program: scheduled or running program to wait for
371 :param int timeout: program run timeout
372 :param int retries: number of tries to verify that the program is scheduled or running
373 :param vm: vm to run on if running on a guest instead of the host
374 :type vm: :py:class:`virttest.qemu_vm.VM` or None
376 log.info("Waiting for program %s to finish with timeout %i",
378 for i in range(retries):
379 cmd = f"{BIN_ARNIED_HELPER} --is-scheduled-or-running " \
381 check_scheduled = run_cmd(cmd=cmd, ignore_errors=True, vm=vm)
382 if check_scheduled.returncode == 0:
386 log.warning("The program %s was not scheduled and is not running", program)
388 cmd = f"{BIN_ARNIED_HELPER} --wait-for-program-end " \
389 f"{program.upper()} --wait-for-program-timeout {timeout}"
390 # add one second to make sure arnied_helper is finished when we expire
391 result = run_cmd(cmd=cmd, vm=vm, timeout=timeout+1)
392 log.debug(result.stdout)
395 def wait_for_arnied(timeout=60, vm=None):
397 Wait for arnied socket to be ready.
399 :param int timeout: maximum number of seconds to wait
400 :param vm: vm to run on if running on a guest instead of the host
401 :type vm: :py:class:`virttest.qemu_vm.VM` or None
403 cmd = f"{BIN_ARNIED_HELPER} --wait-for-arnied-socket " \
404 f"--wait-for-arnied-socket-timeout {timeout}"
405 # add one second to make sure arnied_helper is finished when we expire
406 result = run_cmd(cmd=cmd, vm=vm, timeout=timeout+1)
407 log.debug(result.stdout)
410 # Configuration functionality
412 def get_cnf(cnf_key, cnf_index=1, regex=".*", compact=False, timeout=30, vm=None):
414 Query arnied for a `cnf_key` and extract some information via regex.
416 :param str cnf_key: queried cnf key
417 :param int cnf_index: index of the cnf key
418 :param str regex: regex to apply on the queried cnf key data
419 :param bool compact: whether to retrieve compact version of the matched cnf keys
420 :param int timeout: arnied run verification timeout
421 :param vm: vm to run on if running on a guest instead of the host
422 :type vm: :py:class:`virttest.qemu_vm.VM` or None
423 :returns: extracted information via the regex
426 If `cnf_index` is set to -1, retrieve and perform regex matching on all instances.
428 wait_for_arnied(timeout=timeout, vm=vm)
431 platform_str = " from %s" % vm.name
432 log.info("Extracting arnied value %s for %s%s using pattern %s",
433 cnf_index, cnf_key, platform_str, regex)
434 cmd = "get_cnf%s %s%s" % (" -c " if compact else "", cnf_key,
435 " %s" % cnf_index if cnf_index != -1 else "")
436 # get_cnf creates latin1-encoded output, transfer from VM removes non-ascii
437 output = run_cmd(cmd=cmd, vm=vm).stdout.decode('latin1')
438 return re.search(regex, output, flags=re.DOTALL)
441 def get_cnf_id(cnf_key, value, timeout=30, vm=None):
443 Get the id of a configuration of type `cnf_key` and name `value`.
445 :param str cnf_key: queried cnf key
446 :param str value: cnf value of the cnf key
447 :param int timeout: arnied run verification timeout
448 :param vm: vm to run on if running on a guest instead of the host
449 :type vm: :py:class:`virttest.qemu_vm.VM` or None
450 :returns: the cnf id or -1 if no such cnf variable
453 wait_for_arnied(timeout=timeout, vm=vm)
454 regex = "%s,(\d+): \"%s\"" % (cnf_key, value)
455 cnf_id = get_cnf(cnf_key, cnf_index=-1, regex=regex, compact=True, vm=vm)
459 cnf_id = int(cnf_id.group(1))
460 log.info("Retrieved id \"%s\" for %s is %i", value, cnf_key, cnf_id)
464 def wait_for_generate(timeout=300, vm=None):
466 Wait for the 'generate' program to complete.
468 Arguments are similar to the ones from :py:method:`wait_for_run`.
470 wait_for_run('generate', timeout=timeout, retries=1, vm=vm)
471 wait_for_run('generate_offline', timeout=timeout, retries=1, vm=vm)
474 def unset_cnf(varname="", instance="", timeout=30, vm=None):
476 Remove configuration from arnied.
478 :param str varname: "varname" field of the CNF_VAR to unset
479 :param int instance: "instance" of that variable to unset
480 :param int timeout: arnied run verification timeout
481 :param vm: vm to run on if running on a guest instead of the host
482 :type vm: :py:class:`virttest.qemu_vm.VM` or None
484 wait_for_arnied(timeout=timeout, vm=vm)
486 cmd = "get_cnf %s %s | set_cnf -x" % (varname, instance)
487 run_cmd(cmd=cmd, vm=vm)
489 wait_for_generate(vm=vm)
492 def set_cnf(config_files, kind="cnf", timeout=30, vm=None):
494 Perform static arnied configuration through a set of config files.
496 :param config_files: config files to use for the configuration
497 :type config_files: [str]
498 :param str kind: "json" or "cnf"
499 :param int timeout: arnied run verification timeout
500 :param vm: vm to run on if running on a guest instead of the host
501 :type vm: :py:class:`virttest.qemu_vm.VM` or None
502 :raises: :py:class:`ConfigError` if cannot apply file
504 The config files must be provided and are always expected to be found on
505 the host. If these are absolute paths, they will be kept as is or
506 otherwise will be searched for in `SRC_CONFIG_DIR`. If a vm is provided,
507 the config files will be copied there as temporary files before applying.
509 ..todo:: The static method must be deprecated after we drop and convert
510 lots of use cases for it to dynamic only.
512 log.info("Setting arnied configuration")
513 wait_for_arnied(timeout=timeout, vm=vm)
515 config_paths = prep_config_paths(config_files)
516 for config_path in config_paths:
517 with open(config_path, "rt", errors='replace') as config:
518 log.debug("Contents of applied %s:\n%s", config_path, config.read())
520 new_config_path = generate_config_path()
521 vm.copy_files_to(config_path, new_config_path)
522 config_path = new_config_path
523 argv = ["set_cnf", kind == "json" and "-j" or "", config_path]
525 result = run_cmd(" ".join(argv), ignore_errors=True, vm=vm)
526 logging.debug(result)
527 if result.returncode != 0:
528 raise ConfigError("Failed to apply config %s%s, set_cnf returned %d"
530 " on %s" % vm.name if vm is not None else "",
534 wait_for_generate(vm=vm)
535 except Exception as ex:
536 # handle cases of remote configuration that leads to connection meltdown
537 if vm is not None and isinstance(ex, sys.modules["aexpect"].ShellProcessTerminatedError):
538 log.info("Resetting connection to %s", vm.name)
539 vm.session = vm.wait_for_login(timeout=10)
540 log.debug("Connection reset via remote error: %s", ex)
545 def set_cnf_semidynamic(config_files, params_dict, regex_dict=None,
546 kind="cnf", timeout=30, vm=None):
548 Perform semi-dynamic arnied configuration from an updated version of the
551 :param config_files: config files to use for the configuration
552 :type config_files: [str]
553 :param params_dict: parameters to override the defaults in the config files
554 :type params_dict: {str, str}
555 :param regex_dict: regular expressions to use for matching the overriden parameters
556 :type regex_dict: {str, str} or None
557 :param str kind: "json" or "cnf"
558 :param int timeout: arnied run verification timeout
559 :param vm: vm to run on if running on a guest instead of the host
560 :type vm: :py:class:`virttest.qemu_vm.VM` or None
562 The config files must be provided and are always expected to be found on
563 the host. If these are absolute paths, they will be kept as is or
564 otherwise will be searched for in `SRC_CONFIG_DIR`. If a vm is provided,
565 the config files will be copied there as temporary files before applying.
567 ..todo:: The semi-dynamic method must be deprecated after we drop and convert
568 lots of use cases for it to dynamic only.
570 log.info("Performing semi-dynamic arnied configuration")
572 config_paths = prep_cnf(config_files, params_dict, regex_dict)
573 set_cnf(config_paths, kind=kind, timeout=timeout, vm=vm)
575 log.info("Semi-dynamic arnied configuration successful!")
578 def set_cnf_pipe(cnf, timeout=30, block=False):
580 Set local configuration by talking to arnied via ``set_cnf``.
582 :param cnf: one key with the same value as *kind* and a list of cnfvars as value
583 :type cnf: {str, str}
584 :param int timeout: arnied run verification timeout
585 :param bool block: whether to wait for generate to complete the
587 :returns: whether ``set_cnf`` succeeded or not
590 This is obviously not generic but supposed to be run on the guest.
592 log.info("Setting arnied configuration through local pipe")
593 wait_for_arnied(timeout=timeout)
595 st, out, exit = sysmisc.run_cmd_with_pipe([BIN_SET_CNF, "-j"], inp=str(cnf))
598 log.error("Error applying configuration; status=%r" % exit)
599 log.error("and stderr:\n%s" % out)
601 log.debug("Configuration successfully passed to set_cnf, "
602 "read %d B from pipe" % len(out))
605 log.debug("Waiting for config job to complete")
608 log.debug("Exiting sucessfully")
612 def prep_config_paths(config_files, config_dir=None):
614 Prepare absolute paths for all configs at an expected location.
616 :param config_files: config files to use for the configuration
617 :type config_files: [str]
618 :param config_dir: config directory to prepend to the filepaths
619 :type config_dir: str or None
620 :returns: list of the full config paths
623 if config_dir is None:
624 config_dir = SRC_CONFIG_DIR
626 for config_file in config_files:
627 if os.path.isabs(config_file):
628 # Absolute path: The user requested a specific file
629 # f.e. needed for dynamic arnied config update
630 config_path = config_file
632 config_path = os.path.join(os.path.abspath(config_dir),
634 logging.debug("Using %s for original path %s", config_path, config_file)
635 config_paths.append(config_path)
639 def prep_cnf_value(config_file, value,
640 regex=None, template_key=None, ignore_fail=False):
642 Replace value in a provided arnied config file.
644 :param str config_file: file to use for the replacement
645 :param str value: value to replace the first matched group with
646 :param regex: regular expression to use when replacing a cnf value
647 :type regex: str or None
648 :param template_key: key of a quick template to use for the regex
649 :type template_key: str or None
650 :param bool ignore_fail: whether to ignore regex mismatching
651 :raises: :py:class:`ValueError` if (also default) `regex` doesn't have a match
653 In order to ensure better matching capabilities you are supposed to
654 provide a regex pattern with at least one subgroup to match your value.
655 What this means is that the value you like to replace is not directly
656 searched into the config text but matched within a larger regex in
657 in order to avoid any mismatch.
660 provider.cnf, 'PROVIDER_LOCALIP,0: "(\d+)"', 127.0.0.1
662 if template_key is None:
663 pattern = regex.encode()
665 samples = {"provider": 'PROVIDER_LOCALIP,\d+: "(\d+\.\d+\.\d+\.\d+)"',
666 "global_destination_addr": 'SPAMFILTER_GLOBAL_DESTINATION_ADDR,0: "bounce_target@(.*)"'}
667 pattern = samples[template_key].encode()
669 with open(config_file, "rb") as file_handle:
670 text = file_handle.read()
671 match_line = re.search(pattern, text)
673 if match_line is None and not ignore_fail:
674 raise ValueError("Pattern %s not found in %s" % (pattern, config_file))
675 elif match_line is not None:
676 old_line = match_line.group(0)
677 text = text[:match_line.start(1)] + value.encode() + text[match_line.end(1):]
678 line = re.search(pattern, text).group(0)
679 log.debug("Updating %s to %s in %s", old_line, line, config_file)
680 with open(config_file, "wb") as file_handle:
681 file_handle.write(text)
684 def prep_cnf(config_files, params_dict, regex_dict=None):
686 Update all config files with the default overriding parameters,
687 i.e. override the values hard-coded in those config files.
689 :param config_files: config files to use for the configuration
690 :type config_files: [str]
691 :param params_dict: parameters to override the defaults in the config files
692 :type params_dict: {str, str}
693 :param regex_dict: regular expressions to use for matching the overriden parameters
694 :type regex_dict: {str, str} or None
695 :returns: list of prepared (modified) config paths
698 log.info("Preparing %s template config files", len(config_files))
700 src_config_paths = prep_config_paths(config_files)
701 new_config_paths = []
702 for config_path in src_config_paths:
703 new_config_path = generate_config_path(dumped=True)
704 shutil.copy(config_path, new_config_path)
705 new_config_paths.append(new_config_path)
707 for config_path in new_config_paths:
708 for param_key in params_dict.keys():
709 if regex_dict is None:
710 regex_val = "\s+%s,\d+: \"(.*)\"" % param_key.upper()
711 elif param_key in regex_dict.keys():
712 regex_val = regex_dict[param_key] % param_key.upper()
713 elif re.match("\w*_\d+$", param_key):
714 final_parameter, parent_id = \
715 re.match("(\w*)_(\d+)$", param_key).group(1, 2)
716 regex_val = "\(%s\) %s,\d+: \"(.*)\"" \
717 % (parent_id, final_parameter.upper())
718 log.debug("Requested regex for %s is '%s'",
719 param_key, regex_val)
721 regex_val = "\s+%s,\d+: \"(.*)\"" % param_key.upper()
722 prep_cnf_value(config_path, params_dict[param_key],
723 regex=regex_val, ignore_fail=True)
724 log.info("Prepared template config file %s", config_path)
726 return new_config_paths
729 def generate_config_path(dumped=False):
731 Generate path for a temporary config name.
733 :param bool dumped: whether the file should be in the dump
734 directory or in temporary directory
735 :returns: generated config file path
738 dir = os.path.abspath(DUMP_CONFIG_DIR) if dumped else None
739 fd, filename = tempfile.mkstemp(suffix=".cnf", dir=dir)