示例#1
0
文件: hooks.py 项目: k0ste/vdsm
def before_vm_start(domxml, vmconf={}, final_callback=None):
    errors = []
    final_xml = _runHooksDir(domxml, 'before_vm_start', vmconf=vmconf,
                             raiseError=False, errors=errors)
    if final_callback is not None:
        final_callback(final_xml)
    if errors:
        raise exception.HookError(errors[-1])
    return final_xml
示例#2
0
def _runHooksDir(data, dir, vmconf={}, raiseError=True, params={},
                 hookType=_DOMXML_HOOK):

    scripts = _scriptsPerDir(dir)
    scripts.sort()

    if not scripts:
        return data

    data_fd, data_filename = tempfile.mkstemp()
    try:
        if hookType == _DOMXML_HOOK:
            os.write(data_fd, data or '')
        elif hookType == _JSON_HOOK:
            os.write(data_fd, json.dumps(data))
        os.close(data_fd)

        scriptenv = os.environ.copy()

        # Update the environment using params and custom configuration
        env_update = [params.iteritems(),
                      vmconf.get('custom', {}).iteritems()]

        # Encode custom properties to UTF-8 and save them to scriptenv
        # Pass str objects (byte-strings) without any conversion
        for k, v in itertools.chain(*env_update):
            try:
                if isinstance(v, unicode):
                    scriptenv[k] = v.encode('utf-8')
                else:
                    scriptenv[k] = v
            except UnicodeDecodeError:
                pass

        if vmconf.get('vmId'):
            scriptenv['vmId'] = vmconf.get('vmId')
        ppath = scriptenv.get('PYTHONPATH', '')
        hook = os.path.join(os.path.dirname(__file__), 'hook')
        scriptenv['PYTHONPATH'] = ':'.join(ppath.split(':') + [hook])
        if hookType == _DOMXML_HOOK:
            scriptenv['_hook_domxml'] = data_filename
        elif hookType == _JSON_HOOK:
            scriptenv['_hook_json'] = data_filename

        errorSeen = False
        for s in scripts:
            rc, out, err = commands.execCmd([s], raw=True,
                                            env=scriptenv)
            logging.info(err)
            if rc != 0:
                errorSeen = True

            if rc == 2:
                break
            elif rc > 2:
                logging.warn('hook returned unexpected return code %s', rc)

        if errorSeen and raiseError:
            raise exception.HookError(err)

        with open(data_filename) as f:
            final_data = f.read()
    finally:
        os.unlink(data_filename)
    if hookType == _DOMXML_HOOK:
        return final_data
    elif hookType == _JSON_HOOK:
        return json.loads(final_data)
示例#3
0
def _runHooksDir(data,
                 dir,
                 vmconf={},
                 raiseError=True,
                 errors=None,
                 params={},
                 hookType=_DOMXML_HOOK):
    if errors is None:
        errors = []

    scripts = _scriptsPerDir(dir)
    scripts.sort()

    if not scripts:
        return data

    data_fd, data_filename = tempfile.mkstemp()
    try:
        if hookType == _DOMXML_HOOK:
            os.write(data_fd, data.encode('utf-8') if data else b'')
        elif hookType == _JSON_HOOK:
            os.write(data_fd, json.dumps(data).encode('utf-8'))
        os.close(data_fd)

        scriptenv = os.environ.copy()

        # Update the environment using params and custom configuration
        env_update = [
            six.iteritems(params),
            six.iteritems(vmconf.get('custom', {}))
        ]

        # Encode custom properties to UTF-8 and save them to scriptenv
        # Pass str objects (byte-strings) without any conversion
        for k, v in itertools.chain(*env_update):
            try:
                if isinstance(v, six.text_type):
                    scriptenv[k] = v.encode('utf-8')
                else:
                    scriptenv[k] = v
            except UnicodeEncodeError:
                pass

        if vmconf.get('vmId'):
            scriptenv['vmId'] = vmconf.get('vmId')
        ppath = scriptenv.get('PYTHONPATH', '')
        hook = os.path.dirname(pkgutil.get_loader('vdsm.hook').get_filename())
        scriptenv['PYTHONPATH'] = ':'.join(ppath.split(':') + [hook])
        if hookType == _DOMXML_HOOK:
            scriptenv['_hook_domxml'] = data_filename
        elif hookType == _JSON_HOOK:
            scriptenv['_hook_json'] = data_filename

        for s in scripts:
            p = commands.start([s],
                               stdout=subprocess.PIPE,
                               stderr=subprocess.PIPE,
                               env=scriptenv)

            with commands.terminating(p):
                (out, err) = p.communicate()

            rc = p.returncode
            logging.info('%s: rc=%s err=%s', s, rc, err)
            if rc != 0:
                errors.append(err)

            if rc == 2:
                break
            elif rc > 2:
                logging.warning('hook returned unexpected return code %s', rc)

        if errors and raiseError:
            raise exception.HookError(err)

        with open(data_filename) as f:
            final_data = f.read()
    finally:
        os.unlink(data_filename)
    if hookType == _DOMXML_HOOK:
        return final_data
    elif hookType == _JSON_HOOK:
        return json.loads(final_data)