static int _yapi_desc(const cint_parameter_desc_t *desc, int level) { int dim_index; _yapi_indent(level); CINT_PRINTF("basetype: %s\n", NULLSTR(desc->basetype)); _yapi_indent(level); CINT_PRINTF("pcount: %d\n", desc->pcount); _yapi_indent(level); CINT_PRINTF("name: %s\n", NULLSTR(desc->name)); _yapi_indent(level); CINT_PRINTF( "arrayDimensions: %d\n", desc->utype.declaration.arrayDimensions); for(dim_index = 0; dim_index < desc->utype.declaration.arrayDimensions; ++dim_index) { _yapi_indent(level); CINT_PRINTF( "dimensions[%d]: %d\n", dim_index, desc->dimensions[dim_index]); } _yapi_indent(level); CINT_PRINTF("flags: %d\n", desc->flags); return 0; }
void do_chsave( CHAR_DATA *ch, char *argument ) { char arg1[MAX_INPUT_LENGTH]; char arg2[MAX_INPUT_LENGTH]; char buf[MSL]; argument = one_argument( argument, arg1 ); argument = one_argument( argument, arg2 ); if ( IS_NPC(ch) ) return; if (!ch->desc || NULLSTR(arg1) ) { send_to_char("Syntax: chsave load/save\n\r",ch); send_to_char("Syntax: chsave delete (change number)\n\r",ch); return; } if ( !str_cmp(arg1,"load") ) { load_changes( ); send_to_char("Changes Loaded.\n\r",ch); return; } if ( !str_cmp(arg1,"save") ) { save_changes( ); send_to_char("Changes Saved.\n\r",ch); return; } if ( !str_cmp(arg1, "delete")) { int num; if ( NULLSTR(arg2) || !is_number( arg2 ) ) { send_to_char("For chsave delete, you must provide a change number.\n\r",ch); send_to_char("Syntax: chsave delete (change number)\n\r",ch); return; } num = atoi( arg2 ); if ( num < 0 || num > maxChanges ) { sprintf( buf, "Valid changes are from 0 to %d.\n\r", maxChanges ); send_to_char( buf, ch ); return; } delete_change( num ); send_to_char("Change deleted.\n\r",ch); return; } return; }
/** * qemuAgentSend: * @mon: Monitor * @msg: Message * @seconds: number of seconds to wait for the result, it can be either * -2, -1, 0 or positive. * * Send @msg to agent @mon. If @seconds is equal to * VIR_DOMAIN_QEMU_AGENT_COMMAND_BLOCK(-2), this function will block forever * waiting for the result. The value of * VIR_DOMAIN_QEMU_AGENT_COMMAND_DEFAULT(-1) means use default timeout value * and VIR_DOMAIN_QEMU_AGENT_COMMAND_NOWAIT(0) makes this this function return * immediately without waiting. Any positive value means the number of seconds * to wait for the result. * * Returns: 0 on success, * -2 on timeout, * -1 otherwise */ static int qemuAgentSend(qemuAgentPtr mon, qemuAgentMessagePtr msg, int seconds) { int ret = -1; unsigned long long then = 0; /* Check whether qemu quit unexpectedly */ if (mon->lastError.code != VIR_ERR_OK) { VIR_DEBUG("Attempt to send command while error is set %s", NULLSTR(mon->lastError.message)); virSetError(&mon->lastError); return -1; } if (seconds > VIR_DOMAIN_QEMU_AGENT_COMMAND_BLOCK) { unsigned long long now; if (virTimeMillisNow(&now) < 0) return -1; if (seconds == VIR_DOMAIN_QEMU_AGENT_COMMAND_DEFAULT) seconds = QEMU_AGENT_WAIT_TIME; then = now + seconds * 1000ull; } mon->msg = msg; qemuAgentUpdateWatch(mon); while (!mon->msg->finished) { if ((then && virCondWaitUntil(&mon->notify, &mon->parent.lock, then) < 0) || (!then && virCondWait(&mon->notify, &mon->parent.lock) < 0)) { if (errno == ETIMEDOUT) { virReportError(VIR_ERR_AGENT_UNRESPONSIVE, "%s", _("Guest agent not available for now")); ret = -2; } else { virReportSystemError(errno, "%s", _("Unable to wait on agent monitor " "condition")); } goto cleanup; } } if (mon->lastError.code != VIR_ERR_OK) { VIR_DEBUG("Send command resulted in error %s", NULLSTR(mon->lastError.message)); virSetError(&mon->lastError); goto cleanup; } ret = 0; cleanup: mon->msg = NULL; qemuAgentUpdateWatch(mon); return ret; }
/** * virNetDevVethCreate: * @veth1: pointer to name for parent end of veth pair * @veth2: pointer to return name for container end of veth pair * * Creates a veth device pair using the ip command: * ip link add veth1 type veth peer name veth2 * If veth1 points to NULL on entry, it will be a valid interface on * return. veth2 should point to NULL on entry. * * NOTE: If veth1 and veth2 names are not specified, ip will auto assign * names. There seems to be two problems here - * 1) There doesn't seem to be a way to determine the names of the * devices that it creates. They show up in ip link show and * under /sys/class/net/ however there is no guarantee that they * are the devices that this process just created. * 2) Once one of the veth devices is moved to another namespace, it * is no longer visible in the parent namespace. This seems to * confuse the name assignment causing it to fail with File exists. * Because of these issues, this function currently allocates names * prior to using the ip command, and returns any allocated names * to the caller. * * Returns 0 on success or -1 in case of error */ int virNetDevVethCreate(char** veth1, char** veth2) { int rc = -1; const char *argv[] = { "ip", "link", "add", NULL, "type", "veth", "peer", "name", NULL, NULL }; int vethDev = 0; bool veth1_alloc = false; bool veth2_alloc = false; VIR_DEBUG("Host: %s guest: %s", NULLSTR(*veth1), NULLSTR(*veth2)); if (*veth1 == NULL) { if ((vethDev = virNetDevVethGetFreeName(veth1, vethDev)) < 0) goto cleanup; VIR_DEBUG("Assigned host: %s", *veth1); veth1_alloc = true; vethDev++; } argv[3] = *veth1; while (*veth2 == NULL) { if ((vethDev = virNetDevVethGetFreeName(veth2, vethDev)) < 0) { if (veth1_alloc) VIR_FREE(*veth1); goto cleanup; } /* Just make sure they didn't accidentally get same name */ if (STREQ(*veth1, *veth2)) { vethDev++; VIR_FREE(*veth2); continue; } VIR_DEBUG("Assigned guest: %s", *veth2); veth2_alloc = true; } argv[8] = *veth2; VIR_DEBUG("Create Host: %s guest: %s", *veth1, *veth2); if (virRun(argv, NULL) < 0) { if (veth1_alloc) VIR_FREE(*veth1); if (veth2_alloc) VIR_FREE(*veth2); goto cleanup; } rc = 0; cleanup: return rc; }
/** * qemuAgentSend: * @mon: Monitor * @msg: Message * @timeout: use timeout? * * Send @msg to agent @mon. * Wait max QEMU_AGENT_WAIT_TIME for agent * to reply. * * Returns: 0 on success, * -2 on timeout, * -1 otherwise */ static int qemuAgentSend(qemuAgentPtr mon, qemuAgentMessagePtr msg, bool timeout) { int ret = -1; unsigned long long now, then = 0; /* Check whether qemu quit unexpectedly */ if (mon->lastError.code != VIR_ERR_OK) { VIR_DEBUG("Attempt to send command while error is set %s", NULLSTR(mon->lastError.message)); virSetError(&mon->lastError); return -1; } if (timeout) { if (virTimeMillisNow(&now) < 0) return -1; then = now + QEMU_AGENT_WAIT_TIME; } mon->msg = msg; qemuAgentUpdateWatch(mon); while (!mon->msg->finished) { if ((timeout && virCondWaitUntil(&mon->notify, &mon->lock, then) < 0) || (!timeout && virCondWait(&mon->notify, &mon->lock) < 0)) { if (errno == ETIMEDOUT) { qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Guest agent not available for now")); ret = -2; } else { qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Unable to wait on monitor condition")); } goto cleanup; } } if (mon->lastError.code != VIR_ERR_OK) { VIR_DEBUG("Send command resulted in error %s", NULLSTR(mon->lastError.message)); virSetError(&mon->lastError); goto cleanup; } ret = 0; cleanup: mon->msg = NULL; qemuAgentUpdateWatch(mon); return ret; }
int hyperyVerifyResponse(WsManClient *client, WsXmlDocH response, const char *detail) { int lastError = wsmc_get_last_error(client); int responseCode = wsmc_get_response_code(client); WsManFault *fault; if (lastError != WS_LASTERR_OK) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Transport error during %s: %s (%d)"), detail, wsman_transport_get_last_error_string(lastError), lastError); return -1; } /* Check the HTTP response code and report an error if it's not 200 (OK), * 400 (Bad Request) or 500 (Internal Server Error) */ if (responseCode != 200 && responseCode != 400 && responseCode != 500) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Unexpected HTTP response during %s: %d"), detail, responseCode); return -1; } if (response == NULL) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Empty response during %s"), detail); return -1; } if (wsmc_check_for_fault(response)) { fault = wsmc_fault_new(); if (fault == NULL) { virReportOOMError(); return -1; } wsmc_get_fault_data(response, fault); virReportError(VIR_ERR_INTERNAL_ERROR, _("SOAP fault during %s: code '%s', subcode '%s', " "reason '%s', detail '%s'"), detail, NULLSTR(fault->code), NULLSTR(fault->subcode), NULLSTR(fault->reason), NULLSTR(fault->fault_detail)); wsmc_fault_destroy(fault); return -1; } return 0; }
/** * virCPUUpdate: * * @arch: CPU architecture * @guest: guest CPU definition to be updated * @host: host CPU definition * * Updates @guest CPU definition according to @host CPU. This is required to * support guest CPU definitions specified relatively to host CPU, such as * CPUs with VIR_CPU_MODE_CUSTOM and optional features or * VIR_CPU_MATCH_MINIMUM, or CPUs with VIR_CPU_MODE_HOST_MODEL. * When the guest CPU was not specified relatively, the function does nothing * and returns success. * * Returns 0 on success, -1 on error. */ int virCPUUpdate(virArch arch, virCPUDefPtr guest, const virCPUDef *host) { struct cpuArchDriver *driver; VIR_DEBUG("arch=%s, guest=%p mode=%s model=%s, host=%p model=%s", virArchToString(arch), guest, virCPUModeTypeToString(guest->mode), NULLSTR(guest->model), host, NULLSTR(host ? host->model : NULL)); if (!(driver = cpuGetSubDriver(arch))) return -1; if (guest->mode == VIR_CPU_MODE_HOST_PASSTHROUGH) return 0; if (guest->mode == VIR_CPU_MODE_CUSTOM && guest->match != VIR_CPU_MATCH_MINIMUM) { size_t i; bool optional = false; for (i = 0; i < guest->nfeatures; i++) { if (guest->features[i].policy == VIR_CPU_FEATURE_OPTIONAL) { optional = true; break; } } if (!optional) return 0; } /* We get here if guest CPU is either * - host-model * - custom with minimum match * - custom with optional features */ if (!driver->update) { virReportError(VIR_ERR_NO_SUPPORT, _("cannot update guest CPU for %s architecture"), virArchToString(arch)); return -1; } if (driver->update(guest, host) < 0) return -1; VIR_DEBUG("model=%s", NULLSTR(guest->model)); return 0; }
virCPUCompareResult cpuCompareXML(virCPUDefPtr host, const char *xml) { xmlDocPtr doc = NULL; xmlXPathContextPtr ctxt = NULL; virCPUDefPtr cpu = NULL; virCPUCompareResult ret = VIR_CPU_COMPARE_ERROR; VIR_DEBUG("host=%p, xml=%s", host, NULLSTR(xml)); if (!(doc = virXMLParseStringCtxt(xml, _("(CPU_definition)"), &ctxt))) goto cleanup; cpu = virCPUDefParseXML(ctxt->node, ctxt, VIR_CPU_TYPE_AUTO); if (cpu == NULL) goto cleanup; if (!cpu->model) { virCPUReportError(VIR_ERR_OPERATION_INVALID, "%s", _("no CPU model specified")); goto cleanup; } ret = cpuCompare(host, cpu); cleanup: virCPUDefFree(cpu); xmlXPathFreeContext(ctxt); xmlFreeDoc(doc); return ret; }
int qemuTeardownImageCgroup(virDomainObjPtr vm, virStorageSourcePtr src) { qemuDomainObjPrivatePtr priv = vm->privateData; int perms = VIR_CGROUP_DEVICE_READ | VIR_CGROUP_DEVICE_WRITE | VIR_CGROUP_DEVICE_MKNOD; int ret; if (!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_DEVICES)) return 0; if (!src->path || !virStorageSourceIsLocalStorage(src)) { VIR_DEBUG("Not updating cgroups for disk path '%s', type: %s", NULLSTR(src->path), virStorageTypeToString(src->type)); return 0; } VIR_DEBUG("Deny path %s", src->path); ret = virCgroupDenyDevicePath(priv->cgroup, src->path, perms, true); virDomainAuditCgroupPath(vm, priv->cgroup, "deny", src->path, virCgroupGetDevicePermsString(perms), ret == 0); return ret; }
/** * virCPUCompareXML: * * @arch: CPU architecture * @host: host CPU definition * @xml: XML description of either guest or host CPU to be compared with @host * @failIncompatible: return an error instead of VIR_CPU_COMPARE_INCOMPATIBLE * * Compares the CPU described by @xml with @host CPU. * * Returns VIR_CPU_COMPARE_ERROR on error, VIR_CPU_COMPARE_INCOMPATIBLE when * the two CPUs are incompatible, VIR_CPU_COMPARE_IDENTICAL when the two CPUs * are identical, VIR_CPU_COMPARE_SUPERSET when the @xml CPU is a superset of * the @host CPU. If @failIncompatible is true, the function will return * VIR_CPU_COMPARE_ERROR (and set VIR_ERR_CPU_INCOMPATIBLE error) when the * two CPUs are incompatible. */ virCPUCompareResult virCPUCompareXML(virArch arch, virCPUDefPtr host, const char *xml, bool failIncompatible) { xmlDocPtr doc = NULL; xmlXPathContextPtr ctxt = NULL; virCPUDefPtr cpu = NULL; virCPUCompareResult ret = VIR_CPU_COMPARE_ERROR; VIR_DEBUG("arch=%s, host=%p, xml=%s", virArchToString(arch), host, NULLSTR(xml)); if (!xml) { virReportError(VIR_ERR_INVALID_ARG, "%s", _("missing CPU definition")); goto cleanup; } if (!(doc = virXMLParseStringCtxt(xml, _("(CPU_definition)"), &ctxt))) goto cleanup; if (virCPUDefParseXML(ctxt, NULL, VIR_CPU_TYPE_AUTO, &cpu) < 0) goto cleanup; ret = virCPUCompare(arch, host, cpu, failIncompatible); cleanup: virCPUDefFree(cpu); xmlXPathFreeContext(ctxt); xmlFreeDoc(doc); return ret; }
static int testQemuDiskXMLToPropsValidateSchema(const void *opaque) { struct testQemuDiskXMLToJSONData *data = (void *) opaque; virBuffer debug = VIR_BUFFER_INITIALIZER; char *propsstr = NULL; char *debugmsg = NULL; int ret = 0; size_t i; if (data->fail) return EXIT_AM_SKIP; for (i = 0; i < data->nprops; i++) { if (testQEMUSchemaValidate(data->props[i], data->schemaroot, data->schema, &debug) < 0) { debugmsg = virBufferContentAndReset(&debug); propsstr = virJSONValueToString(data->props[i], true); VIR_TEST_VERBOSE("json does not conform to QAPI schema"); VIR_TEST_DEBUG("json:\n%s\ndoes not match schema. Debug output:\n %s", propsstr, NULLSTR(debugmsg)); VIR_FREE(debugmsg); VIR_FREE(propsstr); ret = -1; } virBufferFreeAndReset(&debug); } return ret; }
void do_delchange( CHAR_DATA * ch, char *argument ) { char arg1[MAX_INPUT_LENGTH]; char buf[MSL]; int num; argument = one_argument( argument, arg1 ); if( IS_NPC( ch ) ) return; if( !ch->desc || NULLSTR( arg1 ) || !is_number( arg1 ) ) { send_to_char( "#wFor delchange you must provide a change number.#D\n\r", ch ); send_to_char( "Syntax: delchange (change number)\n\r", ch ); return; } num = atoi( arg1 ); if( num < 0 || num > maxChanges ) { xprintf( buf, "Valid changes are from 0 to %d.\n\r", maxChanges ); send_to_char( buf, ch ); return; } delete_change( num ); send_to_char( "Change deleted.\n\r", ch ); return; }
/** * virNetworkDefineXML: * @conn: pointer to the hypervisor connection * @xml: the XML description for the network, preferably in UTF-8 * * Define an inactive persistent virtual network or modify an existing * persistent one from the XML description. * * virNetworkFree should be used to free the resources after the * network object is no longer needed. * * Returns NULL in case of error, a pointer to the network otherwise */ virNetworkPtr virNetworkDefineXML(virConnectPtr conn, const char *xml) { VIR_DEBUG("conn=%p, xml=%s", conn, NULLSTR(xml)); virResetLastError(); virCheckConnectReturn(conn, NULL); virCheckReadOnlyGoto(conn->flags, error); virCheckNonNullArgGoto(xml, error); if (conn->networkDriver && conn->networkDriver->networkDefineXML) { virNetworkPtr ret; ret = conn->networkDriver->networkDefineXML(conn, xml); if (!ret) goto error; return ret; } virReportUnsupportedError(); error: virDispatchError(conn); return NULL; }
/** * virNetworkGetDHCPLeases: * @network: Pointer to network object * @mac: Optional ASCII formatted MAC address of an interface * @leases: Pointer to a variable to store the array containing details on * obtained leases, or NULL if the list is not required (just returns * number of leases). * @flags: Extra flags, not used yet, so callers should always pass 0 * * For DHCPv4, the information returned: * - Network Interface Name * - Expiry Time * - MAC address * - IAID (NULL) * - IPv4 address (with type and prefix) * - Hostname (can be NULL) * - Client ID (can be NULL) * * For DHCPv6, the information returned: * - Network Interface Name * - Expiry Time * - MAC address * - IAID (can be NULL, only in rare cases) * - IPv6 address (with type and prefix) * - Hostname (can be NULL) * - Client DUID * * Note: @mac, @iaid, @ipaddr, @clientid are in ASCII form, not raw bytes. * Note: @expirytime can 0, in case the lease is for infinite time. * * The API fetches leases info of guests in the specified network. If the * optional parameter @mac is specified, the returned list will contain only * lease info about a specific guest interface with @mac. There can be * multiple leases for a single @mac because this API supports DHCPv6 too. * * Returns the number of leases found or -1 and sets @leases to NULL in * case of error. On success, the array stored into @leases is guaranteed to * have an extra allocated element set to NULL but not included in the return * count, to make iteration easier. The caller is responsible for calling * virNetworkDHCPLeaseFree() on each array element, then calling free() on @leases. * * See also virNetworkGetDHCPLeasesForMAC() as a convenience for filtering * the list to a single MAC address. * * Example of usage: * * virNetworkDHCPLeasePtr *leases = NULL; * virNetworkPtr network = ... obtain a network pointer here ...; * size_t i; * int nleases; * unsigned int flags = 0; * * nleases = virNetworkGetDHCPLeases(network, NULL, &leases, flags); * if (nleases < 0) * error(); * * ... do something with returned values, for example: * * for (i = 0; i < nleases; i++) { * virNetworkDHCPLeasePtr lease = leases[i]; * * printf("Time(epoch): %lu, MAC address: %s, " * "IP address: %s, Hostname: %s, ClientID: %s\n", * lease->expirytime, lease->mac, lease->ipaddr, * lease->hostname, lease->clientid); * * virNetworkDHCPLeaseFree(leases[i]); * } * * free(leases); * */ int virNetworkGetDHCPLeases(virNetworkPtr network, const char *mac, virNetworkDHCPLeasePtr **leases, unsigned int flags) { virConnectPtr conn; VIR_DEBUG("network=%p, mac='%s' leases=%p, flags=0x%x", network, NULLSTR(mac), leases, flags); virResetLastError(); if (leases) *leases = NULL; virCheckNetworkReturn(network, -1); conn = network->conn; if (conn->networkDriver && conn->networkDriver->networkGetDHCPLeases) { int ret; ret = conn->networkDriver->networkGetDHCPLeases(network, mac, leases, flags); if (ret < 0) goto error; return ret; } virReportUnsupportedError(); error: virDispatchError(network->conn); return -1; }
/** * virNWFilterBindingCreateXML: * @conn: pointer to the hypervisor connection * @xml: an XML description of the binding * @flags: currently unused, pass 0 * * Define a new network filter, based on an XML description * similar to the one returned by virNWFilterGetXMLDesc(). This * API may be used to associate a filter with a currently running * guest that does not have a filter defined for a specific network * port. Since the bindings are generally automatically managed by * the hypervisor, using this command to define a filter for a network * port and then starting the guest afterwards may prevent the guest * from starting if it attempts to use the network port and finds a * filter already defined. * * virNWFilterFree should be used to free the resources after the * binding object is no longer needed. * * Returns a new binding object or NULL in case of failure */ virNWFilterBindingPtr virNWFilterBindingCreateXML(virConnectPtr conn, const char *xml, unsigned int flags) { VIR_DEBUG("conn=%p, xml=%s", conn, NULLSTR(xml)); virResetLastError(); virCheckConnectReturn(conn, NULL); virCheckNonNullArgGoto(xml, error); virCheckReadOnlyGoto(conn->flags, error); if (conn->nwfilterDriver && conn->nwfilterDriver->nwfilterBindingCreateXML) { virNWFilterBindingPtr ret; ret = conn->nwfilterDriver->nwfilterBindingCreateXML(conn, xml, flags); if (!ret) goto error; return ret; } virReportUnsupportedError(); error: virDispatchError(conn); return NULL; }
/** * virConfReadFile: * @filename: the path to the configuration file. * @flags: combination of virConfFlag(s) * * Reads a configuration file. * * Returns a handle to lookup settings or NULL if it failed to * read or parse the file, use virConfFree() to free the data. */ virConfPtr virConfReadFile(const char *filename, unsigned int flags) { char *content; int len; virConfPtr conf = NULL; VIR_DEBUG("filename=%s", NULLSTR(filename)); if (filename == NULL) { virConfError(NULL, VIR_ERR_INVALID_ARG, __FUNCTION__); return NULL; } if ((len = virFileReadAll(filename, MAX_CONFIG_FILE_SIZE, &content)) < 0) return NULL; if (len && len < MAX_CONFIG_FILE_SIZE && content[len - 1] != '\n') { VIR_DEBUG("appending newline to busted config file %s", filename); if (VIR_REALLOC_N(content, len + 1) < 0) goto cleanup; content[len++] = '\n'; content[len] = '\0'; } conf = virConfParse(filename, content, len, flags); cleanup: VIR_FREE(content); return conf; }
int cpuEncode(const char *arch, const virCPUDefPtr cpu, union cpuData **forced, union cpuData **required, union cpuData **optional, union cpuData **disabled, union cpuData **forbidden, union cpuData **vendor) { struct cpuArchDriver *driver; VIR_DEBUG("arch=%s, cpu=%p, forced=%p, required=%p, " "optional=%p, disabled=%p, forbidden=%p, vendor=%p", NULLSTR(arch), cpu, forced, required, optional, disabled, forbidden, vendor); if ((driver = cpuGetSubDriver(arch)) == NULL) return -1; if (driver->encode == NULL) { virCPUReportError(VIR_ERR_NO_SUPPORT, _("cannot encode CPU data for %s architecture"), arch); return -1; } return driver->encode(cpu, forced, required, optional, disabled, forbidden, vendor); }
/** * cpuCompareXML: * * @host: host CPU definition * @xml: XML description of either guest or host CPU to be compared with @host * * Compares the CPU described by @xml with @host CPU. * * Returns VIR_CPU_COMPARE_ERROR on error, VIR_CPU_COMPARE_INCOMPATIBLE when * the two CPUs are incompatible, VIR_CPU_COMPARE_IDENTICAL when the two CPUs * are identical, VIR_CPU_COMPARE_SUPERSET when the @xml CPU is a superset of * the @host CPU. */ virCPUCompareResult cpuCompareXML(virCPUDefPtr host, const char *xml, bool failIncompatible) { xmlDocPtr doc = NULL; xmlXPathContextPtr ctxt = NULL; virCPUDefPtr cpu = NULL; virCPUCompareResult ret = VIR_CPU_COMPARE_ERROR; VIR_DEBUG("host=%p, xml=%s", host, NULLSTR(xml)); if (!(doc = virXMLParseStringCtxt(xml, _("(CPU_definition)"), &ctxt))) goto cleanup; cpu = virCPUDefParseXML(ctxt->node, ctxt, VIR_CPU_TYPE_AUTO); if (cpu == NULL) goto cleanup; ret = cpuCompare(host, cpu, failIncompatible); cleanup: virCPUDefFree(cpu); xmlXPathFreeContext(ctxt); xmlFreeDoc(doc); return ret; }
FUNCTION VOID z_exit ( FUNINT sfi, /* in: value for $sfi */ TEXT *skey /* in: value for $sky */ ) { #define ALDIM(bytes) 1+((bytes-1)/sizeof (ALIGN)) #define HEAD_SIZ (sizeof(struct PARBLK) - P_BYTES + 8) /* 8 for align safety*/ #define ZBLKDIM (3*sizeof(struct VARIABLE) + 2*STRINGSIZ + HEAD_SIZ) /* block dimension */ IMPORT TEXT savekey[]; /* key for last message */ TEXT *keyptr[1]; /* pointer to key string */ TAEINT sfival[1]; ALIGN block[ALDIM(ZBLKDIM)]; /* parameter block to send */ struct PARBLK *termblk; /* pointer to parameter block*/ CODE code; keyptr[0] = skey; /* assume key present */ if (NULLSTR(skey)) keyptr[0] = savekey; /* else, give old key */ sfival[0] = sfi; termblk = (struct PARBLK *)block; /* cast pointer */ q_init(termblk, ZBLKDIM - HEAD_SIZ, P_ABORT); /* initialize the block*/ q_intg(termblk, "$SFI", 1, sfival, P_ADD); /* put sfi in block */ q_string(termblk, "$SKEY", 1, keyptr, P_ADD); /* put skey in block */ code = q_out(termblk); /* send block to tm */ procexit(code); return; }
/* As per: http://www.freedesktop.org/wiki/Software/systemd/inhibit */ static void virNetDaemonCallInhibit(virNetDaemonPtr dmn, const char *what, const char *who, const char *why, const char *mode) { DBusMessage *message; DBusPendingCall *pendingReply; DBusConnection *systemBus; VIR_DEBUG("dmn=%p what=%s who=%s why=%s mode=%s", dmn, NULLSTR(what), NULLSTR(who), NULLSTR(why), NULLSTR(mode)); if (!(systemBus = virDBusGetSystemBus())) return; /* Only one outstanding call at a time */ if (dmn->autoShutdownCallingInhibit) return; message = dbus_message_new_method_call("org.freedesktop.login1", "/org/freedesktop/login1", "org.freedesktop.login1.Manager", "Inhibit"); if (message == NULL) return; dbus_message_append_args(message, DBUS_TYPE_STRING, &what, DBUS_TYPE_STRING, &who, DBUS_TYPE_STRING, &why, DBUS_TYPE_STRING, &mode, DBUS_TYPE_INVALID); pendingReply = NULL; if (dbus_connection_send_with_reply(systemBus, message, &pendingReply, 25*1000)) { dbus_pending_call_set_notify(pendingReply, virNetDaemonGotInhibitReply, dmn, NULL); dmn->autoShutdownCallingInhibit = true; } dbus_message_unref(message); }
virSecurityDriverPtr virSecurityDriverLookup(const char *name, const char *virtDriver) { virSecurityDriverPtr drv = NULL; size_t i; VIR_DEBUG("name=%s", NULLSTR(name)); for (i = 0; i < ARRAY_CARDINALITY(security_drivers) && !drv; i++) { virSecurityDriverPtr tmp = security_drivers[i]; if (name && STRNEQ(tmp->name, name)) continue; switch (tmp->probe(virtDriver)) { case SECURITY_DRIVER_ENABLE: VIR_DEBUG("Probed name=%s", tmp->name); drv = tmp; break; case SECURITY_DRIVER_DISABLE: VIR_DEBUG("Not enabled name=%s", tmp->name); if (name && STREQ(tmp->name, name)) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Security driver %s not enabled"), name); return NULL; } break; case SECURITY_DRIVER_ERROR: default: return NULL; } } if (!drv) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Security driver %s not found"), NULLSTR(name)); return NULL; } return drv; }
int qemuTeardownImageCgroup(virDomainObjPtr vm, virStorageSourcePtr src) { qemuDomainObjPrivatePtr priv = vm->privateData; int perms = VIR_CGROUP_DEVICE_RWM; size_t i; int ret; if (!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_DEVICES)) return 0; if (!src->path || !virStorageSourceIsLocalStorage(src)) { VIR_DEBUG("Not updating cgroups for disk path '%s', type: %s", NULLSTR(src->path), virStorageTypeToString(src->type)); return 0; } if (virFileExists(DEVICE_MAPPER_CONTROL_PATH)) { for (i = 0; i < vm->def->ndisks; i++) { virStorageSourcePtr diskSrc = vm->def->disks[i]->src; if (src == diskSrc) continue; if (virStoragePRDefIsManaged(diskSrc->pr)) break; } if (i == vm->def->ndisks) { VIR_DEBUG("Disabling device mapper control"); ret = virCgroupDenyDevicePath(priv->cgroup, DEVICE_MAPPER_CONTROL_PATH, perms, true); virDomainAuditCgroupPath(vm, priv->cgroup, "deny", DEVICE_MAPPER_CONTROL_PATH, virCgroupGetDevicePermsString(perms), ret); if (ret < 0) return ret; } } VIR_DEBUG("Deny path %s", src->path); ret = virCgroupDenyDevicePath(priv->cgroup, src->path, perms, true); virDomainAuditCgroupPath(vm, priv->cgroup, "deny", src->path, virCgroupGetDevicePermsString(perms), ret); /* If you're looking for a counter part to * qemuSetupImagePathCgroup you're at the right place. * However, we can't just blindly deny all the device mapper * targets of src->path because they might still be used by * another disk in domain. Just like we are not removing * disks from namespace. */ return ret; }
static int testVirNetDevBandwidthSet(const void *data) { int ret = -1; const struct testSetStruct *info = data; const char *iface = info->iface; virNetDevBandwidthPtr band = NULL; virBuffer buf = VIR_BUFFER_INITIALIZER; char *actual_cmd = NULL; PARSE(info->band, band); if (!iface) iface = "eth0"; virCommandSetDryRun(&buf, NULL, NULL); if (virNetDevBandwidthSet(iface, band, info->hierarchical_class) < 0) goto cleanup; if (!(actual_cmd = virBufferContentAndReset(&buf))) { int err = virBufferError(&buf); if (err) { fprintf(stderr, "buffer's in error state: %d", err); goto cleanup; } /* This is interesting, no command has been executed. * Maybe that's expected, actually. */ } if (STRNEQ_NULLABLE(info->exp_cmd, actual_cmd)) { virTestDifference(stderr, NULLSTR(info->exp_cmd), NULLSTR(actual_cmd)); goto cleanup; } ret = 0; cleanup: virCommandSetDryRun(NULL, NULL, NULL); virNetDevBandwidthFree(band); virBufferFreeAndReset(&buf); VIR_FREE(actual_cmd); return ret; }
int virNetClientStreamSetError(virNetClientStreamPtr st, virNetMessagePtr msg) { virNetMessageError err; int ret = -1; virObjectLock(st); if (st->err.code != VIR_ERR_OK) VIR_DEBUG("Overwriting existing stream error %s", NULLSTR(st->err.message)); virResetError(&st->err); memset(&err, 0, sizeof(err)); if (virNetMessageDecodePayload(msg, (xdrproc_t)xdr_virNetMessageError, &err) < 0) goto cleanup; if (err.domain == VIR_FROM_REMOTE && err.code == VIR_ERR_RPC && err.level == VIR_ERR_ERROR && err.message && STRPREFIX(*err.message, "unknown procedure")) { st->err.code = VIR_ERR_NO_SUPPORT; } else { st->err.code = err.code; } if (err.message) { st->err.message = *err.message; *err.message = NULL; } st->err.domain = err.domain; st->err.level = err.level; if (err.str1) { st->err.str1 = *err.str1; *err.str1 = NULL; } if (err.str2) { st->err.str2 = *err.str2; *err.str2 = NULL; } if (err.str3) { st->err.str3 = *err.str3; *err.str3 = NULL; } st->err.int1 = err.int1; st->err.int2 = err.int2; st->incomingEOF = true; virNetClientStreamEventTimerUpdate(st); ret = 0; cleanup: xdr_free((xdrproc_t)xdr_virNetMessageError, (void*)&err); virObjectUnlock(st); return ret; }
static char * getSocketPath(virURIPtr uri) { char *rundir = virGetUserRuntimeDirectory(); char *sock_path = NULL; size_t i = 0; if (!uri) goto cleanup; for (i = 0; i < uri->paramsCount; i++) { virURIParamPtr param = &uri->params[i]; if (STREQ(param->name, "socket")) { VIR_FREE(sock_path); if (VIR_STRDUP(sock_path, param->value) < 0) goto error; } else { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Unknown URI parameter '%s'"), param->name); goto error; } } if (!sock_path) { if (STRNEQ_NULLABLE(uri->scheme, "libvirtd")) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Unsupported URI scheme '%s'"), NULLSTR(uri->scheme)); goto error; } if (STREQ_NULLABLE(uri->path, "/system")) { if (VIR_STRDUP(sock_path, LIBVIRTD_ADMIN_UNIX_SOCKET) < 0) goto error; } else if (STREQ_NULLABLE(uri->path, "/session")) { if (!rundir || virAsprintf(&sock_path, "%s%s", rundir, LIBVIRTD_ADMIN_SOCK_NAME) < 0) goto error; } else { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Invalid URI path '%s', try '/system'"), uri->path ? uri->path : ""); goto error; } } cleanup: VIR_FREE(rundir); return sock_path; error: VIR_FREE(sock_path); goto cleanup; }
static int qemuAgentCheckError(virJSONValuePtr cmd, virJSONValuePtr reply) { if (virJSONValueObjectHasKey(reply, "error")) { virJSONValuePtr error = virJSONValueObjectGet(reply, "error"); char *cmdstr = virJSONValueToString(cmd, false); char *replystr = virJSONValueToString(reply, false); /* Log the full JSON formatted command & error */ VIR_DEBUG("unable to execute QEMU agent command %s: %s", NULLSTR(cmdstr), NULLSTR(replystr)); /* Only send the user the command name + friendly error */ if (!error) virReportError(VIR_ERR_INTERNAL_ERROR, _("unable to execute QEMU agent command '%s'"), qemuAgentCommandName(cmd)); else virReportError(VIR_ERR_INTERNAL_ERROR, _("unable to execute QEMU agent command '%s': %s"), qemuAgentCommandName(cmd), qemuAgentStringifyError(error)); VIR_FREE(cmdstr); VIR_FREE(replystr); return -1; } else if (!virJSONValueObjectHasKey(reply, "return")) { char *cmdstr = virJSONValueToString(cmd, false); char *replystr = virJSONValueToString(reply, false); VIR_DEBUG("Neither 'return' nor 'error' is set in the JSON reply %s: %s", NULLSTR(cmdstr), NULLSTR(replystr)); virReportError(VIR_ERR_INTERNAL_ERROR, _("unable to execute QEMU agent command '%s'"), qemuAgentCommandName(cmd)); VIR_FREE(cmdstr); VIR_FREE(replystr); return -1; } return 0; }
/** * cpuDecode: * * @cpu: CPU definition stub to be filled in * @data: internal CPU data to be decoded into @cpu definition * @models: list of CPU models that can be considered when decoding @data * @nmodels: number of CPU models in @models * @preferred: CPU models that should be used if possible * * Decodes internal CPU data into a CPU definition consisting of a CPU model * and a list of CPU features. The @cpu model stub is supposed to have arch, * type, match and fallback members set, this function will add the rest. If * @models list is NULL, all models supported by libvirt will be considered * when decoding the data. In general, this function will select the model * closest to the CPU specified by @data unless @preferred is non-NULL, in * which case the @preferred model will be used as long as it is compatible * with @data. * * For VIR_ARCH_I686 and VIR_ARCH_X86_64 architectures this means the computed * CPU definition will have the shortest possible list of additional features. * When @preferred is non-NULL, the @preferred model will be used even if * other models would result in a shorter list of additional features. * * Returns 0 on success, -1 on error. */ int cpuDecode(virCPUDefPtr cpu, const virCPUData *data, const char **models, unsigned int nmodels, const char *preferred) { struct cpuArchDriver *driver; VIR_DEBUG("cpu=%p, data=%p, nmodels=%u, preferred=%s", cpu, data, nmodels, NULLSTR(preferred)); if (models) { size_t i; for (i = 0; i < nmodels; i++) VIR_DEBUG("models[%zu]=%s", i, NULLSTR(models[i])); } if (models == NULL && nmodels != 0) { virReportError(VIR_ERR_INVALID_ARG, "%s", _("nonzero nmodels doesn't match with NULL models")); return -1; } if (cpu->type > VIR_CPU_TYPE_GUEST || cpu->mode != VIR_CPU_MODE_CUSTOM) { virReportError(VIR_ERR_INVALID_ARG, "%s", _("invalid CPU definition stub")); return -1; } if ((driver = cpuGetSubDriver(cpu->arch)) == NULL) return -1; if (driver->decode == NULL) { virReportError(VIR_ERR_NO_SUPPORT, _("cannot decode CPU data for %s architecture"), virArchToString(cpu->arch)); return -1; } return driver->decode(cpu, data, models, nmodels, preferred, 0); }
int cpuDecode(virCPUDefPtr cpu, const union cpuData *data, const char **models, unsigned int nmodels, const char *preferred) { struct cpuArchDriver *driver; VIR_DEBUG("cpu=%p, data=%p, nmodels=%u, preferred=%s", cpu, data, nmodels, NULLSTR(preferred)); if (models) { unsigned int i; for (i = 0; i < nmodels; i++) VIR_DEBUG("models[%u]=%s", i, NULLSTR(models[i])); } if (models == NULL && nmodels != 0) { virCPUReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("nonzero nmodels doesn't match with NULL models")); return -1; } if (cpu == NULL) { virCPUReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("invalid CPU definition")); return -1; } if ((driver = cpuGetSubDriver(cpu->arch)) == NULL) return -1; if (driver->decode == NULL) { virCPUReportError(VIR_ERR_NO_SUPPORT, _("cannot decode CPU data for %s architecture"), cpu->arch); return -1; } return driver->decode(cpu, data, models, nmodels, preferred); }
/** * qemuBlockJobSyncBegin: * @job: block job data * @disk: domain disk * * Begin a new synchronous block job for @disk. The synchronous * block job is ended by a call to qemuBlockJobSyncEnd, or by * the guest quitting. * * During a synchronous block job, a block job event for @disk * will not be processed asynchronously. Instead, it will be * processed only when qemuBlockJobUpdate or qemuBlockJobSyncEnd * is called. */ void qemuBlockJobSyncBegin(qemuBlockJobDataPtr job) { const char *diskdst = NULL; if (job->disk) diskdst = job->disk->dst; VIR_DEBUG("disk=%s", NULLSTR(diskdst)); job->synchronous = true; job->newstate = -1; }
/* * Wait for the async command to complete. * Return -1 on any error waiting for * completion. Returns 0 if the command * finished with the exit status set */ int virCommandWait(virCommandPtr cmd, int *exitstatus) { int ret; int status; if (!cmd ||cmd->has_error == ENOMEM) { virReportOOMError(); return -1; } if (cmd->has_error) { virCommandError(VIR_ERR_INTERNAL_ERROR, "%s", _("invalid use of command API")); return -1; } if (cmd->pid == -1) { virCommandError(VIR_ERR_INTERNAL_ERROR, "%s", _("command is not yet running")); return -1; } /* Wait for intermediate process to exit */ while ((ret = waitpid(cmd->pid, &status, 0)) == -1 && errno == EINTR); if (ret == -1) { virReportSystemError(errno, _("unable to wait for process %d"), cmd->pid); return -1; } cmd->pid = -1; cmd->reap = false; if (exitstatus == NULL) { if (status != 0) { char *str = virCommandToString(cmd); char *st = virCommandTranslateStatus(status); virCommandError(VIR_ERR_INTERNAL_ERROR, _("Child process (%s) status unexpected: %s"), str ? str : cmd->args[0], NULLSTR(st)); VIR_FREE(str); VIR_FREE(st); return -1; } } else { *exitstatus = status; } return 0; }