/** * virNetDevBandwidthClear: * @ifname: on which interface * * This function tries to disable QoS on specified interface * by deleting root and ingress qdisc. However, this may fail * if we try to remove the default one. * * Return 0 on success, -1 otherwise. */ int virNetDevBandwidthClear(const char *ifname) { int ret = 0; int dummy; /* for ignoring the exit status */ virCommandPtr cmd = NULL; cmd = virCommandNew(TC); virCommandAddArgList(cmd, "qdisc", "del", "dev", ifname, "root", NULL); if (virCommandRun(cmd, &dummy) < 0) ret = -1; virCommandFree(cmd); cmd = virCommandNew(TC); virCommandAddArgList(cmd, "qdisc", "del", "dev", ifname, "ingress", NULL); if (virCommandRun(cmd, &dummy) < 0) ret = -1; virCommandFree(cmd); return ret; }
static virCommandPtr iptablesCommandNew(const char *table, const char *chain, int family, int action) { virCommandPtr cmd = NULL; virIpTablesInitialize(); #if HAVE_FIREWALLD if (firewall_cmd_path) { cmd = virCommandNew(firewall_cmd_path); virCommandAddArgList(cmd, "--direct", "--passthrough", (family == AF_INET6) ? "ipv6" : "ipv4", NULL); } #endif if (cmd == NULL) { cmd = virCommandNew((family == AF_INET6) ? IP6TABLES_PATH : IPTABLES_PATH); if (iptables_supports_xlock) virCommandAddArgList(cmd, "-w", NULL); } virCommandAddArgList(cmd, "--table", table, action == ADD ? "--insert" : "--delete", chain, NULL); return cmd; }
/* Allow all traffic coming from the bridge, with a valid network address * to proceed to WAN */ static int iptablesForwardAllowOut(iptablesContext *ctx, virSocketAddr *netaddr, unsigned int prefix, const char *iface, const char *physdev, int action) { int ret; char *networkstr; virCommandPtr cmd = NULL; if (!(networkstr = iptablesFormatNetwork(netaddr, prefix))) return -1; cmd = iptablesCommandNew(ctx->forward_filter, VIR_SOCKET_ADDR_FAMILY(netaddr), action); virCommandAddArgList(cmd, "--source", networkstr, "--in-interface", iface, NULL); if (physdev && physdev[0]) virCommandAddArgList(cmd, "--out-interface", physdev, NULL); virCommandAddArgList(cmd, "--jump", "ACCEPT", NULL); ret = iptablesCommandRunAndFree(cmd); VIR_FREE(networkstr); return ret; }
/* Don't masquerade traffic coming from the network associated with the bridge * if said traffic targets @destaddr. */ static int iptablesForwardDontMasquerade(virSocketAddr *netaddr, unsigned int prefix, const char *physdev, const char *destaddr, int action) { int ret = -1; char *networkstr = NULL; virCommandPtr cmd = NULL; if (!(networkstr = iptablesFormatNetwork(netaddr, prefix))) return -1; if (!VIR_SOCKET_ADDR_IS_FAMILY(netaddr, AF_INET)) { /* Higher level code *should* guaranteee it's impossible to get here. */ virReportError(VIR_ERR_INTERNAL_ERROR, _("Attempted to NAT '%s'. NAT is only supported for IPv4."), networkstr); goto cleanup; } cmd = iptablesCommandNew("nat", "POSTROUTING", AF_INET, action); if (physdev && physdev[0]) virCommandAddArgList(cmd, "--out-interface", physdev, NULL); virCommandAddArgList(cmd, "--source", networkstr, "--destination", destaddr, "--jump", "RETURN", NULL); ret = virCommandRun(cmd, NULL); cleanup: virCommandFree(cmd); VIR_FREE(networkstr); return ret; }
/* * virNetDevBandwidthUnplug: * @brname: from which bridge are we unplugging * @id: unique identifier (MUST be greater than 2) * * Remove QoS settings from bridge. * * Returns 0 on success, -1 otherwise. */ int virNetDevBandwidthUnplug(const char *brname, unsigned int id) { int ret = -1; int cmd_ret = 0; virCommandPtr cmd = NULL; char *class_id = NULL; char *qdisc_id = NULL; char *filter_id = NULL; if (id <= 2) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Invalid class ID %d"), id); return -1; } if (virAsprintf(&class_id, "1:%x", id) < 0 || virAsprintf(&qdisc_id, "%x:", id) < 0 || virAsprintf(&filter_id, "%u", id) < 0) { virReportOOMError(); goto cleanup; } cmd = virCommandNew(TC); virCommandAddArgList(cmd, "qdisc", "del", "dev", brname, "handle", qdisc_id, NULL); /* Don't threat tc errors as fatal, but * try to remove as much as possible */ if (virCommandRun(cmd, &cmd_ret) < 0) goto cleanup; virCommandFree(cmd); cmd = virCommandNew(TC); virCommandAddArgList(cmd, "filter", "del", "dev", brname, "prio", filter_id, NULL); if (virCommandRun(cmd, &cmd_ret) < 0) goto cleanup; cmd = virCommandNew(TC); virCommandAddArgList(cmd, "class", "del", "dev", brname, "classid", class_id, NULL); if (virCommandRun(cmd, &cmd_ret) < 0) goto cleanup; ret = 0; cleanup: VIR_FREE(filter_id); VIR_FREE(qdisc_id); VIR_FREE(class_id); virCommandFree(cmd); return ret; }
int libxlDomainGetEmulatorType(const virDomainDef *def) { int ret = LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN; virCommandPtr cmd = NULL; char *output = NULL; if (def->os.type == VIR_DOMAIN_OSTYPE_HVM) { if (def->emulator) { if (!virFileExists(def->emulator)) goto cleanup; cmd = virCommandNew(def->emulator); virCommandAddArgList(cmd, "-help", NULL); virCommandSetOutputBuffer(cmd, &output); if (virCommandRun(cmd, NULL) < 0) goto cleanup; if (strstr(output, LIBXL_QEMU_DM_STR)) ret = LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN_TRADITIONAL; } } cleanup: VIR_FREE(output); virCommandFree(cmd); return ret; }
/** * virNetDevMidonetBindPort: * @ifname: the network interface name * @virtualport: the midonet specific fields * * Bind an interface to a Midonet virtual port * * Returns 0 in case of success or -1 in case of failure. */ int virNetDevMidonetBindPort(const char *ifname, virNetDevVPortProfilePtr virtualport) { int ret = -1; virCommandPtr cmd = NULL; char virtportuuid[VIR_UUID_STRING_BUFLEN]; virUUIDFormat(virtualport->interfaceID, virtportuuid); cmd = virCommandNew(MMCTL); virCommandAddArgList(cmd, "--bind-port", virtportuuid, ifname, NULL); if (virCommandRun(cmd, NULL) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Unable to bind port %s to the virtual port %s"), ifname, virtportuuid); goto cleanup; } ret = 0; cleanup: virCommandFree(cmd); return ret; }
/** * virNetDevBandwidthUpdateRate: * @ifname: interface name * @classid: ID of class to update * @new_rate: new rate * * This function updates the 'rate' attribute of HTB class. * It can be used whenever a new interface is plugged to a * bridge to adjust average throughput of non guaranteed * NICs. * * Returns 0 on success, -1 otherwise. */ int virNetDevBandwidthUpdateRate(const char *ifname, const char *class_id, virNetDevBandwidthPtr bandwidth, unsigned long long new_rate) { int ret = -1; virCommandPtr cmd = NULL; char *rate = NULL; char *ceil = NULL; if (virAsprintf(&rate, "%llukbps", new_rate) < 0 || virAsprintf(&ceil, "%llukbps", bandwidth->in->peak ? bandwidth->in->peak : bandwidth->in->average) < 0) { virReportOOMError(); goto cleanup; } cmd = virCommandNew(TC); virCommandAddArgList(cmd, "class", "change", "dev", ifname, "classid", class_id, "htb", "rate", rate, "ceil", ceil, NULL); if (virCommandRun(cmd, NULL) < 0) goto cleanup; ret = 0; cleanup: virCommandFree(cmd); VIR_FREE(rate); VIR_FREE(ceil); return ret; }
static int bhyveBuildConsoleArgStr(const virDomainDef *def, virCommandPtr cmd) { virDomainChrDefPtr chr = NULL; if (!def->nserials) return 0; chr = def->serials[0]; if (chr->source.type != VIR_DOMAIN_CHR_TYPE_NMDM) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("only nmdm console types are supported")); return -1; } /* bhyve supports only two ports: com1 and com2 */ if (chr->target.port > 2) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("only two serial ports are supported")); return -1; } virCommandAddArgList(cmd, "-s", "1,lpc", NULL); virCommandAddArg(cmd, "-l"); virCommandAddArgFormat(cmd, "com%d,%s", chr->target.port + 1, chr->source.data.file.path); return 0; }
virCommandPtr virBhyveProcessBuildBhyveCmd(bhyveConnPtr driver ATTRIBUTE_UNUSED, virDomainObjPtr vm) { /* * /usr/sbin/bhyve -c 2 -m 256 -AI -H -P \ * -s 0:0,hostbridge \ * -s 1:0,virtio-net,tap0 \ * -s 2:0,ahci-hd,${IMG} \ * -S 31,uart,stdio \ * vm0 */ virCommandPtr cmd = virCommandNew(BHYVE); /* CPUs */ virCommandAddArg(cmd, "-c"); virCommandAddArgFormat(cmd, "%d", vm->def->vcpus); /* Memory */ virCommandAddArg(cmd, "-m"); virCommandAddArgFormat(cmd, "%llu", VIR_DIV_UP(vm->def->mem.max_balloon, 1024)); /* Options */ if (vm->def->features[VIR_DOMAIN_FEATURE_ACPI] == VIR_DOMAIN_FEATURE_STATE_ON) virCommandAddArg(cmd, "-A"); /* Create an ACPI table */ if (vm->def->features[VIR_DOMAIN_FEATURE_APIC] == VIR_DOMAIN_FEATURE_STATE_ON) virCommandAddArg(cmd, "-I"); /* Present ioapic to the guest */ /* Clarification about -H and -P flags from Peter Grehan: * -H and -P flags force the guest to exit when it executes IA32 HLT and PAUSE * instructions respectively. * * For the HLT exit, bhyve uses that to infer that the guest is idling and can * be put to sleep until an external event arrives. If this option is not used, * the guest will always use 100% of CPU on the host. * * The PAUSE exit is most useful when there are large numbers of guest VMs running, * since it forces the guest to exit when it spins on a lock acquisition. */ virCommandAddArg(cmd, "-H"); /* vmexit from guest on hlt */ virCommandAddArg(cmd, "-P"); /* vmexit from guest on pause */ virCommandAddArgList(cmd, "-s", "0:0,hostbridge", NULL); /* Devices */ if (bhyveBuildNetArgStr(vm->def, cmd) < 0) goto error; if (bhyveBuildDiskArgStr(vm->def, cmd) < 0) goto error; if (bhyveBuildConsoleArgStr(vm->def, cmd) < 0) goto error; virCommandAddArg(cmd, vm->def->name); return cmd; error: virCommandFree(cmd); return NULL; }
static int virISCSIConnection(const char *portal, const char *initiatoriqn, const char *target, const char **extraargv) { int ret = -1; const char *const baseargv[] = { ISCSIADM, "--mode", "node", "--portal", portal, "--targetname", target, NULL }; virCommandPtr cmd; char *ifacename = NULL; cmd = virCommandNewArgs(baseargv); virCommandAddArgSet(cmd, extraargv); if (initiatoriqn) { switch (virStorageBackendIQNFound(initiatoriqn, &ifacename)) { case IQN_FOUND: VIR_DEBUG("ifacename: '%s'", ifacename); break; case IQN_MISSING: if (virStorageBackendCreateIfaceIQN(initiatoriqn, &ifacename) != 0) goto cleanup; /* * iscsiadm doesn't let you send commands to the Interface IQN, * unless you've first issued a 'sendtargets' command to the * portal. Without the sendtargets all that is received is a * "iscsiadm: No records found" */ if (virISCSIScanTargets(portal, NULL, NULL) < 0) goto cleanup; break; case IQN_ERROR: default: goto cleanup; } virCommandAddArgList(cmd, "--interface", ifacename, NULL); } if (virCommandRun(cmd, NULL) < 0) goto cleanup; ret = 0; cleanup: virCommandFree(cmd); VIR_FREE(ifacename); return ret; }
static int virIpTablesOnceInit(void) { virCommandPtr cmd; int status; #if HAVE_FIREWALLD firewall_cmd_path = virFindFileInPath("firewall-cmd"); if (!firewall_cmd_path) { VIR_INFO("firewall-cmd not found on system. " "firewalld support disabled for iptables."); } else { cmd = virCommandNew(firewall_cmd_path); virCommandAddArgList(cmd, "--state", NULL); /* don't log non-zero status */ if (virCommandRun(cmd, &status) < 0 || status != 0) { VIR_INFO("firewall-cmd found but disabled for iptables"); VIR_FREE(firewall_cmd_path); firewall_cmd_path = NULL; } else { VIR_INFO("using firewalld for iptables commands"); } virCommandFree(cmd); } if (firewall_cmd_path) return 0; #endif cmd = virCommandNew(IPTABLES_PATH); virCommandAddArgList(cmd, "-w", "-L", "-n", NULL); /* don't log non-zero status */ if (virCommandRun(cmd, &status) < 0 || status != 0) { VIR_INFO("xtables locking not supported by your iptables"); } else { VIR_INFO("using xtables locking for iptables"); iptables_supports_xlock = true; } virCommandFree(cmd); return 0; }
/* * load (add) a profile. Will create one if necessary */ static int load_profile(virSecurityManagerPtr mgr, const char *profile, virDomainDefPtr def, const char *fn, bool append) { int rc = -1; bool create = true; char *xml = NULL; virCommandPtr cmd = NULL; const char *probe = virSecurityManagerGetAllowDiskFormatProbing(mgr) ? "1" : "0"; xml = virDomainDefFormat(def, VIR_DOMAIN_XML_SECURE); if (!xml) goto cleanup; if (profile_status_file(profile) >= 0) create = false; cmd = virCommandNewArgList(VIRT_AA_HELPER, "-p", probe, create ? "-c" : "-r", "-u", profile, NULL); if (!create && fn) { if (append) { virCommandAddArgList(cmd, "-F", fn, NULL); } else { virCommandAddArgList(cmd, "-f", fn, NULL); } } virCommandSetInputBuffer(cmd, xml); rc = virCommandRun(cmd, NULL); cleanup: VIR_FREE(xml); virCommandFree(cmd); return rc; }
static int virStorageBackendISCSIConnection(const char *portal, const char *initiatoriqn, const char *target, const char **extraargv) { int ret = -1; const char *const baseargv[] = { ISCSIADM, "--mode", "node", "--portal", portal, "--targetname", target, NULL }; virCommandPtr cmd; char *ifacename = NULL; cmd = virCommandNewArgs(baseargv); virCommandAddArgSet(cmd, extraargv); if (initiatoriqn) { switch (virStorageBackendIQNFound(initiatoriqn, &ifacename)) { case IQN_FOUND: VIR_DEBUG("ifacename: '%s'", ifacename); break; case IQN_MISSING: if (virStorageBackendCreateIfaceIQN(initiatoriqn, &ifacename) != 0) { goto cleanup; } break; case IQN_ERROR: default: goto cleanup; } virCommandAddArgList(cmd, "--interface", ifacename, NULL); } if (virCommandRun(cmd, NULL) < 0) goto cleanup; ret = 0; cleanup: virCommandFree(cmd); VIR_FREE(ifacename); return ret; }
int qemuCapsProbeCPUModels(const char *qemu, virBitmapPtr qemuCaps, const char *arch, unsigned int *count, const char ***cpus) { char *output = NULL; int ret = -1; qemuCapsParseCPUModels parse; virCommandPtr cmd; if (count) *count = 0; if (cpus) *cpus = NULL; if (STREQ(arch, "i686") || STREQ(arch, "x86_64")) parse = qemuCapsParseX86Models; else if (STREQ(arch, "ppc64")) parse = qemuCapsParsePPCModels; else { VIR_DEBUG("don't know how to parse %s CPU models", arch); return 0; } cmd = qemuCapsProbeCommand(qemu, qemuCaps); virCommandAddArgList(cmd, "-cpu", "?", NULL); virCommandSetOutputBuffer(cmd, &output); if (virCommandRun(cmd, NULL) < 0) goto cleanup; if (parse(output, count, cpus) < 0) goto cleanup; ret = 0; cleanup: VIR_FREE(output); virCommandFree(cmd); return ret; }
int qemuCapsProbeMachineTypes(const char *binary, virBitmapPtr qemuCaps, virCapsGuestMachinePtr **machines, int *nmachines) { char *output; int ret = -1; virCommandPtr cmd; int status; /* Make sure the binary we are about to try exec'ing exists. * Technically we could catch the exec() failure, but that's * in a sub-process so it's hard to feed back a useful error. */ if (!virFileIsExecutable(binary)) { virReportSystemError(errno, _("Cannot find QEMU binary %s"), binary); return -1; } cmd = qemuCapsProbeCommand(binary, qemuCaps); virCommandAddArgList(cmd, "-M", "?", NULL); virCommandSetOutputBuffer(cmd, &output); /* Ignore failure from older qemu that did not understand '-M ?'. */ if (virCommandRun(cmd, &status) < 0) goto cleanup; if (qemuCapsParseMachineTypesStr(output, machines, nmachines) < 0) goto cleanup; ret = 0; cleanup: VIR_FREE(output); virCommandFree(cmd); return ret; }
static int virEbTablesOnceInit(void) { firewall_cmd_path = virFindFileInPath("firewall-cmd"); if (!firewall_cmd_path) { VIR_INFO("firewall-cmd not found on system. " "firewalld support disabled for ebtables."); } else { virCommandPtr cmd = virCommandNew(firewall_cmd_path); int status; virCommandAddArgList(cmd, "--state", NULL); if (virCommandRun(cmd, &status) < 0 || status != 0) { VIR_INFO("firewall-cmd found but disabled for ebtables"); VIR_FREE(firewall_cmd_path); firewall_cmd_path = NULL; } else { VIR_INFO("using firewalld for ebtables commands"); } virCommandFree(cmd); } return 0; }
/* * qemuTPMEmulatorStop * @swtpmStateDir: A directory where the socket is located * @shortName: short and unique name of the domain * * Gracefully stop the swptm */ static void qemuTPMEmulatorStop(const char *swtpmStateDir, const char *shortName) { virCommandPtr cmd; char *pathname; char *errbuf = NULL; if (qemuTPMEmulatorInit() < 0) return; if (!(pathname = qemuTPMCreateEmulatorSocket(swtpmStateDir, shortName))) return; if (!virFileExists(pathname)) goto cleanup; cmd = virCommandNew(swtpm_ioctl); if (!cmd) goto cleanup; virCommandAddArgList(cmd, "--unix", pathname, "-s", NULL); virCommandSetErrorBuffer(cmd, &errbuf); ignore_value(virCommandRun(cmd, NULL)); virCommandFree(cmd); /* clean up the socket */ unlink(pathname); cleanup: VIR_FREE(pathname); VIR_FREE(errbuf); }
/** * virNetDevOpenvswitchAddPort: * @brname: the bridge name * @ifname: the network interface name * @macaddr: the mac address of the virtual interface * @ovsport: the ovs specific fields * * Add an interface to the OVS bridge * * Returns 0 in case of success or -1 in case of failure. */ int virNetDevOpenvswitchAddPort(const char *brname, const char *ifname, const unsigned char *macaddr, virNetDevVPortProfilePtr ovsport) { int ret = -1; virCommandPtr cmd = NULL; char macaddrstr[VIR_MAC_STRING_BUFLEN]; char uuidstr[VIR_UUID_STRING_BUFLEN]; char *attachedmac_ex_id = NULL; char *ifaceid_ex_id = NULL; char *profile_ex_id = NULL; virMacAddrFormat(macaddr, macaddrstr); virUUIDFormat(ovsport->u.openvswitch.interfaceID, uuidstr); if (virAsprintf(&attachedmac_ex_id, "external-ids:attached-mac=\"%s\"", macaddrstr) < 0) goto cleanup; if (virAsprintf(&ifaceid_ex_id, "external-ids:iface-id=\"%s\"", uuidstr) < 0) goto cleanup; if (ovsport->u.openvswitch.profileID[0] != '\0') { if (virAsprintf(&profile_ex_id, "external-ids:port-profile=\"%s\"", ovsport->u.openvswitch.profileID) < 0) goto cleanup; } cmd = virCommandNew(OVSVSCTL); if (ovsport->u.openvswitch.profileID[0] == '\0') { virCommandAddArgList(cmd, "--", "--may-exist", "add-port", brname, ifname, "--", "set", "Interface", ifname, attachedmac_ex_id, "--", "set", "Interface", ifname, ifaceid_ex_id, "--", "set", "Interface", ifname, "external-ids:iface-status=active", NULL); } else { virCommandAddArgList(cmd, "--", "--may-exist", "add-port", brname, ifname, "--", "set", "Interface", ifname, attachedmac_ex_id, "--", "set", "Interface", ifname, ifaceid_ex_id, "--", "set", "Interface", ifname, profile_ex_id, "--", "set", "Interface", ifname, "external-ids:iface-status=active", NULL); } if (virCommandRun(cmd, NULL) < 0) { virReportSystemError(VIR_ERR_INTERNAL_ERROR, _("Unable to add port %s to OVS bridge %s"), ifname, brname); goto cleanup; } ret = 0; cleanup: VIR_FREE(attachedmac_ex_id); VIR_FREE(ifaceid_ex_id); VIR_FREE(profile_ex_id); virCommandFree(cmd); return ret; }
/** * virNetDevOpenvswitchAddPort: * @brname: the bridge name * @ifname: the network interface name * @macaddr: the mac address of the virtual interface * @vmuuid: the Domain UUID that has this interface * @ovsport: the ovs specific fields * * Add an interface to the OVS bridge * * Returns 0 in case of success or -1 in case of failure. */ int virNetDevOpenvswitchAddPort(const char *brname, const char *ifname, const virMacAddr *macaddr, const unsigned char *vmuuid, virNetDevVPortProfilePtr ovsport, virNetDevVlanPtr virtVlan) { int ret = -1; size_t i = 0; virCommandPtr cmd = NULL; char macaddrstr[VIR_MAC_STRING_BUFLEN]; char ifuuidstr[VIR_UUID_STRING_BUFLEN]; char vmuuidstr[VIR_UUID_STRING_BUFLEN]; char *attachedmac_ex_id = NULL; char *ifaceid_ex_id = NULL; char *profile_ex_id = NULL; char *vmid_ex_id = NULL; virBuffer buf = VIR_BUFFER_INITIALIZER; virMacAddrFormat(macaddr, macaddrstr); virUUIDFormat(ovsport->interfaceID, ifuuidstr); virUUIDFormat(vmuuid, vmuuidstr); if (virAsprintf(&attachedmac_ex_id, "external-ids:attached-mac=\"%s\"", macaddrstr) < 0) goto cleanup; if (virAsprintf(&ifaceid_ex_id, "external-ids:iface-id=\"%s\"", ifuuidstr) < 0) goto cleanup; if (virAsprintf(&vmid_ex_id, "external-ids:vm-id=\"%s\"", vmuuidstr) < 0) goto cleanup; if (ovsport->profileID[0] != '\0') { if (virAsprintf(&profile_ex_id, "external-ids:port-profile=\"%s\"", ovsport->profileID) < 0) goto cleanup; } cmd = virCommandNew(OVSVSCTL); virCommandAddArgList(cmd, "--timeout=5", "--", "--if-exists", "del-port", ifname, "--", "add-port", brname, ifname, NULL); if (virtVlan && virtVlan->nTags > 0) { switch (virtVlan->nativeMode) { case VIR_NATIVE_VLAN_MODE_TAGGED: virCommandAddArg(cmd, "vlan_mode=native-tagged"); virCommandAddArgFormat(cmd, "tag=%d", virtVlan->nativeTag); break; case VIR_NATIVE_VLAN_MODE_UNTAGGED: virCommandAddArg(cmd, "vlan_mode=native-untagged"); virCommandAddArgFormat(cmd, "tag=%d", virtVlan->nativeTag); break; case VIR_NATIVE_VLAN_MODE_DEFAULT: default: break; } if (virtVlan->trunk) { virBufferAddLit(&buf, "trunk="); /* * Trunk ports have at least one VLAN. Do the first one * outside the "for" loop so we can put a "," at the * start of the for loop if there are more than one VLANs * on this trunk port. */ virBufferAsprintf(&buf, "%d", virtVlan->tag[i]); for (i = 1; i < virtVlan->nTags; i++) { virBufferAddLit(&buf, ","); virBufferAsprintf(&buf, "%d", virtVlan->tag[i]); } if (virBufferCheckError(&buf) < 0) goto cleanup; virCommandAddArg(cmd, virBufferCurrentContent(&buf)); } else if (virtVlan->nTags) { virCommandAddArgFormat(cmd, "tag=%d", virtVlan->tag[0]); } } if (ovsport->profileID[0] == '\0') { virCommandAddArgList(cmd, "--", "set", "Interface", ifname, attachedmac_ex_id, "--", "set", "Interface", ifname, ifaceid_ex_id, "--", "set", "Interface", ifname, vmid_ex_id, "--", "set", "Interface", ifname, "external-ids:iface-status=active", NULL); } else { virCommandAddArgList(cmd, "--", "set", "Interface", ifname, attachedmac_ex_id, "--", "set", "Interface", ifname, ifaceid_ex_id, "--", "set", "Interface", ifname, vmid_ex_id, "--", "set", "Interface", ifname, profile_ex_id, "--", "set", "Interface", ifname, "external-ids:iface-status=active", NULL); } if (virCommandRun(cmd, NULL) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Unable to add port %s to OVS bridge %s"), ifname, brname); goto cleanup; } ret = 0; cleanup: virBufferFreeAndReset(&buf); VIR_FREE(attachedmac_ex_id); VIR_FREE(ifaceid_ex_id); VIR_FREE(vmid_ex_id); VIR_FREE(profile_ex_id); virCommandFree(cmd); return ret; }
/* * virNetDevBandwidthPlug: * @brname: name of the bridge * @net_bandwidth: QoS settings on @brname * @ifmac: MAC of interface * @bandwidth: QoS settings for interface * @id: unique ID (MUST be greater than 2) * * Set bridge part of interface QoS settings, e.g. guaranteed * bandwidth. @id is an unique ID (among @brname) from which * other identifiers for class, qdisc and filter are derived. * However, two classes were already set up (by * virNetDevBandwidthSet). That's why this @id MUST be greater * than 2. You may want to keep passed @id, as it is used later * by virNetDevBandwidthUnplug. * * Returns: * 0 if QoS set successfully * -1 otherwise. */ int virNetDevBandwidthPlug(const char *brname, virNetDevBandwidthPtr net_bandwidth, const virMacAddrPtr ifmac_ptr, virNetDevBandwidthPtr bandwidth, unsigned int id) { int ret = -1; virCommandPtr cmd = NULL; char *class_id = NULL; char *qdisc_id = NULL; char *filter_id = NULL; char *floor = NULL; char *ceil = NULL; unsigned char ifmac[VIR_MAC_BUFLEN]; char ifmacStr[VIR_MAC_STRING_BUFLEN]; char *mac[2] = {NULL, NULL}; if (id <= 2) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Invalid class ID %d"), id); return -1; } virMacAddrGetRaw(ifmac_ptr, ifmac); virMacAddrFormat(ifmac_ptr, ifmacStr); if (!net_bandwidth || !net_bandwidth->in) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Bridge '%s' has no QoS set, therefore " "unable to set 'floor' on '%s'"), brname, ifmacStr); return -1; } if (virAsprintf(&class_id, "1:%x", id) < 0 || virAsprintf(&qdisc_id, "%x:", id) < 0 || virAsprintf(&filter_id, "%u", id) < 0 || virAsprintf(&mac[0], "0x%02x%02x%02x%02x", ifmac[2], ifmac[3], ifmac[4], ifmac[5]) < 0 || virAsprintf(&mac[1], "0x%02x%02x", ifmac[0], ifmac[1]) < 0 || virAsprintf(&floor, "%llukbps", bandwidth->in->floor) < 0 || virAsprintf(&ceil, "%llukbps", net_bandwidth->in->peak ? net_bandwidth->in->peak : net_bandwidth->in->average) < 0) { virReportOOMError(); goto cleanup; } cmd = virCommandNew(TC); virCommandAddArgList(cmd, "class", "add", "dev", brname, "parent", "1:1", "classid", class_id, "htb", "rate", floor, "ceil", ceil, NULL); if (virCommandRun(cmd, NULL) < 0) goto cleanup; virCommandFree(cmd); cmd = virCommandNew(TC); virCommandAddArgList(cmd, "qdisc", "add", "dev", brname, "parent", class_id, "handle", qdisc_id, "sfq", "perturb", "10", NULL); if (virCommandRun(cmd, NULL) < 0) goto cleanup; virCommandFree(cmd); cmd = virCommandNew(TC); /* Okay, this not nice. But since libvirt does not know anything about * interface IP address(es), and tc fw filter simply refuse to use ebtables * marks, we need to use u32 selector to match MAC address. * If libvirt will ever know something, remove this FIXME */ virCommandAddArgList(cmd, "filter", "add", "dev", brname, "protocol", "ip", "prio", filter_id, "u32", "match", "u16", "0x0800", "0xffff", "at", "-2", "match", "u32", mac[0], "0xffffffff", "at", "-12", "match", "u16", mac[1], "0xffff", "at", "-14", "flowid", class_id, NULL); if (virCommandRun(cmd, NULL) < 0) goto cleanup; ret = 0; cleanup: VIR_FREE(mac[1]); VIR_FREE(mac[0]); VIR_FREE(ceil); VIR_FREE(floor); VIR_FREE(filter_id); VIR_FREE(qdisc_id); VIR_FREE(class_id); virCommandFree(cmd); 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 ret = -1; char *veth1auto = NULL; char *veth2auto = NULL; int vethNum = 0; virCommandPtr cmd = NULL; size_t i; /* * We might race with other containers, but this is reasonably * unlikely, so don't do too many retries for device creation */ if (virNetDevVethCreateMutexInitialize() < 0) return -1; virMutexLock(&virNetDevVethCreateMutex); #define MAX_VETH_RETRIES 10 for (i = 0; i < MAX_VETH_RETRIES; i++) { int status; if (!*veth1) { int veth1num; if ((veth1num = virNetDevVethGetFreeNum(vethNum)) < 0) goto cleanup; if (virAsprintf(&veth1auto, "vnet%d", veth1num) < 0) goto cleanup; vethNum = veth1num + 1; } if (!*veth2) { int veth2num; if ((veth2num = virNetDevVethGetFreeNum(vethNum)) < 0) goto cleanup; if (virAsprintf(&veth2auto, "vnet%d", veth2num) < 0) goto cleanup; vethNum = veth2num + 1; } cmd = virCommandNew("ip"); virCommandAddArgList(cmd, "link", "add", *veth1 ? *veth1 : veth1auto, "type", "veth", "peer", "name", *veth2 ? *veth2 : veth2auto, NULL); if (virCommandRun(cmd, &status) < 0) goto cleanup; if (status == 0) { if (veth1auto) { *veth1 = veth1auto; veth1auto = NULL; } if (veth2auto) { *veth2 = veth2auto; veth2auto = NULL; } VIR_DEBUG("Create Host: %s guest: %s", *veth1, *veth2); ret = 0; goto cleanup; } VIR_DEBUG("Failed to create veth host: %s guest: %s: %d", *veth1 ? *veth1 : veth1auto, *veth1 ? *veth1 : veth1auto, status); VIR_FREE(veth1auto); VIR_FREE(veth2auto); virCommandFree(cmd); cmd = NULL; } virReportError(VIR_ERR_INTERNAL_ERROR, _("Failed to allocate free veth pair after %d attempts"), MAX_VETH_RETRIES); cleanup: virMutexUnlock(&virNetDevVethCreateMutex); virCommandFree(cmd); VIR_FREE(veth1auto); VIR_FREE(veth2auto); return ret; }
/** * virNetDevBandwidthSet: * @ifname: on which interface * @bandwidth: rates to set (may be NULL) * @hierarchical_class: whether to create hierarchical class * * This function enables QoS on specified interface * and set given traffic limits for both, incoming * and outgoing traffic. Any previous setting get * overwritten. If @hierarchical_class is TRUE, create * hierarchical class. It is used to guarantee minimal * throughput ('floor' attribute in NIC). * * Return 0 on success, -1 otherwise. */ int virNetDevBandwidthSet(const char *ifname, virNetDevBandwidthPtr bandwidth, bool hierarchical_class) { int ret = -1; virCommandPtr cmd = NULL; char *average = NULL; char *peak = NULL; char *burst = NULL; if (!bandwidth) { /* nothing to be enabled */ ret = 0; goto cleanup; } virNetDevBandwidthClear(ifname); if (bandwidth->in && bandwidth->in->average) { if (virAsprintf(&average, "%llukbps", bandwidth->in->average) < 0) goto cleanup; if (bandwidth->in->peak && (virAsprintf(&peak, "%llukbps", bandwidth->in->peak) < 0)) goto cleanup; if (bandwidth->in->burst && (virAsprintf(&burst, "%llukb", bandwidth->in->burst) < 0)) goto cleanup; cmd = virCommandNew(TC); virCommandAddArgList(cmd, "qdisc", "add", "dev", ifname, "root", "handle", "1:", "htb", "default", hierarchical_class ? "2" : "1", NULL); if (virCommandRun(cmd, NULL) < 0) goto cleanup; /* If we are creating a hierarchical class, all non guaranteed traffic * goes to the 1:2 class which will adjust 'rate' dynamically as NICs * with guaranteed throughput are plugged and unplugged. Class 1:1 * exists so we don't exceed the maximum limit for the network. For each * NIC with guaranteed throughput a separate classid will be created. * NB '1:' is just a shorter notation of '1:0'. * * To get a picture how this works: * * +-----+ +---------+ +-----------+ +-----------+ +-----+ * | | | qdisc | | class 1:1 | | class 1:2 | | | * | NIC | | def 1:2 | | rate | | rate | | sfq | * | | --> | | --> | peak | -+-> | peak | --> | | * +-----+ +---------+ +-----------+ | +-----------+ +-----+ * | * | +-----------+ +-----+ * | | class 1:3 | | | * | | rate | | sfq | * +-> | peak | --> | | * | +-----------+ +-----+ * ... * | +-----------+ +-----+ * | | class 1:n | | | * | | rate | | sfq | * +-> | peak | --> | | * +-----------+ +-----+ * * After the routing decision, when is it clear a packet is to be sent * via a particular NIC, it is sent to the root qdisc (queueing * discipline). In this case HTB (Hierarchical Token Bucket). It has * only one direct child class (with id 1:1) which shapes the overall * rate that is sent through the NIC. This class has at least one child * (1:2) which is meant for all non-privileged (non guaranteed) traffic * from all domains. Then, for each interface with guaranteed * throughput, a separate class (1:n) is created. Imagine a class is a * box. Whenever a packet ends up in a class it is stored in this box * until the kernel sends it, then it is removed from box. Packets are * placed into boxes based on rules (filters) - e.g. depending on * destination IP/MAC address. If there is no rule to be applied, the * root qdisc has a default where such packets go (1:2 in this case). * Packets come in over and over again and boxes get filled more and * more. Imagine that kernel sends packets just once a second. So it * starts to traverse through this tree. It starts with the root qdisc * and through 1:1 it gets to 1:2. It sends packets up to 1:2's 'rate'. * Then it moves to 1:3 and again sends packets up to 1:3's 'rate'. The * whole process is repeated until 1:n is processed. So now we have * ensured each class its guaranteed bandwidth. If the sum of sent data * doesn't exceed the 'rate' in 1:1 class, we can go further and send * more packets. The rest of available bandwidth is distributed to the * 1:2,1:3...1:n classes by ratio of their 'rate'. As soon as the root * 'rate' limit is reached or there are no more packets to send, we stop * sending and wait another second. Each class has an SFQ qdisc which * shuffles packets in boxes stochastically, so one sender cannot * starve others. * * Therefore, whenever we want to plug in a new guaranteed interface, we * need to create a new class and adjust the 'rate' of the 1:2 class. * When unplugging we do the exact opposite - remove the associated * class, and adjust the 'rate'. * * This description is rather long, but it is still a good idea to read * it before you dig into the code. */ if (hierarchical_class) { virCommandFree(cmd); cmd = virCommandNew(TC); virCommandAddArgList(cmd, "class", "add", "dev", ifname, "parent", "1:", "classid", "1:1", "htb", "rate", average, "ceil", peak ? peak : average, NULL); if (virCommandRun(cmd, NULL) < 0) goto cleanup; } virCommandFree(cmd); cmd = virCommandNew(TC); virCommandAddArgList(cmd,"class", "add", "dev", ifname, "parent", hierarchical_class ? "1:1" : "1:", "classid", hierarchical_class ? "1:2" : "1:1", "htb", "rate", average, NULL); if (peak) virCommandAddArgList(cmd, "ceil", peak, NULL); if (burst) virCommandAddArgList(cmd, "burst", burst, NULL); if (virCommandRun(cmd, NULL) < 0) goto cleanup; virCommandFree(cmd); cmd = virCommandNew(TC); virCommandAddArgList(cmd, "qdisc", "add", "dev", ifname, "parent", hierarchical_class ? "1:2" : "1:1", "handle", "2:", "sfq", "perturb", "10", NULL); if (virCommandRun(cmd, NULL) < 0) goto cleanup; virCommandFree(cmd); cmd = virCommandNew(TC); virCommandAddArgList(cmd,"filter", "add", "dev", ifname, "parent", "1:0", "protocol", "ip", "handle", "1", "fw", "flowid", "1", NULL); if (virCommandRun(cmd, NULL) < 0) goto cleanup; VIR_FREE(average); VIR_FREE(peak); VIR_FREE(burst); } if (bandwidth->out) { if (virAsprintf(&average, "%llukbps", bandwidth->out->average) < 0) goto cleanup; if (virAsprintf(&burst, "%llukb", bandwidth->out->burst ? bandwidth->out->burst : bandwidth->out->average) < 0) goto cleanup; virCommandFree(cmd); cmd = virCommandNew(TC); virCommandAddArgList(cmd, "qdisc", "add", "dev", ifname, "ingress", NULL); if (virCommandRun(cmd, NULL) < 0) goto cleanup; virCommandFree(cmd); cmd = virCommandNew(TC); virCommandAddArgList(cmd, "filter", "add", "dev", ifname, "parent", "ffff:", "protocol", "ip", "u32", "match", "ip", "src", "0.0.0.0/0", "police", "rate", average, "burst", burst, "mtu", "64kb", "drop", "flowid", ":1", NULL); if (virCommandRun(cmd, NULL) < 0) goto cleanup; } ret = 0; cleanup: virCommandFree(cmd); VIR_FREE(average); VIR_FREE(peak); VIR_FREE(burst); return ret; }
static virCommandPtr virLXCProcessBuildControllerCmd(virLXCDriverPtr driver, virDomainObjPtr vm, int nveths, char **veths, int *ttyFDs, size_t nttyFDs, int *files, size_t nfiles, int handshakefd) { size_t i; char *filterstr; char *outputstr; virCommandPtr cmd; virLXCDriverConfigPtr cfg = virLXCDriverGetConfig(driver); cmd = virCommandNew(vm->def->emulator); /* The controller may call ip command, so we have to retain PATH. */ virCommandAddEnvPassBlockSUID(cmd, "PATH", "/bin:/usr/bin"); virCommandAddEnvFormat(cmd, "LIBVIRT_DEBUG=%d", virLogGetDefaultPriority()); if (virLogGetNbFilters() > 0) { filterstr = virLogGetFilters(); if (!filterstr) { virReportOOMError(); goto cleanup; } virCommandAddEnvPair(cmd, "LIBVIRT_LOG_FILTERS", filterstr); VIR_FREE(filterstr); } if (cfg->log_libvirtd) { if (virLogGetNbOutputs() > 0) { outputstr = virLogGetOutputs(); if (!outputstr) { virReportOOMError(); goto cleanup; } virCommandAddEnvPair(cmd, "LIBVIRT_LOG_OUTPUTS", outputstr); VIR_FREE(outputstr); } } else { virCommandAddEnvFormat(cmd, "LIBVIRT_LOG_OUTPUTS=%d:stderr", virLogGetDefaultPriority()); } virCommandAddArgList(cmd, "--name", vm->def->name, NULL); for (i = 0; i < nttyFDs; i++) { virCommandAddArg(cmd, "--console"); virCommandAddArgFormat(cmd, "%d", ttyFDs[i]); virCommandPassFD(cmd, ttyFDs[i], 0); } for (i = 0; i < nfiles; i++) { virCommandAddArg(cmd, "--passfd"); virCommandAddArgFormat(cmd, "%d", files[i]); virCommandPassFD(cmd, files[i], 0); } virCommandAddArgPair(cmd, "--security", virSecurityManagerGetModel(driver->securityManager)); virCommandAddArg(cmd, "--handshake"); virCommandAddArgFormat(cmd, "%d", handshakefd); virCommandAddArg(cmd, "--background"); for (i = 0; i < nveths; i++) { virCommandAddArgList(cmd, "--veth", veths[i], NULL); } virCommandPassFD(cmd, handshakefd, 0); return cmd; cleanup: virCommandFree(cmd); virObjectUnref(cfg); return NULL; }
/* Masquerade all traffic coming from the network associated * with the bridge */ static int iptablesForwardMasquerade(iptablesContext *ctx, virSocketAddr *netaddr, unsigned int prefix, const char *physdev, virSocketAddr *addrStart, virSocketAddr *addrEnd, unsigned int portStart, unsigned int portEnd, const char *protocol, int action) { int ret = -1; char *networkstr = NULL; char *addrStartStr = NULL; char *addrEndStr = NULL; char *portRangeStr = NULL; char *natRangeStr = NULL; virCommandPtr cmd = NULL; if (!(networkstr = iptablesFormatNetwork(netaddr, prefix))) return -1; if (!VIR_SOCKET_ADDR_IS_FAMILY(netaddr, AF_INET)) { /* Higher level code *should* guaranteee it's impossible to get here. */ virReportError(VIR_ERR_INTERNAL_ERROR, _("Attempted to NAT '%s'. NAT is only supported for IPv4."), networkstr); goto cleanup; } if (VIR_SOCKET_ADDR_IS_FAMILY(addrStart, AF_INET)) { if (!(addrStartStr = virSocketAddrFormat(addrStart))) goto cleanup; if (VIR_SOCKET_ADDR_IS_FAMILY(addrEnd, AF_INET)) { if (!(addrEndStr = virSocketAddrFormat(addrEnd))) goto cleanup; } } cmd = iptablesCommandNew(ctx->nat_postrouting, AF_INET, action); virCommandAddArgList(cmd, "--source", networkstr, NULL); if (protocol && protocol[0]) virCommandAddArgList(cmd, "-p", protocol, NULL); virCommandAddArgList(cmd, "!", "--destination", networkstr, NULL); if (physdev && physdev[0]) virCommandAddArgList(cmd, "--out-interface", physdev, NULL); if (protocol && protocol[0]) { if (portStart == 0 && portEnd == 0) { portStart = 1024; portEnd = 65535; } if (portStart < portEnd && portEnd < 65536) { if (virAsprintf(&portRangeStr, ":%u-%u", portStart, portEnd) < 0) { virReportOOMError(); goto cleanup; } } else { virReportError(VIR_ERR_INTERNAL_ERROR, _("Invalid port range '%u-%u'."), portStart, portEnd); } } /* Use --jump SNAT if public addr is specified */ if (addrStartStr && addrStartStr[0]) { int r = 0; if (addrEndStr && addrEndStr[0]) { r = virAsprintf(&natRangeStr, "%s-%s%s", addrStartStr, addrEndStr, portRangeStr ? portRangeStr : ""); } else { r = virAsprintf(&natRangeStr, "%s%s", addrStartStr, portRangeStr ? portRangeStr : ""); } if (r < 0) { virReportOOMError(); goto cleanup; } virCommandAddArgList(cmd, "--jump", "SNAT", "--to-source", natRangeStr, NULL); } else { virCommandAddArgList(cmd, "--jump", "MASQUERADE", NULL); if (portRangeStr && portRangeStr[0]) virCommandAddArgList(cmd, "--to-ports", &portRangeStr[1], NULL); } ret = virCommandRun(cmd, NULL); cleanup: virCommandFree(cmd); VIR_FREE(networkstr); VIR_FREE(addrStartStr); VIR_FREE(addrEndStr); VIR_FREE(portRangeStr); VIR_FREE(natRangeStr); return ret; }
/* * qemuTPMEmulatorBuildCommand: * * @tpm: TPM definition * @vmname: The name of the VM * @vmuuid: The UUID of the VM * @privileged: whether we are running in privileged mode * @swtpm_user: The uid for the swtpm to run as (drop privileges to from root) * @swtpm_group: The gid for the swtpm to run as * @swtpmStateDir: the directory where swtpm writes the pid file and creates the * Unix socket * @shortName: the short name of the VM * * Create the virCommand use for starting the emulator * Do some initializations on the way, such as creation of storage * and emulator setup. */ static virCommandPtr qemuTPMEmulatorBuildCommand(virDomainTPMDefPtr tpm, const char *vmname, const unsigned char *vmuuid, bool privileged, uid_t swtpm_user, gid_t swtpm_group, const char *swtpmStateDir, const char *shortName) { virCommandPtr cmd = NULL; bool created = false; char *pidfile; if (qemuTPMCreateEmulatorStorage(tpm->data.emulator.storagepath, &created, swtpm_user, swtpm_group) < 0) return NULL; if (created && qemuTPMEmulatorRunSetup(tpm->data.emulator.storagepath, vmname, vmuuid, privileged, swtpm_user, swtpm_group, tpm->data.emulator.logfile, tpm->version) < 0) goto error; unlink(tpm->data.emulator.source.data.nix.path); cmd = virCommandNew(swtpm_path); if (!cmd) goto error; virCommandClearCaps(cmd); virCommandAddArgList(cmd, "socket", "--daemon", "--ctrl", NULL); virCommandAddArgFormat(cmd, "type=unixio,path=%s,mode=0600", tpm->data.emulator.source.data.nix.path); virCommandAddArg(cmd, "--tpmstate"); virCommandAddArgFormat(cmd, "dir=%s,mode=0600", tpm->data.emulator.storagepath); virCommandAddArg(cmd, "--log"); virCommandAddArgFormat(cmd, "file=%s", tpm->data.emulator.logfile); virCommandSetUID(cmd, swtpm_user); virCommandSetGID(cmd, swtpm_group); switch (tpm->version) { case VIR_DOMAIN_TPM_VERSION_1_2: break; case VIR_DOMAIN_TPM_VERSION_2_0: virCommandAddArg(cmd, "--tpm2"); break; case VIR_DOMAIN_TPM_VERSION_DEFAULT: case VIR_DOMAIN_TPM_VERSION_LAST: break; } if (!(pidfile = qemuTPMEmulatorCreatePidFilename(swtpmStateDir, shortName))) goto error; virCommandAddArg(cmd, "--pid"); virCommandAddArgFormat(cmd, "file=%s", pidfile); VIR_FREE(pidfile); return cmd; error: if (created) qemuTPMDeleteEmulatorStorage(tpm); virCommandFree(cmd); return NULL; }
/* * qemuTPMEmulatorRunSetup * * @storagepath: path to the directory for TPM state * @vmname: the name of the VM * @vmuuid: the UUID of the VM * @privileged: whether we are running in privileged mode * @swtpm_user: The userid to switch to when setting up the TPM; * typically this should be the uid of 'tss' or 'root' * @swtpm_group: The group id to switch to * @logfile: The file to write the log into; it must be writable * for the user given by userid or 'tss' * @tpmversion: The version of the TPM, either a TPM 1.2 or TPM 2 * * Setup the external swtpm by creating endorsement key and * certificates for it. */ static int qemuTPMEmulatorRunSetup(const char *storagepath, const char *vmname, const unsigned char *vmuuid, bool privileged, uid_t swtpm_user, gid_t swtpm_group, const char *logfile, const virDomainTPMVersion tpmversion) { virCommandPtr cmd = NULL; int exitstatus; int ret = -1; char uuid[VIR_UUID_STRING_BUFLEN]; char *vmid = NULL; if (!privileged && tpmversion == VIR_DOMAIN_TPM_VERSION_1_2) return virFileWriteStr(logfile, _("Did not create EK and certificates since " "this requires privileged mode for a " "TPM 1.2\n"), 0600); cmd = virCommandNew(swtpm_setup); if (!cmd) goto cleanup; virUUIDFormat(vmuuid, uuid); if (virAsprintf(&vmid, "%s:%s", vmname, uuid) < 0) goto cleanup; virCommandSetUID(cmd, swtpm_user); virCommandSetGID(cmd, swtpm_group); switch (tpmversion) { case VIR_DOMAIN_TPM_VERSION_1_2: break; case VIR_DOMAIN_TPM_VERSION_2_0: virCommandAddArgList(cmd, "--tpm2", NULL); break; case VIR_DOMAIN_TPM_VERSION_DEFAULT: case VIR_DOMAIN_TPM_VERSION_LAST: break; } virCommandAddArgList(cmd, "--tpm-state", storagepath, "--vmid", vmid, "--logfile", logfile, "--createek", "--create-ek-cert", "--create-platform-cert", "--lock-nvram", "--not-overwrite", NULL); virCommandClearCaps(cmd); if (virCommandRun(cmd, &exitstatus) < 0 || exitstatus != 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not run '%s'. exitstatus: %d; " "Check error log '%s' for details."), swtpm_setup, exitstatus, logfile); goto cleanup; } ret = 0; cleanup: VIR_FREE(vmid); virCommandFree(cmd); return ret; }
static int virStorageBackendZFSCreateVol(virConnectPtr conn ATTRIBUTE_UNUSED, virStoragePoolObjPtr pool, virStorageVolDefPtr vol) { virCommandPtr cmd = NULL; int ret = -1; int volmode_needed = -1; if (vol->target.format != VIR_STORAGE_FILE_RAW) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("only RAW volumes are supported by this storage pool")); return -1; } if (vol->target.encryption != NULL) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("storage pool does not support encrypted " "volumes")); return -1; } vol->type = VIR_STORAGE_VOL_BLOCK; VIR_FREE(vol->target.path); if (virAsprintf(&vol->target.path, "%s/%s", pool->def->target.path, vol->name) == -1) return -1; if (VIR_STRDUP(vol->key, vol->target.path) < 0) goto cleanup; volmode_needed = virStorageBackendZFSVolModeNeeded(); if (volmode_needed < 0) goto cleanup; /** * $ zfs create -o volmode=dev -V 10240K test/volname * * -o volmode=dev -- we want to get volumes exposed as cdev * devices. If we don't specify that zfs * will lookup vfs.zfs.vol.mode sysctl value * -V -- tells to create a volume with the specified size */ cmd = virCommandNewArgList(ZFS, "create", NULL); if (volmode_needed) virCommandAddArgList(cmd, "-o", "volmode=dev", NULL); virCommandAddArg(cmd, "-V"); virCommandAddArgFormat(cmd, "%lluK", VIR_DIV_UP(vol->target.capacity, 1024)); virCommandAddArgFormat(cmd, "%s/%s", pool->def->source.name, vol->name); if (virCommandRun(cmd, NULL) < 0) goto cleanup; if (virStorageBackendZFSFindVols(pool, vol) < 0) goto cleanup; ret = 0; cleanup: virCommandFree(cmd); return ret; }
static int bhyveBuildNetArgStr(const virDomainDef *def, virCommandPtr cmd) { virDomainNetDefPtr net = NULL; char *brname = NULL; char *realifname = NULL; int *tapfd = NULL; if (def->nnets != 1) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("domain should have one and only one net defined")); return -1; } net = def->nets[0]; if (net) { int actualType = virDomainNetGetActualType(net); if (actualType == VIR_DOMAIN_NET_TYPE_BRIDGE) { if (VIR_STRDUP(brname, virDomainNetGetActualBridgeName(net)) < 0) return -1; } else { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Network type %d is not supported"), virDomainNetGetActualType(net)); return -1; } if (!net->ifname || STRPREFIX(net->ifname, VIR_NET_GENERATED_PREFIX) || strchr(net->ifname, '%')) { VIR_FREE(net->ifname); if (VIR_STRDUP(net->ifname, VIR_NET_GENERATED_PREFIX "%d") < 0) { VIR_FREE(brname); return -1; } } if (virNetDevTapCreateInBridgePort(brname, &net->ifname, &net->mac, def->uuid, tapfd, 1, virDomainNetGetActualVirtPortProfile(net), virDomainNetGetActualVlan(net), VIR_NETDEV_TAP_CREATE_IFUP | VIR_NETDEV_TAP_CREATE_PERSIST) < 0) { VIR_FREE(net->ifname); VIR_FREE(brname); return -1; } } realifname = virBhyveTapGetRealDeviceName(net->ifname); if (realifname == NULL) { VIR_FREE(net->ifname); VIR_FREE(brname); return -1; } VIR_DEBUG("%s -> %s", net->ifname, realifname); /* hack on top of other hack: we need to set * interface to 'UP' again after re-opening to find its * name */ if (virNetDevSetOnline(net->ifname, true) != 0) { VIR_FREE(net->ifname); VIR_FREE(brname); return -1; } virCommandAddArgList(cmd, "-s", "0:0,hostbridge", NULL); virCommandAddArg(cmd, "-s"); virCommandAddArgFormat(cmd, "1:0,virtio-net,%s", realifname); return 0; }