# Path: crmsh/utils.py
# def stdout2list(cmd, stderr_on=True, shell=True):
#     '''
#     Run a cmd, fetch output, return it as a list of lines.
#     stderr_on controls whether to show output which comes on stderr.
#     '''
#     rc, s = get_stdout(add_sudo(cmd), stderr_on=stderr_on, shell=shell)
#     if not s:
#         return rc, []
#     return rc, s.split('\n')
# 
# def is_program(prog):
#     """Is this program available?"""
#     def isexec(filename):
#         return os.path.isfile(filename) and os.access(filename, os.X_OK)
#     for p in os.getenv("PATH").split(os.pathsep):
#         f = os.path.join(p, prog)
#         if isexec(f):
#             return f
#     return None
# 
# def is_process(s):
#     """
#     Returns true if argument is the name of a running process.
# 
#     s: process name
#     returns Boolean
#     """
#     from os.path import join, basename
#     # find pids of running processes
#     pids = [pid for pid in os.listdir('/proc') if pid.isdigit()]
#     for pid in pids:
#         try:
#             cmdline = open(join('/proc', pid, 'cmdline'), 'rb').read()
#             procname = basename(to_ascii(cmdline).replace('\x00', ' ').split(' ')[0])
#             if procname == s:
#                 return True
#         except EnvironmentError:
#             # a process may have died since we got the list of pids
#             pass
#     return False
# 
# def to_ascii(input_str):
#     """Convert the bytes string to a ASCII string
#     Usefull to remove accent (diacritics)"""
#     if input_str is None:
#         return input_str
#     if isinstance(input_str, str):
#         return input_str
#     try:
#         return str(input_str, 'utf-8')
#     except UnicodeDecodeError:
#         if config.core.debug or options.regression_tests:
#             import traceback
#             traceback.print_exc()
#         return input_str.decode('utf-8', errors='ignore')
# 
# Path: crmsh/utils.py
# def os_types_list(path):
#     l = []
#     for f in glob.glob(path):
#         if os.access(f, os.X_OK) and os.path.isfile(f):
#             a = f.split("/")
#             l.append(a[-1])
#     return l
# 
# def get_stdout(cmd, input_s=None, stderr_on=True, shell=True, raw=False):
#     '''
#     Run a cmd, return stdout output.
#     Optional input string "input_s".
#     stderr_on controls whether to show output which comes on stderr.
#     '''
#     if stderr_on:
#         stderr = None
#     else:
#         stderr = subprocess.PIPE
#     if options.regression_tests:
#         print(".EXT", cmd)
#     proc = subprocess.Popen(cmd,
#                             shell=shell,
#                             stdin=subprocess.PIPE,
#                             stdout=subprocess.PIPE,
#                             stderr=stderr)
#     stdout_data, stderr_data = proc.communicate(input_s)
#     if raw:
#         return proc.returncode, stdout_data
#     return proc.returncode, to_ascii(stdout_data).strip()
# 
# Path: crmsh/utils.py
# def crm_msec(t):
#     '''
#     See lib/common/utils.c:crm_get_msec().
#     '''
#     convtab = {
#         'ms': (1, 1),
#         'msec': (1, 1),
#         'us': (1, 1000),
#         'usec': (1, 1000),
#         '': (1000, 1),
#         's': (1000, 1),
#         'sec': (1000, 1),
#         'm': (60*1000, 1),
#         'min': (60*1000, 1),
#         'h': (60*60*1000, 1),
#         'hr': (60*60*1000, 1),
#     }
#     if not t:
#         return -1
#     r = re.match(r"\s*(\d+)\s*([a-zA-Z]+)?", t)
#     if not r:
#         return -1
#     if not r.group(2):
#         q = ''
#     else:
#         q = r.group(2).lower()
#     try:
#         mult, div = convtab[q]
#     except KeyError:
#         return -1
#     return (int(r.group(1))*mult) // div
# 
# def crm_time_cmp(a, b):
#     return crm_msec(a) - crm_msec(b)


import os
import subprocess
import copy
import re
import glob
from lxml import etree
from . import cache
from . import constants
from . import config
from . import options
from . import userdir
from . import utils
from .utils import stdout2list, is_program, is_process, to_ascii
from .utils import os_types_list, get_stdout
from .utils import crm_msec, crm_time_cmp
from . import log
    from distutils import version
        def sanity_check_op_timeout(op, op_dict):
            """
            Helper method used by sanity_check_op, to check operation's timeout
            """
            rc = 0
            role = None
            depth = None
            if op == "monitor":
                for monitor_item in op_dict[op]:
                    role = monitor_item['role'] if 'role' in monitor_item else None
                    depth = monitor_item['depth'] if 'depth' in monitor_item else None
                    adv_timeout = self.get_op_attr_value(op, "timeout", role=role, depth=depth)
                    rc |= timeout_check(op, monitor_item, adv_timeout)
            else:
                adv_timeout = self.get_op_attr_value(op, "timeout")
                rc |= timeout_check(op, op_dict[op], adv_timeout)
            return rc

        def sanity_check_op_interval(op, op_dict):
            """
            Helper method used by sanity_check_op, to check operation's interval
            """
            rc = 0
            prev_intervals = []
            if op == "monitor":
                for monitor_item in op_dict[op]:
                    role = monitor_item['role'] if 'role' in monitor_item else None
                    depth = monitor_item['depth'] if 'depth' in monitor_item else None
                    # make sure interval in multi monitor operations is unique and non-zero
                    adv_interval = self.get_op_attr_value(op, "interval", role=role, depth=depth)

