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
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)
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)