Parse network interfaces info from prlctl output.
Parallels Cloud Server uses virtual networks model for
network configuration: You can add network adapter to
VM and connect it to some predefined virtual network.
Fill type, mac, network name and linkstate fields of
virDomainNetDef structure.
Signed-off-by: Dmitry Guryanov <dguryanov(a)parallels.com>
---
src/parallels/parallels_driver.c | 111 ++++++++++++++++++++++++++++++++++++++
1 files changed, 111 insertions(+), 0 deletions(-)
diff --git a/src/parallels/parallels_driver.c b/src/parallels/parallels_driver.c
index 118dc13..755816e 100644
--- a/src/parallels/parallels_driver.c
+++ b/src/parallels/parallels_driver.c
@@ -50,6 +50,7 @@
#include "configmake.h"
#include "storage_file.h"
#include "nodeinfo.h"
+#include "c-ctype.h"
#include "parallels_driver.h"
#include "parallels_utils.h"
@@ -426,6 +427,113 @@ error:
return -1;
}
+static inline unsigned char hex2int(char c)
+{
+ if (c <= '9')
+ return c - '0';
+ else
+ return 10 + c - 'A';
+}
+
+/*
+ * Parse MAC address in format XXXXXXXXXXXX.
+ */
+static int
+parallelsMacAddrParse(const char *str, virMacAddrPtr addr)
+{
+ int i;
+
+ if (strlen(str) != 12)
+ goto error;
+
+ for (i = 0; i < 6; i++) {
+ if (!c_isxdigit(str[2 * i]) || !c_isxdigit(str[2 * i + 1]))
+ goto error;
+
+ addr->addr[i] = (hex2int(str[2 * i]) << 4) + hex2int(str[2 * i + 1]);
+ }
+
+ return 0;
+error:
+ virReportError(VIR_ERR_INVALID_ARG,
+ _("Invalid MAC address format '%s'"), str);
+ return -1;
+}
+
+static int
+parallelsGetNetInfo(virDomainNetDefPtr net,
+ const char *key,
+ virJSONValuePtr value)
+{
+ const char *tmp;
+
+ /* use device name, shown by prlctl as target device
+ * for identifying network adapter in virDomainDefineXML */
+ if (!(net->ifname = strdup(key))) {
+ virReportOOMError();
+ goto error;
+ }
+
+ net->type = VIR_DOMAIN_NET_TYPE_NETWORK;
+
+ if (!(tmp = virJSONValueObjectGetString(value, "mac"))) {
+ parallelsParseError();
+ return -1;
+ }
+
+ if (parallelsMacAddrParse(tmp, &net->mac) < 0) {
+ parallelsParseError();
+ goto error;
+ }
+
+ if (!(tmp = virJSONValueObjectGetString(value, "network"))) {
+ parallelsParseError();
+ goto error;
+ }
+
+ if (!(net->data.network.name = strdup(tmp))) {
+ virReportOOMError();
+ goto error;
+ }
+
+ net->linkstate = VIR_DOMAIN_NET_INTERFACE_LINK_STATE_UP;
+ if (virJSONValueObjectHasKey(value, "state")) {
+ tmp = virJSONValueObjectGetString(value, "state");
+ if STREQ(tmp, "disconnected")
+ net->linkstate = VIR_DOMAIN_NET_INTERFACE_LINK_STATE_DOWN;
+ }
+
+ return 0;
+
+error:
+ return -1;
+}
+
+static int
+parallelsAddNetInfo(virDomainDefPtr def, const char *key, virJSONValuePtr value)
+{
+ virDomainNetDefPtr net = NULL;
+
+ if (VIR_ALLOC(net) < 0)
+ goto no_memory;
+
+ if (parallelsGetNetInfo(net, key, value))
+ goto error;
+
+ if (VIR_EXPAND_N(def->nets, def->nnets, 1) < 0)
+ goto no_memory;
+
+ def->nets[def->nnets - 1] = net;
+
+ return 0;
+
+no_memory:
+ virReportOOMError();
+error:
+ virDomainNetDefFree(net);
+ return -1;
+}
+
static int
parallelsAddDomainHardware(virDomainDefPtr def, virJSONValuePtr jobj)
{
@@ -457,6 +565,9 @@ parallelsAddDomainHardware(virDomainDefPtr def, virJSONValuePtr jobj)
} else if (STRPREFIX(key, "hdd")) {
if (parallelsAddHddInfo(def, key, value))
goto cleanup;
+ } else if (STRPREFIX(key, "net")) {
+ if (parallelsAddNetInfo(def, key, value))
+ goto cleanup;
}
}
--
1.7.7.6