# Path: crmsh/utils.py
# def stdout2list(cmd, stderr_on=True, shell=True):
#     '''
#     Run a cmd, fetch output, return it as a list of lines.
#     stderr_on controls whether to show output which comes on stderr.
#     '''
#     rc, s = get_stdout(add_sudo(cmd), stderr_on=stderr_on, shell=shell)
#     if not s:
#         return rc, []
#     return rc, s.split('\n')
# 
# def is_program(prog):
#     """Is this program available?"""
#     def isexec(filename):
#         return os.path.isfile(filename) and os.access(filename, os.X_OK)
#     for p in os.getenv("PATH").split(os.pathsep):
#         f = os.path.join(p, prog)
#         if isexec(f):
#             return f
#     return None
# 
# def is_process(s):
#     """
#     Returns true if argument is the name of a running process.
# 
#     s: process name
#     returns Boolean
#     """
#     from os.path import join, basename
#     # find pids of running processes
#     pids = [pid for pid in os.listdir('/proc') if pid.isdigit()]
#     for pid in pids:
#         try:
#             cmdline = open(join('/proc', pid, 'cmdline'), 'rb').read()
#             procname = basename(to_ascii(cmdline).replace('\x00', ' ').split(' ')[0])
#             if procname == s:
#                 return True
#         except EnvironmentError:
#             # a process may have died since we got the list of pids
#             pass
#     return False
# 
# def to_ascii(input_str):
#     """Convert the bytes string to a ASCII string
#     Usefull to remove accent (diacritics)"""
#     if input_str is None:
#         return input_str
#     if isinstance(input_str, str):
#         return input_str
#     try:
#         return str(input_str, 'utf-8')
#     except UnicodeDecodeError:
#         if config.core.debug or options.regression_tests:
#             import traceback
#             traceback.print_exc()
#         return input_str.decode('utf-8', errors='ignore')
# 
# Path: crmsh/utils.py
# def os_types_list(path):
#     l = []
#     for f in glob.glob(path):
#         if os.access(f, os.X_OK) and os.path.isfile(f):
#             a = f.split("/")
#             l.append(a[-1])
#     return l
# 
# def get_stdout(cmd, input_s=None, stderr_on=True, shell=True, raw=False):
#     '''
#     Run a cmd, return stdout output.
#     Optional input string "input_s".
#     stderr_on controls whether to show output which comes on stderr.
#     '''
#     if stderr_on:
#         stderr = None
#     else:
#         stderr = subprocess.PIPE
#     if options.regression_tests:
#         print(".EXT", cmd)
#     proc = subprocess.Popen(cmd,
#                             shell=shell,
#                             stdin=subprocess.PIPE,
#                             stdout=subprocess.PIPE,
#                             stderr=stderr)
#     stdout_data, stderr_data = proc.communicate(input_s)
#     if raw:
#         return proc.returncode, stdout_data
#     return proc.returncode, to_ascii(stdout_data).strip()
# 
# Path: crmsh/utils.py
# def crm_msec(t):
#     '''
#     See lib/common/utils.c:crm_get_msec().
#     '''
#     convtab = {
#         'ms': (1, 1),
#         'msec': (1, 1),
#         'us': (1, 1000),
#         'usec': (1, 1000),
#         '': (1000, 1),
#         's': (1000, 1),
#         'sec': (1000, 1),
#         'm': (60*1000, 1),
#         'min': (60*1000, 1),
#         'h': (60*60*1000, 1),
#         'hr': (60*60*1000, 1),
#     }
#     if not t:
#         return -1
#     r = re.match(r"\s*(\d+)\s*([a-zA-Z]+)?", t)
#     if not r:
#         return -1
#     if not r.group(2):
#         q = ''
#     else:
#         q = r.group(2).lower()
#     try:
#         mult, div = convtab[q]
#     except KeyError:
#         return -1
#     return (int(r.group(1))*mult) // div
# 
# def crm_time_cmp(a, b):
#     return crm_msec(a) - crm_msec(b)


# Path: crmsh/ra.py
import os
import subprocess
import copy
import re
import glob
from lxml import etree
from . import cache
from . import constants
from . import config
from . import options
from . import userdir
from . import utils
from .utils import stdout2list, is_program, is_process, to_ascii
from .utils import os_types_list, get_stdout
from .utils import crm_msec, crm_time_cmp
from . import log
    from distutils import version

        def sanity_check_op_timeout(op, op_dict):
            """
            Helper method used by sanity_check_op, to check operation's timeout
            """
            rc = 0
            role = None
            depth = None
            if op == "monitor":
                for monitor_item in op_dict[op]:
                    role = monitor_item['role'] if 'role' in monitor_item else None
                    depth = monitor_item['depth'] if 'depth' in monitor_item else None
                    adv_timeout = self.get_op_attr_value(op, "timeout", role=role, depth=depth)
                    rc |= timeout_check(op, monitor_item, adv_timeout)
            else:
                adv_timeout = self.get_op_attr_value(op, "timeout")
                rc |= timeout_check(op, op_dict[op], adv_timeout)
            return rc

        def sanity_check_op_interval(op, op_dict):
            """
            Helper method used by sanity_check_op, to check operation's interval
            """
            rc = 0
            prev_intervals = []
            if op == "monitor":
                for monitor_item in op_dict[op]:
                    role = monitor_item['role'] if 'role' in monitor_item else None
                    depth = monitor_item['depth'] if 'depth' in monitor_item else None
                    # make sure interval in multi monitor operations is unique and non-zero
                    adv_interval = self.get_op_attr_value(op, "interval", role=role, depth=depth)

                    actual_interval_msec = crm_msec(monitor_item["interval"])