On Tue, Dec 11, 2012 at 02:59:43PM +0400, Dmitry Guryanov wrote:
Allow changing network interfaces in domain configuration.
ifname is used as iterface identifier: if there is interface
with some ifname in old config and there are no interfaces with
such name in the new config - issue prlctl command to delete
the network interface. And vice versa - if interface with
some ifname exists only in new config - issue prlctl command
to create it.
Signed-off-by: Dmitry Guryanov <dguryanov(a)parallels.com>
---
src/parallels/parallels_driver.c | 169 +++++++++++++++++++++++++++++++++++++-
1 files changed, 168 insertions(+), 1 deletions(-)
diff --git a/src/parallels/parallels_driver.c b/src/parallels/parallels_driver.c
index 755816e..f29b6ca 100644
--- a/src/parallels/parallels_driver.c
+++ b/src/parallels/parallels_driver.c
@@ -1776,6 +1776,170 @@ parallelsApplyDisksParams(virConnectPtr conn, parallelsDomObjPtr
pdom,
return 0;
}
+static int parallelsApplyIfaceParams(parallelsDomObjPtr pdom,
+ virDomainNetDefPtr oldnet,
+ virDomainNetDefPtr newnet)
+{
+ bool create = false;
+ bool is_changed = false;
+ virCommandPtr cmd;
+ char strmac[VIR_MAC_STRING_BUFLEN];
+ int i;
+
+ if (!oldnet) {
+ create = true;
+ if (VIR_ALLOC(oldnet) < 0) {
+ virReportOOMError();
+ return -1;
+ }
+ }
+
+ if (!create && oldnet->type != newnet->type) {
+ virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
+ _("Changing network type is not supported"));
+ return -1;
+ }
+
+ if (!STREQ_NULLABLE(oldnet->model, newnet->model)) {
+ virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
+ _("Changing network device model is not supported"));
+ return -1;
+ }
+
+ if (!STREQ_NULLABLE(oldnet->data.network.portgroup,
+ newnet->data.network.portgroup)) {
+ virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
+ _("Changing network portgroup is not supported"));
+ return -1;
+ }
+
+ if (!virNetDevVPortProfileEqual(oldnet->virtPortProfile,
+ newnet->virtPortProfile)) {
+ virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
+ _("Changing virtual port profile is not supported"));
+ return -1;
+ }
+
+ if (newnet->tune.sndbuf_specified) {
+ virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
+ _("Setting send buffer size is not supported"));
+ return -1;
+ }
+
+ if (!STREQ_NULLABLE(oldnet->script, newnet->script)) {
+ virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
+ _("Setting startup script is not supported"));
+ return -1;
+ }
+
+ if (!STREQ_NULLABLE(oldnet->filter, newnet->filter)) {
+ virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
+ _("Changing filter params is not supported"));
+ return -1;
+ }
+
+ if (newnet->bandwidth != NULL) {
+ virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
+ _("Setting bandwidth params is not supported"));
+ return -1;
+ }
+
+ for (i = 0; i < sizeof(newnet->vlan); i++) {
+ if (((char *)&newnet->vlan)[i] != 0) {
+ virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
+ _("Setting vlan params is not supported"));
+ return -1;
+ }
+ }
+
+ /* Here we know, that there are no differences, that are forbidden.
+ * Check is something changed, if no - do nothing */
+
+ if (create) {
+ cmd = virCommandNewArgList(PRLCTL, "set", pdom->uuid,
+ "--device-add", "net", NULL);
+ } else {
+ cmd = virCommandNewArgList(PRLCTL, "set", pdom->uuid,
+ "--device-set", newnet->ifname, NULL);
+ }
+
+ if (virMacAddrCmp(&oldnet->mac, &newnet->mac)) {
+ virMacAddrFormat(&newnet->mac, strmac);
+ virCommandAddArgFormat(cmd, "--mac=%s", strmac);
+ is_changed = true;
+ }
+
+ if (!STREQ_NULLABLE(oldnet->data.network.name, newnet->data.network.name)) {
+ virCommandAddArgFormat(cmd, "--network=%s",
newnet->data.network.name);
+ is_changed = true;
+ }
+
+ if (oldnet->linkstate != newnet->linkstate) {
+ if (newnet->linkstate == VIR_DOMAIN_NET_INTERFACE_LINK_STATE_UP) {
+ virCommandAddArgFormat(cmd, "--connect");
+ } else if (newnet->linkstate == VIR_DOMAIN_NET_INTERFACE_LINK_STATE_DOWN) {
+ virCommandAddArgFormat(cmd, "--disconnect");
+ }
+ is_changed = true;
+ }
+
+ if (!create && !is_changed) {
+ /* nothing changed - no need to run prlctl */
+ return 0;
+ }
+
+ if (virCommandRun(cmd, NULL))
+ return -1;
+
+ return 0;
+}
+
+static int
+parallelsApplyIfacesParams(parallelsDomObjPtr pdom,
+ virDomainNetDefPtr *oldnets, int nold,
+ virDomainNetDefPtr *newnets, int nnew)
+{
+ int i, j;
+
+ for (i = 0; i < nold; i++) {
+ virDomainNetDefPtr newnet = NULL;
+ virDomainNetDefPtr oldnet = oldnets[i];
let's move those declarations out of the loop
+ for (j = 0; j < nnew; j++) {
+ if (STREQ_NULLABLE(newnets[j]->ifname, oldnet->ifname)) {
+ newnet = newnets[j];
+ break;
+ }
+ }
+
+ if (!newnet) {
+ if (parallelsCmdRun(PRLCTL, "set", pdom->uuid,
+ "--device-del", oldnet->ifname, NULL) <
0)
+ return -1;
+
+ continue;
+ }
+
+ if (parallelsApplyIfaceParams(pdom, oldnet, newnet) < 0)
+ return -1;
+ }
+
+ for (i = 0; i < nnew; i++) {
+ virDomainNetDefPtr newnet = newnets[i];
+ bool found = false;
+
same
+ for (j = 0; j < nold; j++)
+ if (STREQ_NULLABLE(oldnets[j]->ifname, newnet->ifname))
+ found = true;
+ if (found)
+ continue;
+
+ if (parallelsApplyIfaceParams(pdom, NULL, newnet))
+ return -1;
+ }
+
+ return 0;
+}
+
static int
parallelsApplyChanges(virConnectPtr conn, virDomainObjPtr dom, virDomainDefPtr new)
{
@@ -1975,7 +2139,7 @@ parallelsApplyChanges(virConnectPtr conn, virDomainObjPtr dom,
virDomainDefPtr n
new->graphics, new->ngraphics) < 0)
return -1;
- if (new->nfss != 0 || new->nnets != 0 ||
+ if (new->nfss != 0 ||
new->nsounds != 0 || new->nhostdevs != 0 ||
new->nredirdevs != 0 || new->nsmartcards != 0 ||
new->nparallels || new->nchannels != 0 ||
@@ -2013,6 +2177,9 @@ parallelsApplyChanges(virConnectPtr conn, virDomainObjPtr dom,
virDomainDefPtr n
if (parallelsApplyDisksParams(conn, pdom, old->disks, old->ndisks,
new->disks, new->ndisks) < 0)
return -1;
+ if (parallelsApplyIfacesParams(pdom, old->nets, old->nnets,
+ new->nets, new->nnets) < 0)
+ return -1;
return 0;
}
ACK with associated fixup:
diff --git a/src/parallels/parallels_driver.c b/src/parallels/parallels_driver.c
index f16777a..60507e7 100644
--- a/src/parallels/parallels_driver.c
+++ b/src/parallels/parallels_driver.c
@@ -1924,10 +1924,13 @@ parallelsApplyIfacesParams(parallelsDomObjPtr pdom,
virDomainNetDefPtr *newnets, int nnew)
{
int i, j;
+ virDomainNetDefPtr newnet;
+ virDomainNetDefPtr oldnet;
+ bool found;
for (i = 0; i < nold; i++) {
- virDomainNetDefPtr newnet = NULL;
- virDomainNetDefPtr oldnet = oldnets[i];
+ newnet = NULL;
+ oldnet = oldnets[i];
for (j = 0; j < nnew; j++) {
if (STREQ_NULLABLE(newnets[j]->ifname, oldnet->ifname)) {
newnet = newnets[j];
@@ -1948,8 +1951,8 @@ parallelsApplyIfacesParams(parallelsDomObjPtr pdom,
}
for (i = 0; i < nnew; i++) {
- virDomainNetDefPtr newnet = newnets[i];
- bool found = false;
+ newnet = newnets[i];
+ found = false;
for (j = 0; j < nold; j++)
if (STREQ_NULLABLE(oldnets[j]->ifname, newnet->ifname))
Daniel
--
Daniel Veillard | Open Source and Standards, Red Hat
veillard(a)redhat.com | libxml Gnome XML XSLT toolkit
http://xmlsoft.org/
http://veillard.com/ | virtualization library
http://libvirt.org/