Let users add NICs to domains.
---
examples/virtxml.c | 96 ++++++++++++++++++++++++----
libvirt-designer/libvirt-designer-domain.c | 53 +++++++++++++++
libvirt-designer/libvirt-designer-domain.h | 3 +
libvirt-designer/libvirt-designer.sym | 1 +
4 files changed, 141 insertions(+), 12 deletions(-)
diff --git a/examples/virtxml.c b/examples/virtxml.c
index 36bc3bb..87929b2 100644
--- a/examples/virtxml.c
+++ b/examples/virtxml.c
@@ -56,17 +56,19 @@ print_usage(const char *progname)
{
printf("\nUsage: %s options ...\n"
" options:\n"
- " -h | --help print this help\n"
- " -c | --connect=URI libvirt connection URI used \n"
- " for querying capabilities\n"
- " --list-os list IDs of known OSes\n"
- " --list-platform list IDs of known hypervisors\n"
- " -o | --os=OS set domain OS\n"
- " -p | --platform=PLATFORM set hypervisor under which \n"
- " domain will be running\n"
- " -a | --architecture=ARCH set domain architecture\n"
- " -d | --disk=PATH[,FORMAT] add disk to domain with PATH being
\n"
- " source and FORMAT is its format\n",
+ " -h | --help print this help\n"
+ " -c | --connect=URI libvirt connection URI used
\n"
+ " for querying
capabilities\n"
+ " --list-os list IDs of known OSes\n"
+ " --list-platform list IDs of known
hypervisors\n"
+ " -o | --os=OS set domain OS\n"
+ " -p | --platform=PLATFORM set hypervisor under which
\n"
+ " domain will be running\n"
+ " -a | --architecture=ARCH set domain architecture\n"
+ " -d | --disk=PATH[,FORMAT] add disk to domain with PATH
being \n"
+ " source and FORMAT is its
format\n"
+ " -i | --interface=NETWORK[,ARG=VAL] add interface with NETWORK
source.\n"
+ " Possible ARGs:
mac,link={up,down}\n",
progname);
}
@@ -186,6 +188,69 @@ add_disk(gpointer data,
}
+static void
+add_iface(gpointer data,
+ gpointer user_data)
+{
+ GVirDesignerDomain *domain = (GVirDesignerDomain *) user_data;
+ char *network = (char *) data;
+ char *param = NULL;
+ GVirConfigDomainInterface *iface = NULL;
+ GError *error = NULL;
+
+ param = strchr(network, ',');
+ if (param) {
+ *param = '\0';
+ param++;
+ }
+
+ iface = gvir_designer_domain_add_interface_network(domain, network, &error);
+ if (error) {
+ print_error("%s", error->message);
+ exit(EXIT_FAILURE);
+ }
+
+ while (param && *param) {
+ char *key = param;
+ char *val;
+ GVirConfigDomainInterfaceLinkState link;
+
+ /* move to next token */
+ param = strchr(param, ',');
+ if (param) {
+ *param = '\0';
+ param++;
+ }
+
+ /* parse token */
+ val = strchr(key, '=');
+ if (!val) {
+ print_error("Invalid format: %s", key);
+ exit(EXIT_FAILURE);
+ }
+
+ *val = '\0';
+ val++;
+
+ if (!strcmp(key, "mac")) {
+ gvir_config_domain_interface_set_mac(iface, val);
+ } else if (!strcmp(key, "link")) {
+ if (!strcmp(val, "up")) {
+ link = GVIR_CONFIG_DOMAIN_INTERFACE_LINK_STATE_UP;
+ } else if (!strcmp(val, "down")) {
+ link = GVIR_CONFIG_DOMAIN_INTERFACE_LINK_STATE_DOWN;
+ } else {
+ print_error("Unknown value: %s", val);
+ exit(EXIT_FAILURE);
+ }
+ gvir_config_domain_interface_set_link_state(iface, link);
+ } else {
+ print_error("Unknown key: %s", key);
+ exit(EXIT_FAILURE);
+ }
+ }
+}
+
#define CHECK_ERROR \
if (error) { \
print_error("%s", error->message); \
@@ -210,6 +275,7 @@ main(int argc, char *argv[])
char *arch_str = NULL;
char *connect_uri = NULL;
GList *disk_str_list = NULL;
+ GList *iface_str_list = NULL;
int arg;
struct option opt[] = {
@@ -221,6 +287,7 @@ main(int argc, char *argv[])
{"platform", required_argument, NULL, 'p'},
{"architecture", required_argument, NULL, 'a'},
{"disk", required_argument, NULL, 'd'},
+ {"interface", required_argument, NULL, 'i'},
{NULL, 0, NULL, 0}
};
@@ -230,7 +297,7 @@ main(int argc, char *argv[])
/* Standard (non-command) options. The leading + ensures that no
* argument reordering takes place, so that command options are
* not confused with top-level virsh options. */
- while ((arg = getopt_long(argc, argv, "+hc:o:p:a:d:", opt, NULL)) != -1) {
+ while ((arg = getopt_long(argc, argv, "+hc:o:p:a:d:i:", opt, NULL)) != -1)
{
char *progname;
switch (arg) {
case 'h':
@@ -277,6 +344,9 @@ main(int argc, char *argv[])
case 'd':
disk_str_list = g_list_append(disk_str_list, optarg);
break;
+ case 'i':
+ iface_str_list = g_list_append(iface_str_list, optarg);
+ break;
default:
print_error("Something has gone tragically wrong");
case '?':
@@ -321,6 +391,8 @@ main(int argc, char *argv[])
g_list_foreach(disk_str_list, add_disk, domain);
+ g_list_foreach(iface_str_list, add_iface, domain);
+
config = gvir_designer_domain_get_config(domain);
xml = gvir_config_object_to_xml(GVIR_CONFIG_OBJECT(config));
diff --git a/libvirt-designer/libvirt-designer-domain.c
b/libvirt-designer/libvirt-designer-domain.c
index 20611f2..5a10836 100644
--- a/libvirt-designer/libvirt-designer-domain.c
+++ b/libvirt-designer/libvirt-designer-domain.c
@@ -907,3 +907,56 @@ GVirConfigDomainDisk
*gvir_designer_domain_add_disk_device(GVirDesignerDomain *d
error);
return ret;
}
+
+static const gchar *
+gvir_designer_domain_get_preferred_nic_model(GVirDesignerDomain *design,
+ GError **error)
+{
+ const gchar *ret = NULL;
+ OsinfoDeviceLink *link = NULL;
+
+ link = gvir_designer_domain_get_preferred_device(design, "network",
error);
+ if (!link)
+ goto cleanup;
+
+ ret = osinfo_devicelink_get_driver(link);
+
+cleanup:
+ if (link)
+ g_object_unref(link);
+ return ret;
+}
+
+/**
+ * gvir_designer_domain_add_interface_network:
+ * @design: (transfer none): the domain designer instance
+ * @network: (transfer none): network name
+ *
+ * Add new network interface card into @design. The interface is
+ * of 'network' type with @network used as the source network.
+ *
+ * Returns: (transfer none): the pointer to the new interface.
+ */
+GVirConfigDomainInterface *
+gvir_designer_domain_add_interface_network(GVirDesignerDomain *design,
+ const char *network,
+ GError **error)
+{
+ g_return_val_if_fail(GVIR_DESIGNER_IS_DOMAIN(design), NULL);
+
+ GVirConfigDomainInterface *ret;
+ const gchar *model = NULL;
+
+ model = gvir_designer_domain_get_preferred_nic_model(design, error);
+
+ ret = GVIR_CONFIG_DOMAIN_INTERFACE(gvir_config_domain_interface_network_new());
+
+
gvir_config_domain_interface_network_set_source(GVIR_CONFIG_DOMAIN_INTERFACE_NETWORK(ret),
+ network);
+ if (model)
+ gvir_config_domain_interface_set_model(ret, model);
+
+ gvir_config_domain_add_device(design->priv->config,
GVIR_CONFIG_DOMAIN_DEVICE(ret));
+
+ return ret;
+}
diff --git a/libvirt-designer/libvirt-designer-domain.h
b/libvirt-designer/libvirt-designer-domain.h
index 06a5749..5097393 100644
--- a/libvirt-designer/libvirt-designer-domain.h
+++ b/libvirt-designer/libvirt-designer-domain.h
@@ -101,6 +101,9 @@ GVirConfigDomainDisk
*gvir_designer_domain_add_disk_device(GVirDesignerDomain *d
const char *devpath,
GError **error);
+GVirConfigDomainInterface *gvir_designer_domain_add_interface_network(GVirDesignerDomain
*design,
+ const char
*network,
+ GError **error);
G_END_DECLS
#endif /* __LIBVIRT_DESIGNER_DOMAIN_H__ */
diff --git a/libvirt-designer/libvirt-designer.sym
b/libvirt-designer/libvirt-designer.sym
index e67323a..77f76b4 100644
--- a/libvirt-designer/libvirt-designer.sym
+++ b/libvirt-designer/libvirt-designer.sym
@@ -12,6 +12,7 @@ LIBVIRT_DESIGNER_0.0.1 {
gvir_designer_domain_add_disk_file;
gvir_designer_domain_add_disk_device;
+ gvir_designer_domain_add_interface_network;
gvir_designer_domain_setup_machine;
gvir_designer_domain_setup_machine_full;
--
1.7.8.6