/* * virHookInitialize: * * Initialize synchronous hooks support. * Check is there is an installed hook for all the drivers * * Returns the number of hooks found or -1 in case of failure */ int virHookInitialize(void) { int i, res, ret = 0; virHooksFound = 0; for (i = 0;i < VIR_HOOK_DRIVER_LAST;i++) { res = virHookCheck(i, virHookDriverTypeToString(i)); if (res < 0) return -1; if (res == 1) { virHooksFound |= (1 << i); ret++; } } return ret; }
/** * virHookCall: * @driver: the driver number (from virHookDriver enum) * @id: an id for the object '-' if non available for example on daemon hooks * @op: the operation on the id e.g. VIR_HOOK_QEMU_OP_START * @sub_op: a sub_operation, currently unused * @extra: optional string information * @input: extra input given to the script on stdin * @output: optional address of variable to store malloced result buffer * * Implement a hook call, where the external script for the driver is * called with the given information. This is a synchronous call, we wait for * execution completion. If @output is non-NULL, *output is guaranteed to be * allocated after successful virHookCall, and is best-effort allocated after * failed virHookCall; the caller is responsible for freeing *output. * * Returns: 0 if the execution succeeded, 1 if the script was not found or * invalid parameters, and -1 if script returned an error */ int virHookCall(int driver, const char *id, int op, int sub_op, const char *extra, const char *input, char **output) { int ret; int exitstatus; char *path; virCommandPtr cmd; const char *drvstr; const char *opstr; const char *subopstr; if (output) *output = NULL; if ((driver < VIR_HOOK_DRIVER_DAEMON) || (driver >= VIR_HOOK_DRIVER_LAST)) return 1; /* * We cache the availability of the script to minimize impact at * runtime if no script is defined, this is being reset on SIGHUP */ if ((virHooksFound == -1) || ((driver == VIR_HOOK_DRIVER_DAEMON) && (op == VIR_HOOK_DAEMON_OP_RELOAD || op == VIR_HOOK_DAEMON_OP_SHUTDOWN))) virHookInitialize(); if ((virHooksFound & (1 << driver)) == 0) return 1; drvstr = virHookDriverTypeToString(driver); opstr = NULL; switch (driver) { case VIR_HOOK_DRIVER_DAEMON: opstr = virHookDaemonOpTypeToString(op); break; case VIR_HOOK_DRIVER_QEMU: opstr = virHookQemuOpTypeToString(op); break; case VIR_HOOK_DRIVER_LXC: opstr = virHookLxcOpTypeToString(op); break; } if (opstr == NULL) { virHookReportError(VIR_ERR_INTERNAL_ERROR, _("Hook for %s, failed to find operation #%d"), drvstr, op); return 1; } subopstr = virHookSubopTypeToString(sub_op); if (subopstr == NULL) subopstr = "-"; if (extra == NULL) extra = "-"; ret = virBuildPath(&path, LIBVIRT_HOOK_DIR, drvstr); if ((ret < 0) || (path == NULL)) { virHookReportError(VIR_ERR_INTERNAL_ERROR, _("Failed to build path for %s hook"), drvstr); return -1; } cmd = virCommandNewArgList(path, id, opstr, subopstr, extra, NULL); virCommandAddEnvPassCommon(cmd); if (input) virCommandSetInputBuffer(cmd, input); if (output) virCommandSetOutputBuffer(cmd, output); ret = virCommandRun(cmd, &exitstatus); if (ret == 0 && exitstatus != 0) { virHookReportError(VIR_ERR_HOOK_SCRIPT_FAILED, _("Hook script %s %s failed with error code %d"), path, drvstr, exitstatus); ret = -1; } virCommandFree(cmd); VIR_FREE(path); return ret; }
/** * virHookCall: * @driver: the driver number (from virHookDriver enum) * @id: an id for the object '-' if non available for example on daemon hooks * @op: the operation on the id e.g. VIR_HOOK_QEMU_OP_START * @sub_op: a sub_operation, currently unused * @extra: optional string information * @input: extra input given to the script on stdin * @output: optional address of variable to store malloced result buffer * * Implement a hook call, where the external script for the driver is * called with the given information. This is a synchronous call, we wait for * execution completion. If @output is non-NULL, *output is guaranteed to be * allocated after successful virHookCall, and is best-effort allocated after * failed virHookCall; the caller is responsible for freeing *output. * * Returns: 0 if the execution succeeded, 1 if the script was not found or * invalid parameters, and -1 if script returned an error */ int virHookCall(int driver, const char *id, int op, int sub_op, const char *extra, const char *input, char **output) { int ret; char *path; virCommandPtr cmd; const char *drvstr; const char *opstr; const char *subopstr; if (output) *output = NULL; if ((driver < VIR_HOOK_DRIVER_DAEMON) || (driver >= VIR_HOOK_DRIVER_LAST)) return 1; /* * We cache the availability of the script to minimize impact at * runtime if no script is defined, this is being reset on SIGHUP */ if ((virHooksFound == -1) || ((driver == VIR_HOOK_DRIVER_DAEMON) && (op == VIR_HOOK_DAEMON_OP_RELOAD || op == VIR_HOOK_DAEMON_OP_SHUTDOWN))) virHookInitialize(); if ((virHooksFound & (1 << driver)) == 0) return 1; drvstr = virHookDriverTypeToString(driver); opstr = NULL; switch (driver) { case VIR_HOOK_DRIVER_DAEMON: opstr = virHookDaemonOpTypeToString(op); break; case VIR_HOOK_DRIVER_QEMU: opstr = virHookQemuOpTypeToString(op); break; case VIR_HOOK_DRIVER_LXC: opstr = virHookLxcOpTypeToString(op); break; case VIR_HOOK_DRIVER_NETWORK: opstr = virHookNetworkOpTypeToString(op); } if (opstr == NULL) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Hook for %s, failed to find operation #%d"), drvstr, op); return 1; } subopstr = virHookSubopTypeToString(sub_op); if (subopstr == NULL) subopstr = "-"; if (extra == NULL) extra = "-"; if (virBuildPath(&path, LIBVIRT_HOOK_DIR, drvstr) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Failed to build path for %s hook"), drvstr); return -1; } VIR_DEBUG("Calling hook opstr=%s subopstr=%s extra=%s", opstr, subopstr, extra); cmd = virCommandNewArgList(path, id, opstr, subopstr, extra, NULL); virCommandAddEnvPassCommon(cmd); if (input) virCommandSetInputBuffer(cmd, input); if (output) virCommandSetOutputBuffer(cmd, output); ret = virCommandRun(cmd, NULL); if (ret < 0) { /* Convert INTERNAL_ERROR into known error. */ virErrorPtr err = virGetLastError(); virReportError(VIR_ERR_HOOK_SCRIPT_FAILED, "%s", err ? err->message : _("unknown error")); } virCommandFree(cmd); VIR_FREE(path); return ret; }