static int DeleteVirtNetwork(virConnectPtr vc, char **networks, Attributes a, Promise *pp) { virNetworkPtr network; int ret = true; if ((network = virNetworkLookupByName(vc, pp->promiser)) == NULL) { cfPS(cf_verbose, CF_NOP, "", pp, a, " -> Couldn't find a network called \"%s\" - promise assumed kept\n", pp->promiser); return true; } if (virNetworkDestroy(network) == 0) { cfPS(cf_inform, CF_CHG, "", pp, a, " -> Deleted network \"%s\" - promise repaired\n", pp->promiser); } else { cfPS(cf_error, CF_FAIL, "", pp, a, " !! Network deletion of \"%s\" failed\n", pp->promiser); ret = false; } virNetworkFree(network); return ret; }
bool MakeHardLink(EvalContext *ctx, const char *from, const char *to, Attributes attr, const Promise *pp, PromiseResult *result) { if (DONTDO) { Log(LOG_LEVEL_ERR, "Need to hard link files '%s' -> '%s'", from, to); return false; } else { if (link(to, from) == -1) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, attr, "Couldn't hard link '%s' to '%s'. (link: %s)", to, from, GetErrorStr()); *result = PromiseResultUpdate(*result, PROMISE_RESULT_FAIL); return false; } else { cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_CHANGE, pp, attr, "Hard linked files '%s' -> '%s'", from, to); *result = PromiseResultUpdate(*result, PROMISE_RESULT_CHANGE); return true; } } }
static int VerifyFreeSpace(char *file, Attributes a, Promise *pp) { struct stat statbuf; long kilobytes; #ifdef MINGW if (!a.volume.check_foreign) { CfOut(cf_verbose, "", "storage.volume.check_foreign is not supported on Windows (checking every mount)"); } #endif /* MINGW */ if (cfstat(file, &statbuf) == -1) { CfOut(cf_error, "stat", "Couldn't stat %s checking diskspace\n", file); return true; } #ifndef MINGW if (!a.volume.check_foreign) { if (IsForeignFileSystem(&statbuf, file)) { CfOut(cf_inform, "", "Filesystem %s is mounted from a foreign system, so skipping it", file); return true; } } #endif /* NOT MINGW */ kilobytes = a.volume.freespace; if (kilobytes < 0) { int free = (int) GetDiskUsage(file, cfpercent); kilobytes = -1 * kilobytes; if (free < (int) kilobytes) { cfPS(cf_error, CF_FAIL, "", pp, a, " !! Free disk space is under %ld%% for volume containing %s (%d%% free)\n", kilobytes, file, free); return false; } } else { off_t free = GetDiskUsage(file, cfabs); kilobytes = kilobytes / 1024; if (free < kilobytes) { cfPS(cf_error, CF_FAIL, "", pp, a, " !! Disk space under %ld kB for volume containing %s (%lld kB free)\n", kilobytes, file, (long long) free); return false; } } return true; }
static int DeleteVirt(virConnectPtr vc, char *uri, Attributes a, Promise *pp) { virDomainPtr dom; int ret = true; dom = virDomainLookupByName(vc, pp->promiser); if (dom) { if (virDomainDestroy(dom) == -1) { cfPS(cf_verbose, CF_FAIL, "", pp, a, " !! Failed to delete virtual domain \"%s\"\n", pp->promiser); ret = false; } else { cfPS(cf_verbose, CF_CHG, "", pp, a, " -> Deleted virtual domain \"%s\"\n", pp->promiser); } virDomainFree(dom); } else { cfPS(cf_verbose, CF_NOP, "", pp, a, " -> No such virtual domain called \"%s\" - promise kept\n", pp->promiser); } return ret; }
static PromiseResult DeleteVirt(EvalContext *ctx, virConnectPtr vc, Attributes a, const Promise *pp) { virDomainPtr dom; dom = virDomainLookupByName(vc, pp->promiser); PromiseResult result = PROMISE_RESULT_NOOP; if (dom) { if (virDomainDestroy(dom) == -1) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Failed to delete virtual domain '%s'", pp->promiser); result = PromiseResultUpdate(result, PROMISE_RESULT_FAIL); } else { cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_CHANGE, pp, a, "Deleted virtual domain '%s'", pp->promiser); result = PromiseResultUpdate(result, PROMISE_RESULT_CHANGE); } virDomainFree(dom); } else { cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_NOOP, pp, a, "No such virtual domain called '%s' - promise kept", pp->promiser); } return result; }
int VerifyUnmount(char *name, Attributes a, Promise *pp) { char comm[CF_BUFSIZE], line[CF_BUFSIZE]; FILE *pfp; char *mountpt; mountpt = name; if (!DONTDO) { snprintf(comm, CF_BUFSIZE, "%s %s", VUNMOUNTCOMM[VSYSTEMHARDCLASS], mountpt); if ((pfp = cf_popen(comm, "r")) == NULL) { CfOut(cf_error, "", " !! Failed to open pipe from %s\n", VUNMOUNTCOMM[VSYSTEMHARDCLASS]); return 0; } CfReadLine(line, CF_BUFSIZE, pfp); if ((strstr(line, "busy")) || (strstr(line, "Busy"))) { cfPS(cf_inform, CF_INTERPT, "", pp, a, " !! The device under %s cannot be unmounted\n", mountpt); cf_pclose(pfp); return 1; } cf_pclose(pfp); } cfPS(cf_inform, CF_CHG, "", pp, a, " -> Unmounting %s to keep promise\n", mountpt); return 0; }
static int DeleteVirt(EvalContext *ctx, virConnectPtr vc, Attributes a, Promise *pp) { virDomainPtr dom; int ret = true; dom = virDomainLookupByName(vc, pp->promiser); if (dom) { if (virDomainDestroy(dom) == -1) { cfPS(ctx, OUTPUT_LEVEL_VERBOSE, PROMISE_RESULT_FAIL, "", pp, a, " !! Failed to delete virtual domain \"%s\"\n", pp->promiser); ret = false; } else { cfPS(ctx, OUTPUT_LEVEL_VERBOSE, PROMISE_RESULT_CHANGE, "", pp, a, " -> Deleted virtual domain \"%s\"\n", pp->promiser); } virDomainFree(dom); } else { cfPS(ctx, OUTPUT_LEVEL_VERBOSE, PROMISE_RESULT_NOOP, "", pp, a, " -> No such virtual domain called \"%s\" - promise kept\n", pp->promiser); } return ret; }
static int DeleteVirtNetwork(EvalContext *ctx, virConnectPtr vc, Attributes a, Promise *pp) { virNetworkPtr network; int ret = true; if ((network = virNetworkLookupByName(vc, pp->promiser)) == NULL) { cfPS(ctx, OUTPUT_LEVEL_VERBOSE, PROMISE_RESULT_NOOP, "", pp, a, " -> Couldn't find a network called \"%s\" - promise assumed kept\n", pp->promiser); return true; } if (virNetworkDestroy(network) == 0) { cfPS(ctx, OUTPUT_LEVEL_INFORM, PROMISE_RESULT_CHANGE, "", pp, a, " -> Deleted network \"%s\" - promise repaired\n", pp->promiser); } else { cfPS(ctx, OUTPUT_LEVEL_ERROR, PROMISE_RESULT_FAIL, "", pp, a, " !! Network deletion of \"%s\" failed\n", pp->promiser); ret = false; } virNetworkFree(network); return ret; }
int VerifyMount(char *name, Attributes a, Promise *pp) { char comm[CF_BUFSIZE], line[CF_BUFSIZE]; FILE *pfp; char *host, *rmountpt, *mountpt; host = a.mount.mount_server; rmountpt = a.mount.mount_source; mountpt = name; if (!DONTDO) { snprintf(comm, CF_BUFSIZE, "%s %s:%s %s", GetArg0(VMOUNTCOMM[VSYSTEMHARDCLASS]), host, rmountpt, mountpt); if ((pfp = cf_popen(comm, "r")) == NULL) { CfOut(cf_error, "", " !! Failed to open pipe from %s\n", GetArg0(VMOUNTCOMM[VSYSTEMHARDCLASS])); return 0; } CfReadLine(line, CF_BUFSIZE, pfp); if (strstr(line, "busy") || strstr(line, "Busy")) { cfPS(cf_inform, CF_INTERPT, "", pp, a, " !! The device under %s cannot be mounted\n", mountpt); cf_pclose(pfp); return 1; } cf_pclose(pfp); } cfPS(cf_inform, CF_CHG, "", pp, a, " -> Mounting %s to keep promise\n", mountpt); return 0; }
static PromiseResult DeleteVirtNetwork(EvalContext *ctx, virConnectPtr vc, Attributes a, const Promise *pp) { virNetworkPtr network; if ((network = virNetworkLookupByName(vc, pp->promiser)) == NULL) { cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_NOOP, pp, a, "Couldn't find a network called '%s' - promise assumed kept", pp->promiser); return PROMISE_RESULT_NOOP; } PromiseResult result = PROMISE_RESULT_NOOP; if (virNetworkDestroy(network) == 0) { cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_CHANGE, pp, a, "Deleted network '%s' - promise repaired", pp->promiser); result = PromiseResultUpdate(result, PROMISE_RESULT_CHANGE); } else { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Network deletion of '%s' failed", pp->promiser); result = PromiseResultUpdate(result, PROMISE_RESULT_FAIL); } virNetworkFree(network); return result; }
static VersionCmpResult RunCmpCommand(const char *command, const char *v1, const char *v2, Attributes a, Promise *pp) { char expanded_command[CF_EXPANDSIZE]; SetNewScope("cf_pack_context"); NewScalar("cf_pack_context", "v1", v1, cf_str); NewScalar("cf_pack_context", "v2", v2, cf_str); ExpandScalar(command, expanded_command); DeleteScope("cf_pack_context"); FILE *pfp = a.packages.package_commands_useshell ? cf_popen_sh(expanded_command, "w") : cf_popen(expanded_command, "w"); if (pfp == NULL) { cfPS(cf_error, CF_FAIL, "cf_popen", pp, a, "Can not start package version comparison command: %s", expanded_command); return VERCMP_ERROR; } CfOut(cf_verbose, "", "Executing %s", expanded_command); int retcode = cf_pclose(pfp); if (retcode == -1) { cfPS(cf_error, CF_FAIL, "cf_pclose", pp, a, "Error during package version comparison command execution: %s", expanded_command); return VERCMP_ERROR; } return retcode == 0; }
static bool MakeLink(EvalContext *ctx, const char *from, const char *to, Attributes attr, const Promise *pp, PromiseResult *result) { if (DONTDO || (attr.transaction.action == cfa_warn)) { Log(LOG_LEVEL_WARNING, "Need to link files '%s' -> '%s'", from, to); return false; } else { if (symlink(to, from) == -1) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, attr, "Couldn't link '%s' to '%s'. (symlink: %s)", to, from, GetErrorStr()); *result = PromiseResultUpdate(*result, PROMISE_RESULT_FAIL); return false; } else { cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_CHANGE, pp, attr, "Linked files '%s' -> '%s'", from, to); *result = PromiseResultUpdate(*result, PROMISE_RESULT_CHANGE); return true; } } }
static PromiseResult CreateVirtNetwork(EvalContext *ctx, virConnectPtr vc, char **networks, Attributes a, const Promise *pp) { virNetworkPtr network; char *xml_file; char defaultxml[CF_MAXVARSIZE]; int i, found = false; snprintf(defaultxml, CF_MAXVARSIZE - 1, "<network>" "<name>%s</name>" "<bridge name=\"virbr0\" />" "<forward mode=\"nat\"/>" "<ip address=\"192.168.122.1\" netmask=\"255.255.255.0\">" "<dhcp>" "<range start=\"192.168.122.2\" end=\"192.168.122.254\" />" "</dhcp>" "</ip>" "</network>", pp->promiser); for (i = 0; networks[i] != NULL; i++) { Log(LOG_LEVEL_VERBOSE, "Discovered a running network '%s'", networks[i]); if (strcmp(networks[i], pp->promiser) == 0) { found = true; } } if (found) { cfPS(ctx, LOG_LEVEL_VERBOSE, PROMISE_RESULT_NOOP, pp, a, "Network '%s' exists - promise kept", pp->promiser); return PROMISE_RESULT_NOOP; } if (a.env.spec) { xml_file = xstrdup(a.env.spec); } else { xml_file = xstrdup(defaultxml); } PromiseResult result = PROMISE_RESULT_NOOP; if ((network = virNetworkCreateXML(vc, xml_file)) == NULL) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Unable to create network '%s'", pp->promiser); free(xml_file); return PROMISE_RESULT_FAIL; } else { cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_CHANGE, pp, a, "Created network '%s' - promise repaired", pp->promiser); result = PromiseResultUpdate(result, PROMISE_RESULT_CHANGE); } free(xml_file); virNetworkFree(network); return result; }
int Unix_DoAllSignals(Item *siglist, Attributes a, Promise *pp) { Item *ip; Rlist *rp; pid_t pid; int killed = false; CfDebug("DoSignals(%s)\n", pp->promiser); if (siglist == NULL) { return 0; } if (a.signals == NULL) { CfOut(cf_verbose, "", " -> No signals to send for %s\n", pp->promiser); return 0; } for (ip = siglist; ip != NULL; ip = ip->next) { pid = ip->counter; for (rp = a.signals; rp != NULL; rp = rp->next) { int signal = Signal2Int(rp->item); if (!DONTDO) { if (signal == SIGKILL || signal == SIGTERM) { killed = true; } if (kill((pid_t) pid, signal) < 0) { cfPS(cf_verbose, CF_FAIL, "kill", pp, a, " !! Couldn't send promised signal \'%s\' (%d) to pid %jd (might be dead)\n", ScalarValue(rp), signal, (intmax_t)pid); } else { cfPS(cf_inform, CF_CHG, "", pp, a, " -> Signalled '%s' (%d) to process %jd (%s)\n", ScalarValue(rp), signal, (intmax_t)pid, ip->name); } } else { CfOut(cf_error, "", " -> Need to keep signal promise \'%s\' in process entry %s", ScalarValue(rp), ip->name); } } } return killed; }
static int CreateVirtNetwork(virConnectPtr vc, char **networks, Attributes a, Promise *pp) { virNetworkPtr network; char *xml_file; char defaultxml[CF_MAXVARSIZE]; int i, found = false; snprintf(defaultxml, CF_MAXVARSIZE - 1, "<network>" "<name>%s</name>" "<bridge name=\"virbr0\" />" "<forward mode=\"nat\"/>" "<ip address=\"192.168.122.1\" netmask=\"255.255.255.0\">" "<dhcp>" "<range start=\"192.168.122.2\" end=\"192.168.122.254\" />" "</dhcp>" "</ip>" "</network>", pp->promiser); for (i = 0; networks[i] != NULL; i++) { CfOut(cf_verbose, "", " -> Discovered a running network \"%s\"", networks[i]); if (strcmp(networks[i], pp->promiser) == 0) { found = true; } } if (found) { cfPS(cf_verbose, CF_NOP, "", pp, a, " -> Network \"%s\" exists - promise kept\n", pp->promiser); return true; } if (a.env.spec) { xml_file = xstrdup(a.env.spec); } else { xml_file = xstrdup(defaultxml); } if ((network = virNetworkCreateXML(vc, xml_file)) == NULL) { cfPS(cf_error, CF_FAIL, "", pp, a, " !! Unable to create network \"%s\"\n", pp->promiser); free(xml_file); return false; } else { cfPS(cf_inform, CF_CHG, "", pp, a, " -> Created network \"%s\" - promise repaired\n", pp->promiser); } free(xml_file); virNetworkFree(network); return true; }
int DoAllSignals(EvalContext *ctx, Item *siglist, Attributes a, const Promise *pp, PromiseResult *result) { Item *ip; Rlist *rp; pid_t pid; int killed = false; if (siglist == NULL) { return 0; } if (a.signals == NULL) { Log(LOG_LEVEL_VERBOSE, "No signals to send for '%s'", pp->promiser); return 0; } for (ip = siglist; ip != NULL; ip = ip->next) { pid = ip->counter; for (rp = a.signals; rp != NULL; rp = rp->next) { int signal = SignalFromString(RlistScalarValue(rp)); if (!DONTDO) { if ((signal == SIGKILL) || (signal == SIGTERM)) { killed = true; } if (kill((pid_t) pid, signal) < 0) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Couldn't send promised signal '%s' (%d) to pid %jd (might be dead). (kill: %s)", RlistScalarValue(rp), signal, (intmax_t)pid, GetErrorStr()); *result = PromiseResultUpdate(*result, PROMISE_RESULT_FAIL); } else { cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_CHANGE, pp, a, "Signalled '%s' (%d) to process %jd (%s)", RlistScalarValue(rp), signal, (intmax_t)pid, ip->name); *result = PromiseResultUpdate(*result, PROMISE_RESULT_CHANGE); } } else { Log(LOG_LEVEL_ERR, "Need to keep signal promise '%s' in process entry '%s'", RlistScalarValue(rp), ip->name); } } } return killed; }
static int DoAllSignals(Item *siglist, Attributes a, Promise *pp) { Item *ip; Rlist *rp; pid_t pid; int killed = false; CfDebug("DoSignals(%s)\n", pp->promiser); if (siglist == NULL) { return 0; } if (a.signals == NULL) { CfOut(OUTPUT_LEVEL_VERBOSE, "", " -> No signals to send for %s\n", pp->promiser); return 0; } for (ip = siglist; ip != NULL; ip = ip->next) { pid = ip->counter; for (rp = a.signals; rp != NULL; rp = rp->next) { int signal = SignalFromString(rp->item); if (!DONTDO) { if ((signal == SIGKILL) || (signal == SIGTERM)) { killed = true; } if (kill((pid_t) pid, signal) < 0) { cfPS(OUTPUT_LEVEL_VERBOSE, CF_FAIL, "kill", pp, a, " !! Couldn't send promised signal \'%s\' (%d) to pid %jd (might be dead)\n", RlistScalarValue(rp), signal, (intmax_t)pid); } else { cfPS(OUTPUT_LEVEL_INFORM, CF_CHG, "", pp, a, " -> Signalled '%s' (%d) to process %jd (%s)\n", RlistScalarValue(rp), signal, (intmax_t)pid, ip->name); } } else { CfOut(OUTPUT_LEVEL_ERROR, "", " -> Need to keep signal promise \'%s\' in process entry %s", RlistScalarValue(rp), ip->name); } } } return killed; }
static PromiseResult VerifyFreeSpace(EvalContext *ctx, char *file, Attributes a, Promise *pp) { struct stat statbuf; #ifdef __MINGW32__ if (!a.volume.check_foreign) { Log(LOG_LEVEL_VERBOSE, "storage.volume.check_foreign is not supported on Windows (checking every mount)"); } #endif /* __MINGW32__ */ if (stat(file, &statbuf) == -1) { Log(LOG_LEVEL_ERR, "Couldn't stat '%s' while checking diskspace. (stat: %s)", file, GetErrorStr()); return PROMISE_RESULT_NOOP; } #ifndef __MINGW32__ if (!a.volume.check_foreign) { if (IsForeignFileSystem(&statbuf, file)) { Log(LOG_LEVEL_INFO, "Filesystem '%s' is mounted from a foreign system, so skipping it", file); return PROMISE_RESULT_NOOP; } } #endif /* !__MINGW32__ */ if (a.volume.freespace < 0) { int threshold_percentage = -a.volume.freespace; int free_percentage = GetDiskUsage(file, cfpercent); if (free_percentage < threshold_percentage) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Free disk space is under %d%% for volume containing '%s', %d%% free", threshold_percentage, file, free_percentage); return PROMISE_RESULT_FAIL; } } else { off_t threshold = a.volume.freespace; off_t free_bytes = GetDiskUsage(file, cfabs); if (free_bytes < threshold) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Disk space under %jd kB for volume containing '%s' (%jd kB free)", (intmax_t) (threshold / 1024), file, (intmax_t) (free_bytes / 1024)); return PROMISE_RESULT_FAIL; } } return PROMISE_RESULT_NOOP; }
static int VerifyFreeSpace(EvalContext *ctx, char *file, Attributes a, Promise *pp) { struct stat statbuf; #ifdef __MINGW32__ if (!a.volume.check_foreign) { CfOut(OUTPUT_LEVEL_VERBOSE, "", "storage.volume.check_foreign is not supported on Windows (checking every mount)"); } #endif /* __MINGW32__ */ if (cfstat(file, &statbuf) == -1) { CfOut(OUTPUT_LEVEL_ERROR, "stat", "Couldn't stat %s checking diskspace\n", file); return true; } #ifndef __MINGW32__ if (!a.volume.check_foreign) { if (IsForeignFileSystem(&statbuf, file)) { CfOut(OUTPUT_LEVEL_INFORM, "", "Filesystem %s is mounted from a foreign system, so skipping it", file); return true; } } #endif /* !__MINGW32__ */ if (a.volume.freespace < 0) { int threshold_percentage = -a.volume.freespace; int free_percentage = GetDiskUsage(file, cfpercent); if (free_percentage < threshold_percentage) { cfPS(ctx, OUTPUT_LEVEL_ERROR, PROMISE_RESULT_FAIL, "", pp, a, " !! Free disk space is under %d%% for volume containing %s (%d%% free)\n", threshold_percentage, file, free_percentage); return false; } } else { off_t threshold = a.volume.freespace; off_t free_bytes = GetDiskUsage(file, cfabs); if (free_bytes < threshold) { cfPS(ctx, OUTPUT_LEVEL_ERROR, PROMISE_RESULT_FAIL, "", pp, a, " !! Disk space under %jd kB for volume containing %s (%jd kB free)\n", (intmax_t) (threshold / 1024), file, (intmax_t) (free_bytes / 1024)); return false; } } return true; }
int VerifyMount(EvalContext *ctx, char *name, Attributes a, Promise *pp) { char comm[CF_BUFSIZE], line[CF_BUFSIZE]; FILE *pfp; char *host, *rmountpt, *mountpt, *opts=NULL; host = a.mount.mount_server; rmountpt = a.mount.mount_source; mountpt = name; /* Check for options required for this mount - i.e., -o ro,rsize, etc. */ if (a.mount.mount_options) { opts = Rlist2String(a.mount.mount_options, ","); } else { opts = xstrdup(VMOUNTOPTS[VSYSTEMHARDCLASS]); } if (!DONTDO) { snprintf(comm, CF_BUFSIZE, "%s -o %s %s:%s %s", CommandArg0(VMOUNTCOMM[VSYSTEMHARDCLASS]), opts, host, rmountpt, mountpt); if ((pfp = cf_popen(comm, "r", true)) == NULL) { Log(LOG_LEVEL_ERR, "Failed to open pipe from %s", CommandArg0(VMOUNTCOMM[VSYSTEMHARDCLASS])); return 0; } ssize_t res = CfReadLine(line, CF_BUFSIZE, pfp); if (res == -1) { Log(LOG_LEVEL_ERR, "Unable to read output of mount command. (fread: %s)", GetErrorStr()); cf_pclose(pfp); return 0; } if (res != 0 && ((strstr(line, "busy")) || (strstr(line, "Busy")))) { cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_INTERRUPTED, pp, a, "The device under %s cannot be mounted\n", mountpt); cf_pclose(pfp); return 1; } cf_pclose(pfp); } /* Since opts is either Rlist2String or xstrdup'd, we need to always free it */ free(opts); cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_CHANGE, pp, a, "Mounting %s to keep promise\n", mountpt); return 0; }
static PromiseResult DoVerifyServices(EvalContext *ctx, Attributes a, const Promise *pp) { FnCall *service_bundle = PromiseGetConstraintAsRval(pp, "service_bundle", RVAL_TYPE_FNCALL); PromiseResult result = PROMISE_RESULT_NOOP; if (!service_bundle) { service_bundle = PromiseGetConstraintAsRval(pp, "service_bundle", RVAL_TYPE_SCALAR); } if (!service_bundle) { cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_FAIL, pp, a, "Service '%s' cannot be resolved as a bundle", pp->promiser); return PromiseResultUpdate(result, PROMISE_RESULT_FAIL); } switch (a.service.service_policy) { case SERVICE_POLICY_START: EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_THIS, "service_policy", "start", CF_DATA_TYPE_STRING, "source=promise"); break; case SERVICE_POLICY_RESTART: EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_THIS, "service_policy", "restart", CF_DATA_TYPE_STRING, "source=promise"); break; case SERVICE_POLICY_RELOAD: EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_THIS, "service_policy", "reload", CF_DATA_TYPE_STRING, "source=promise"); break; case SERVICE_POLICY_STOP: case SERVICE_POLICY_DISABLE: default: EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_THIS, "service_policy", "stop", CF_DATA_TYPE_STRING, "source=promise"); break; } const Bundle *bp = PolicyGetBundle(PolicyFromPromise(pp), NULL, "agent", service_bundle->name); if (!bp) { bp = PolicyGetBundle(PolicyFromPromise(pp), NULL, "common", service_bundle->name); } if (!bp) { cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_FAIL, pp, a, "Service '%s' could not be invoked successfully", pp->promiser); result = PromiseResultUpdate(result, PROMISE_RESULT_FAIL); } if (!DONTDO) { result = PromiseResultUpdate(result, VerifyMethod(ctx, "service_bundle", a, pp)); // Send list of classes to set privately? } return result; }
int VerifyMount(char *name, Attributes a, Promise *pp) { char comm[CF_BUFSIZE], line[CF_BUFSIZE]; FILE *pfp; char *host, *rmountpt, *mountpt, *opts=NULL; host = a.mount.mount_server; rmountpt = a.mount.mount_source; mountpt = name; /* Check for options required for this mount - i.e., -o ro,rsize, etc. */ if (a.mount.mount_options) { opts = Rlist2String(a.mount.mount_options, ","); } else { opts = xstrdup(VMOUNTOPTS[VSYSTEMHARDCLASS]); } if (!DONTDO) { snprintf(comm, CF_BUFSIZE, "%s -o %s %s:%s %s", GetArg0(VMOUNTCOMM[VSYSTEMHARDCLASS]), opts, host, rmountpt, mountpt); if ((pfp = cf_popen(comm, "r")) == NULL) { CfOut(cf_error, "", " !! Failed to open pipe from %s\n", GetArg0(VMOUNTCOMM[VSYSTEMHARDCLASS])); return 0; } if (CfReadLine(line, CF_BUFSIZE, pfp) == -1) { FatalError("Error in CfReadLine"); } if ((strstr(line, "busy")) || (strstr(line, "Busy"))) { cfPS(cf_inform, CF_INTERPT, "", pp, a, " !! The device under %s cannot be mounted\n", mountpt); cf_pclose(pfp); return 1; } cf_pclose(pfp); } /* Since opts is either Rlist2String or xstrdup'd, we need to always free it */ free(opts); cfPS(cf_inform, CF_CHG, "", pp, a, " -> Mounting %s to keep promise\n", mountpt); return 0; }
bool SaveXmlCallback(EvalContext *ctx, const char *dest_filename, const char *orig_filename, void *param, Attributes a, Promise *pp) { xmlDocPtr doc = param; //saving xml to file if (xmlSaveFile(dest_filename, doc) == -1) { cfPS(ctx, OUTPUT_LEVEL_ERROR, CF_FAIL, "xmlSaveFile", pp, a, "Failed to write xml document to file %s after editing\n", dest_filename); return false; } cfPS(ctx, OUTPUT_LEVEL_INFORM, CF_CHG, "", pp, a, " -> Edited xml file %s \n", orig_filename); return true; }
PromiseResult VerifyUsersPromise(EvalContext *ctx, Promise *pp) { Attributes a = { {0} }; CfLock thislock; char lockname[CF_BUFSIZE]; a = GetUserAttributes(ctx, pp); if (!UserSanityCheck(a, pp)) { return PROMISE_RESULT_FAIL; } PromiseBanner(pp); snprintf(lockname, CF_BUFSIZE - 1, "user-%s-%d", pp->promiser, a.users.policy); thislock = AcquireLock(ctx, lockname, VUQNAME, CFSTARTTIME, a.transaction, pp, false); if (thislock.lock == NULL) { return PROMISE_RESULT_SKIPPED; } PromiseResult result = PROMISE_RESULT_NOOP; VerifyOneUsersPromise(pp->promiser, a.users, &result, a.transaction.action, ctx, &a, pp); switch (result) { case PROMISE_RESULT_NOOP: cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_NOOP, pp, a, "User promise kept"); break; case PROMISE_RESULT_FAIL: case PROMISE_RESULT_DENIED: case PROMISE_RESULT_TIMEOUT: case PROMISE_RESULT_INTERRUPTED: case PROMISE_RESULT_WARN: cfPS(ctx, LOG_LEVEL_INFO, result, pp, a, "User promise not kept"); break; case PROMISE_RESULT_CHANGE: cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_CHANGE, pp, a, "User promise repaired"); break; default: ProgrammingError("Unknown promise result"); break; } YieldCurrentLock(thislock); return result; }
PromiseResult VerifyUnmount(EvalContext *ctx, char *name, const Attributes *a, const Promise *pp) { char comm[CF_BUFSIZE]; FILE *pfp; char *mountpt; mountpt = name; PromiseResult result = PROMISE_RESULT_NOOP; if (!DONTDO) { snprintf(comm, CF_BUFSIZE, "%s %s", VUNMOUNTCOMM[VSYSTEMHARDCLASS], mountpt); if ((pfp = cf_popen(comm, "r", true)) == NULL) { Log(LOG_LEVEL_ERR, "Failed to open pipe from %s", VUNMOUNTCOMM[VSYSTEMHARDCLASS]); return result; } size_t line_size = CF_BUFSIZE; char *line = xmalloc(line_size); ssize_t res = CfReadLine(&line, &line_size, pfp); if (res == -1) { cf_pclose(pfp); free(line); if (!feof(pfp)) { Log(LOG_LEVEL_ERR, "Unable to read output of unmount command. (fread: %s)", GetErrorStr()); return result; } } else if (res > 0 && ((strstr(line, "busy")) || (strstr(line, "Busy")))) { cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_INTERRUPTED, pp, a, "The device under '%s' cannot be unmounted", mountpt); result = PromiseResultUpdate(result, PROMISE_RESULT_INTERRUPTED); cf_pclose(pfp); free(line); return result; } } cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_CHANGE, pp, a, "Unmounting '%s' to keep promise", mountpt); result = PromiseResultUpdate(result, PROMISE_RESULT_CHANGE); return result; }
static VersionCmpResult RunCmpCommand(EvalContext *ctx, const char *command, const char *v1, const char *v2, Attributes a, const Promise *pp, PromiseResult *result) { Buffer *expanded_command = BufferNew(); { VarRef *ref_v1 = VarRefParseFromScope("v1", PACKAGES_CONTEXT); EvalContextVariablePut(ctx, ref_v1, v1, CF_DATA_TYPE_STRING, "source=promise"); VarRef *ref_v2 = VarRefParseFromScope("v2", PACKAGES_CONTEXT); EvalContextVariablePut(ctx, ref_v2, v2, CF_DATA_TYPE_STRING, "source=promise"); ExpandScalar(ctx, NULL, PACKAGES_CONTEXT, command, expanded_command); EvalContextVariableRemove(ctx, ref_v1); VarRefDestroy(ref_v1); EvalContextVariableRemove(ctx, ref_v2); VarRefDestroy(ref_v2); } FILE *pfp = a.packages.package_commands_useshell ? cf_popen_sh(BufferData(expanded_command), "w") : cf_popen(BufferData(expanded_command), "w", true); if (pfp == NULL) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Can not start package version comparison command '%s'. (cf_popen: %s)", BufferData(expanded_command), GetErrorStr()); *result = PromiseResultUpdate(*result, PROMISE_RESULT_FAIL); BufferDestroy(expanded_command); return VERCMP_ERROR; } Log(LOG_LEVEL_VERBOSE, "Executing '%s'", BufferData(expanded_command)); int retcode = cf_pclose(pfp); if (retcode == -1) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Error during package version comparison command execution '%s'. (cf_pclose: %s)", BufferData(expanded_command), GetErrorStr()); *result = PromiseResultUpdate(*result, PROMISE_RESULT_FAIL); BufferDestroy(expanded_command); return VERCMP_ERROR; } BufferDestroy(expanded_command); return retcode == 0; }
PromiseResult VerifyMeasurementPromise(EvalContext *ctx, double *measurement, const Promise *pp) { if (EvalContextPromiseIsDone(ctx, pp)) { if (pp->comment) { Log(LOG_LEVEL_VERBOSE, "Skipping static observation '%s' (comment: %s), already done", pp->promiser, pp->comment); } else { Log(LOG_LEVEL_VERBOSE, "Skipping static observation '%s', already done", pp->promiser); } return PROMISE_RESULT_NOOP; } PromiseBanner(pp); Attributes a = GetMeasurementAttributes(ctx, pp); if (!CheckMeasureSanity(a.measure, pp)) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_INTERRUPTED, pp, a, "Measurement promise is not valid"); return PROMISE_RESULT_INTERRUPTED; } return VerifyMeasurement(ctx, measurement, a, pp); }
PromiseResult CheckPosixLinuxACL(EvalContext *ctx, ARG_UNUSED const char *file_path, ARG_UNUSED Acl acl, Attributes a, const Promise *pp) { cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Posix ACLs are not supported on this Linux system - install the Posix acl library"); PromiseRef(LOG_LEVEL_ERR, pp); return PROMISE_RESULT_FAIL; }
static void PrintFile(Attributes a, Promise *pp) { FILE *fp; char buffer[CF_BUFSIZE]; int lines = 0; if (a.report.filename == NULL) { CfOut(cf_verbose, "", "Printfile promise was incomplete, with no filename.\n"); return; } if ((fp = fopen(a.report.filename, "r")) == NULL) { cfPS(cf_error, CF_INTERPT, "fopen", pp, a, " !! Printing of file %s was not possible.\n", a.report.filename); return; } while (!feof(fp) && (lines < a.report.numlines)) { buffer[0] = '\0'; fgets(buffer, CF_BUFSIZE, fp); CfOut(cf_error, "", "R: %s", buffer); lines++; } fclose(fp); }
bool KillGhostLink(EvalContext *ctx, const char *name, Attributes attr, const Promise *pp, PromiseResult *result) { Log(LOG_LEVEL_VERBOSE, "Windows does not support symbolic links (at KillGhostLink())"); cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, attr, "Windows does not support killing link '%s'", name); PromiseResultUpdate(*result, PROMISE_RESULT_FAIL); return false; }