qemuDomainPCIAddressEnsureAddr(priv->pciaddrs, &net->info) < 0)
goto cleanup;
- vlan = qemuDomainNetVLAN(net);
+ if ((qemuCmdFlags & QEMUD_CMD_FLAG_NETDEV) &&
+ (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE)) {
+ vlan = -1;
+ } else {
+ vlan = qemuDomainNetVLAN(net);
- if (vlan < 0) {
- qemuReportError(VIR_ERR_NO_SUPPORT, "%s",
- _("Unable to attach network devices without vlan"));
- goto cleanup;
+ if (vlan < 0) {
+ qemuReportError(VIR_ERR_NO_SUPPORT, "%s",
+ _("Unable to attach network devices without vlan"));
+ goto cleanup;
+ }
}
if (tapfd != -1) {
}
qemuDomainObjEnterMonitorWithDriver(driver, vm);
- if (qemuMonitorAddHostNetwork(priv->mon, netstr) < 0) {
- qemuDomainObjExitMonitorWithDriver(driver, vm);
- goto try_tapfd_close;
+ if ((qemuCmdFlags & QEMUD_CMD_FLAG_NETDEV) &&
+ (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE)) {
+ if (qemuMonitorAddNetdev(priv->mon, netstr) < 0) {
+ qemuDomainObjExitMonitorWithDriver(driver, vm);
+ goto try_tapfd_close;
+ }
+ } else {
+ if (qemuMonitorAddHostNetwork(priv->mon, netstr) < 0) {
+ qemuDomainObjExitMonitorWithDriver(driver, vm);
+ goto try_tapfd_close;
+ }
}
qemuDomainObjExitMonitorWithDriver(driver, vm);
try_remove:
if (vlan < 0) {
- VIR_WARN0(_("Unable to remove network backend"));
+ if ((qemuCmdFlags & QEMUD_CMD_FLAG_NETDEV) &&
+ (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE)) {
+ char *netdev_name;
+ if (virAsprintf(&netdev_name, "host%s", net->info.alias) < 0)
+ goto no_memory;
+ qemuDomainObjEnterMonitorWithDriver(driver, vm);
+ if (qemuMonitorRemoveNetdev(priv->mon, netdev_name) < 0)
+ VIR_WARN(_("Failed to remove network backend for netdev %s"),
+ netdev_name);
+ qemuDomainObjExitMonitorWithDriver(driver, vm);
+ VIR_FREE(netdev_name);
+ } else {
+ VIR_WARN0(_("Unable to remove network backend"));
+ }
} else {
char *hostnet_name;
if (virAsprintf(&hostnet_name, "host%s", net->info.alias) < 0)
}
}
- if (qemuMonitorRemoveHostNetwork(priv->mon, vlan, hostnet_name) < 0) {
- qemuDomainObjExitMonitorWithDriver(driver, vm);
- goto cleanup;
+ if ((qemuCmdFlags & QEMUD_CMD_FLAG_NETDEV) &&
+ (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE)) {
+ if (qemuMonitorRemoveNetdev(priv->mon, hostnet_name) < 0) {
+ qemuDomainObjExitMonitorWithDriver(driver, vm);
+ goto cleanup;
+ }
+ } else {
+ if (qemuMonitorRemoveHostNetwork(priv->mon, vlan, hostnet_name) < 0) {
+ qemuDomainObjExitMonitorWithDriver(driver, vm);
+ goto cleanup;
+ }
}
qemuDomainObjExitMonitorWithDriver(driver, vm);
return ret;
}
+
+int qemuMonitorAddNetdev(qemuMonitorPtr mon,
+ const char *netdevstr)
+{
+ int ret;
+ DEBUG("mon=%p, fd=%d netdevstr=%s",
+ mon, mon->fd, netdevstr);
+
+ if (mon->json)
+ ret = qemuMonitorJSONAddNetdev(mon, netdevstr);
+ else
+ ret = qemuMonitorTextAddNetdev(mon, netdevstr);
+ return ret;
+}
+
+
+int qemuMonitorRemoveNetdev(qemuMonitorPtr mon,
+ const char *alias)
+{
+ int ret;
+ DEBUG("mon=%p, fd=%d alias=%s",
+ mon, mon->fd, alias);
+
+ if (mon->json)
+ ret = qemuMonitorJSONRemoveNetdev(mon, alias);
+ else
+ ret = qemuMonitorTextRemoveNetdev(mon, alias);
+ return ret;
+}
+
+
int qemuMonitorGetPtyPaths(qemuMonitorPtr mon,
virHashTablePtr paths)
{
int vlan,
const char *netname);
+int qemuMonitorAddNetdev(qemuMonitorPtr mon,
+ const char *netdevstr);
+
+int qemuMonitorRemoveNetdev(qemuMonitorPtr mon,
+ const char *alias);
+
int qemuMonitorGetPtyPaths(qemuMonitorPtr mon,
virHashTablePtr paths);
}
+static void
+qemuFreeKeywords(int nkeywords, char **keywords, char **values)
+{
+ int i;
+ for (i = 0 ; i < nkeywords ; i++) {
+ VIR_FREE(keywords[i]);
+ VIR_FREE(values[i]);
+ }
+ VIR_FREE(keywords);
+ VIR_FREE(values);
+}
+
+static virJSONValuePtr
+qemuMonitorJSONKeywordStringToJSON(const char *str, const char *firstkeyword)
+{
+ virJSONValuePtr ret = NULL;
+ char **keywords = NULL;
+ char **values = NULL;
+ int nkeywords = 0;
+ int i;
+
+ if (!(ret = virJSONValueNewObject()))
+ goto no_memory;
+
+ nkeywords = qemuParseKeywords(str, &keywords, &values, 1);
+
+ if (nkeywords < 0)
+ goto error;
+
+ for (i = 0 ; i < nkeywords ; i++) {
+ if (values[i] == NULL) {
+ if (i != 0) {
+ qemuReportError(VIR_ERR_INTERNAL_ERROR,
+ _("unexpected empty keyword in %s"), str);
+ goto error;
+ } else {
+ /* This 3rd arg isn't a typo - the way the parser works is
+ * that the value ended up in the keyword field */
+ if (virJSONValueObjectAppendString(ret, firstkeyword, keywords[i]) < 0)
+ goto no_memory;
+ }
+ } else {
+ if (virJSONValueObjectAppendString(ret, keywords[i], values[i]) < 0)
+ goto no_memory;
+ }
+ }
+
+ qemuFreeKeywords(nkeywords, keywords, values);
+ return ret;
+
+no_memory:
+ virReportOOMError();
+error:
+ qemuFreeKeywords(nkeywords, keywords, values);
+ virJSONValueFree(ret);
+ return NULL;
+}
+
+
static void qemuMonitorJSONHandleShutdown(qemuMonitorPtr mon, virJSONValuePtr data ATTRIBUTE_UNUSED)
{
qemuMonitorEmitShutdown(mon);
}
+int qemuMonitorJSONAddNetdev(qemuMonitorPtr mon,
+ const char *netdevstr)
+{
+ int ret = -1;
+ virJSONValuePtr cmd = NULL;
+ virJSONValuePtr reply = NULL;
+ virJSONValuePtr args = NULL;
+
+ cmd = qemuMonitorJSONMakeCommand("netdev_add", NULL);
+ if (!cmd)
+ return -1;
+
+ args = qemuMonitorJSONKeywordStringToJSON(netdevstr, "type");
+ if (!args)
+ goto cleanup;
+
+ if (virJSONValueObjectAppend(cmd, "arguments", args) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+ args = NULL; /* obj owns reference to args now */
+
+ ret = qemuMonitorJSONCommand(mon, cmd, &reply);
+
+ if (ret == 0)
+ ret = qemuMonitorJSONCheckError(cmd, reply);
+
+cleanup:
+ virJSONValueFree(args);
+ virJSONValueFree(cmd);
+ virJSONValueFree(reply);
+ return ret;
+}
+
+
+int qemuMonitorJSONRemoveNetdev(qemuMonitorPtr mon,
+ const char *alias)
+{
+ int ret;
+ virJSONValuePtr cmd = qemuMonitorJSONMakeCommand("netdev_del",
+ "s:id", alias,
+ NULL);
+ virJSONValuePtr reply = NULL;
+ if (!cmd)
+ return -1;
+
+ ret = qemuMonitorJSONCommand(mon, cmd, &reply);
+
+ if (ret == 0)
+ ret = qemuMonitorJSONCheckError(cmd, reply);
+
+ virJSONValueFree(cmd);
+ virJSONValueFree(reply);
+ return ret;
+}
+
+
/*
* Example return data
*
}
-static void
-qemuFreeKeywords(int nkeywords, char **keywords, char **values)
-{
- int i;
- for (i = 0 ; i < nkeywords ; i++) {
- VIR_FREE(keywords[i]);
- VIR_FREE(values[i]);
- }
- VIR_FREE(keywords);
- VIR_FREE(values);
-}
-
-static virJSONValuePtr
-qemuMonitorJSONKeywordStringToJSON(const char *str, const char *firstkeyword)
-{
- virJSONValuePtr ret = NULL;
- char **keywords = NULL;
- char **values = NULL;
- int nkeywords = 0;
- int i;
-
- if (!(ret = virJSONValueNewObject()))
- goto no_memory;
-
- nkeywords = qemuParseKeywords(str, &keywords, &values, 1);
-
- if (nkeywords < 0)
- goto error;
-
- for (i = 0 ; i < nkeywords ; i++) {
- if (values[i] == NULL) {
- if (i != 0) {
- qemuReportError(VIR_ERR_INTERNAL_ERROR,
- _("unexpected empty keyword in %s"), str);
- goto error;
- } else {
- /* This 3rd arg isn't a typo - the way the parser works is
- * that the value ended up in the keyword field */
- if (virJSONValueObjectAppendString(ret, firstkeyword, keywords[i]) < 0)
- goto no_memory;
- }
- } else {
- if (virJSONValueObjectAppendString(ret, keywords[i], values[i]) < 0)
- goto no_memory;
- }
- }
-
- qemuFreeKeywords(nkeywords, keywords, values);
- return ret;
-
-no_memory:
- virReportOOMError();
-error:
- qemuFreeKeywords(nkeywords, keywords, values);
- virJSONValueFree(ret);
- return NULL;
-}
-
-
int qemuMonitorJSONAddDevice(qemuMonitorPtr mon,
const char *devicestr)
{
int vlan,
const char *netname);
+int qemuMonitorJSONAddNetdev(qemuMonitorPtr mon,
+ const char *netdevstr);
+
+int qemuMonitorJSONRemoveNetdev(qemuMonitorPtr mon,
+ const char *alias);
+
int qemuMonitorJSONGetPtyPaths(qemuMonitorPtr mon,
virHashTablePtr paths);
}
+int qemuMonitorTextAddNetdev(qemuMonitorPtr mon,
+ const char *netdevstr)
+{
+ char *cmd;
+ char *reply = NULL;
+ int ret = -1;
+
+ if (virAsprintf(&cmd, "netdev_add %s", netdevstr) < 0) {
+ virReportOOMError();
+ return -1;
+ }
+
+ if (qemuMonitorCommand(mon, cmd, &reply) < 0) {
+ qemuReportError(VIR_ERR_OPERATION_FAILED,
+ _("failed to add netdev with '%s'"), cmd);
+ goto cleanup;
+ }
+
+ /* XXX error messages here ? */
+
+ ret = 0;
+
+cleanup:
+ VIR_FREE(cmd);
+ VIR_FREE(reply);
+ return ret;
+}
+
+
+int qemuMonitorTextRemoveNetdev(qemuMonitorPtr mon,
+ const char *alias)
+{
+ char *cmd;
+ char *reply = NULL;
+ int ret = -1;
+
+ if (virAsprintf(&cmd, "netdev_del %s", alias) < 0) {
+ virReportOOMError();
+ return -1;
+ }
+
+ if (qemuMonitorCommand(mon, cmd, &reply) < 0) {
+ qemuReportError(VIR_ERR_OPERATION_FAILED,
+ _("failed to remove netdev in qemu with '%s'"), cmd);
+ goto cleanup;
+ }
+
+ /* XXX error messages here ? */
+
+ ret = 0;
+
+cleanup:
+ VIR_FREE(cmd);
+ VIR_FREE(reply);
+ return ret;
+}
+
+
/* Parse the output of "info chardev" and return a hash of pty paths.
*
* Output is:
int vlan,
const char *netname);
+int qemuMonitorTextAddNetdev(qemuMonitorPtr mon,
+ const char *netdevstr);
+
+int qemuMonitorTextRemoveNetdev(qemuMonitorPtr mon,
+ const char *alias);
+
int qemuMonitorTextGetPtyPaths(qemuMonitorPtr mon,
virHashTablePtr paths);