mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-11-05 12:51:12 +00:00
aa81db3ff8
And redundant error resetting. Pushed under trivial rule.
860 lines
24 KiB
C
860 lines
24 KiB
C
/*
|
|
* virsh-network.c: Commands to manage network
|
|
*
|
|
* Copyright (C) 2005, 2007-2012 Red Hat, Inc.
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; If not, see
|
|
* <http://www.gnu.org/licenses/>.
|
|
*
|
|
* Daniel Veillard <veillard@redhat.com>
|
|
* Karel Zak <kzak@redhat.com>
|
|
* Daniel P. Berrange <berrange@redhat.com>
|
|
*
|
|
*/
|
|
|
|
#include <config.h>
|
|
#include "virsh-network.h"
|
|
|
|
#include <libxml/parser.h>
|
|
#include <libxml/tree.h>
|
|
#include <libxml/xpath.h>
|
|
#include <libxml/xmlsave.h>
|
|
|
|
#include "internal.h"
|
|
#include "buf.h"
|
|
#include "memory.h"
|
|
#include "util.h"
|
|
#include "xml.h"
|
|
#include "conf/network_conf.h"
|
|
|
|
virNetworkPtr
|
|
vshCommandOptNetworkBy(vshControl *ctl, const vshCmd *cmd,
|
|
const char **name, unsigned int flags)
|
|
{
|
|
virNetworkPtr network = NULL;
|
|
const char *n = NULL;
|
|
const char *optname = "network";
|
|
virCheckFlags(VSH_BYUUID | VSH_BYNAME, NULL);
|
|
|
|
if (!vshCmdHasOption(ctl, cmd, optname))
|
|
return NULL;
|
|
|
|
if (vshCommandOptString(cmd, optname, &n) <= 0)
|
|
return NULL;
|
|
|
|
vshDebug(ctl, VSH_ERR_INFO, "%s: found option <%s>: %s\n",
|
|
cmd->def->name, optname, n);
|
|
|
|
if (name)
|
|
*name = n;
|
|
|
|
/* try it by UUID */
|
|
if ((flags & VSH_BYUUID) && strlen(n) == VIR_UUID_STRING_BUFLEN-1) {
|
|
vshDebug(ctl, VSH_ERR_DEBUG, "%s: <%s> trying as network UUID\n",
|
|
cmd->def->name, optname);
|
|
network = virNetworkLookupByUUIDString(ctl->conn, n);
|
|
}
|
|
/* try it by NAME */
|
|
if (!network && (flags & VSH_BYNAME)) {
|
|
vshDebug(ctl, VSH_ERR_DEBUG, "%s: <%s> trying as network NAME\n",
|
|
cmd->def->name, optname);
|
|
network = virNetworkLookupByName(ctl->conn, n);
|
|
}
|
|
|
|
if (!network)
|
|
vshError(ctl, _("failed to get network '%s'"), n);
|
|
|
|
return network;
|
|
}
|
|
|
|
/*
|
|
* "net-autostart" command
|
|
*/
|
|
static const vshCmdInfo info_network_autostart[] = {
|
|
{"help", N_("autostart a network")},
|
|
{"desc",
|
|
N_("Configure a network to be automatically started at boot.")},
|
|
{NULL, NULL}
|
|
};
|
|
|
|
static const vshCmdOptDef opts_network_autostart[] = {
|
|
{"network", VSH_OT_DATA, VSH_OFLAG_REQ, N_("network name or uuid")},
|
|
{"disable", VSH_OT_BOOL, 0, N_("disable autostarting")},
|
|
{NULL, 0, 0, NULL}
|
|
};
|
|
|
|
static bool
|
|
cmdNetworkAutostart(vshControl *ctl, const vshCmd *cmd)
|
|
{
|
|
virNetworkPtr network;
|
|
const char *name;
|
|
int autostart;
|
|
|
|
if (!(network = vshCommandOptNetwork(ctl, cmd, &name)))
|
|
return false;
|
|
|
|
autostart = !vshCommandOptBool(cmd, "disable");
|
|
|
|
if (virNetworkSetAutostart(network, autostart) < 0) {
|
|
if (autostart)
|
|
vshError(ctl, _("failed to mark network %s as autostarted"), name);
|
|
else
|
|
vshError(ctl, _("failed to unmark network %s as autostarted"), name);
|
|
virNetworkFree(network);
|
|
return false;
|
|
}
|
|
|
|
if (autostart)
|
|
vshPrint(ctl, _("Network %s marked as autostarted\n"), name);
|
|
else
|
|
vshPrint(ctl, _("Network %s unmarked as autostarted\n"), name);
|
|
|
|
virNetworkFree(network);
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
* "net-create" command
|
|
*/
|
|
static const vshCmdInfo info_network_create[] = {
|
|
{"help", N_("create a network from an XML file")},
|
|
{"desc", N_("Create a network.")},
|
|
{NULL, NULL}
|
|
};
|
|
|
|
static const vshCmdOptDef opts_network_create[] = {
|
|
{"file", VSH_OT_DATA, VSH_OFLAG_REQ, N_("file containing an XML network description")},
|
|
{NULL, 0, 0, NULL}
|
|
};
|
|
|
|
static bool
|
|
cmdNetworkCreate(vshControl *ctl, const vshCmd *cmd)
|
|
{
|
|
virNetworkPtr network;
|
|
const char *from = NULL;
|
|
bool ret = true;
|
|
char *buffer;
|
|
|
|
if (vshCommandOptString(cmd, "file", &from) <= 0)
|
|
return false;
|
|
|
|
if (virFileReadAll(from, VSH_MAX_XML_FILE, &buffer) < 0)
|
|
return false;
|
|
|
|
network = virNetworkCreateXML(ctl->conn, buffer);
|
|
VIR_FREE(buffer);
|
|
|
|
if (network != NULL) {
|
|
vshPrint(ctl, _("Network %s created from %s\n"),
|
|
virNetworkGetName(network), from);
|
|
virNetworkFree(network);
|
|
} else {
|
|
vshError(ctl, _("Failed to create network from %s"), from);
|
|
ret = false;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
/*
|
|
* "net-define" command
|
|
*/
|
|
static const vshCmdInfo info_network_define[] = {
|
|
{"help", N_("define (but don't start) a network from an XML file")},
|
|
{"desc", N_("Define a network.")},
|
|
{NULL, NULL}
|
|
};
|
|
|
|
static const vshCmdOptDef opts_network_define[] = {
|
|
{"file", VSH_OT_DATA, VSH_OFLAG_REQ, N_("file containing an XML network description")},
|
|
{NULL, 0, 0, NULL}
|
|
};
|
|
|
|
static bool
|
|
cmdNetworkDefine(vshControl *ctl, const vshCmd *cmd)
|
|
{
|
|
virNetworkPtr network;
|
|
const char *from = NULL;
|
|
bool ret = true;
|
|
char *buffer;
|
|
|
|
if (vshCommandOptString(cmd, "file", &from) <= 0)
|
|
return false;
|
|
|
|
if (virFileReadAll(from, VSH_MAX_XML_FILE, &buffer) < 0)
|
|
return false;
|
|
|
|
network = virNetworkDefineXML(ctl->conn, buffer);
|
|
VIR_FREE(buffer);
|
|
|
|
if (network != NULL) {
|
|
vshPrint(ctl, _("Network %s defined from %s\n"),
|
|
virNetworkGetName(network), from);
|
|
virNetworkFree(network);
|
|
} else {
|
|
vshError(ctl, _("Failed to define network from %s"), from);
|
|
ret = false;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
/*
|
|
* "net-destroy" command
|
|
*/
|
|
static const vshCmdInfo info_network_destroy[] = {
|
|
{"help", N_("destroy (stop) a network")},
|
|
{"desc", N_("Forcefully stop a given network.")},
|
|
{NULL, NULL}
|
|
};
|
|
|
|
static const vshCmdOptDef opts_network_destroy[] = {
|
|
{"network", VSH_OT_DATA, VSH_OFLAG_REQ, N_("network name or uuid")},
|
|
{NULL, 0, 0, NULL}
|
|
};
|
|
|
|
static bool
|
|
cmdNetworkDestroy(vshControl *ctl, const vshCmd *cmd)
|
|
{
|
|
virNetworkPtr network;
|
|
bool ret = true;
|
|
const char *name;
|
|
|
|
if (!(network = vshCommandOptNetwork(ctl, cmd, &name)))
|
|
return false;
|
|
|
|
if (virNetworkDestroy(network) == 0) {
|
|
vshPrint(ctl, _("Network %s destroyed\n"), name);
|
|
} else {
|
|
vshError(ctl, _("Failed to destroy network %s"), name);
|
|
ret = false;
|
|
}
|
|
|
|
virNetworkFree(network);
|
|
return ret;
|
|
}
|
|
|
|
/*
|
|
* "net-dumpxml" command
|
|
*/
|
|
static const vshCmdInfo info_network_dumpxml[] = {
|
|
{"help", N_("network information in XML")},
|
|
{"desc", N_("Output the network information as an XML dump to stdout.")},
|
|
{NULL, NULL}
|
|
};
|
|
|
|
static const vshCmdOptDef opts_network_dumpxml[] = {
|
|
{"network", VSH_OT_DATA, VSH_OFLAG_REQ, N_("network name or uuid")},
|
|
{"inactive", VSH_OT_BOOL, VSH_OFLAG_NONE, N_("network information of an inactive domain")},
|
|
{NULL, 0, 0, NULL}
|
|
};
|
|
|
|
static bool
|
|
cmdNetworkDumpXML(vshControl *ctl, const vshCmd *cmd)
|
|
{
|
|
virNetworkPtr network;
|
|
bool ret = true;
|
|
char *dump;
|
|
unsigned int flags = 0;
|
|
int inactive;
|
|
|
|
if (!(network = vshCommandOptNetwork(ctl, cmd, NULL)))
|
|
return false;
|
|
|
|
inactive = vshCommandOptBool(cmd, "inactive");
|
|
if (inactive)
|
|
flags |= VIR_NETWORK_XML_INACTIVE;
|
|
|
|
dump = virNetworkGetXMLDesc(network, flags);
|
|
|
|
if (dump != NULL) {
|
|
vshPrint(ctl, "%s", dump);
|
|
VIR_FREE(dump);
|
|
} else {
|
|
ret = false;
|
|
}
|
|
|
|
virNetworkFree(network);
|
|
return ret;
|
|
}
|
|
|
|
/*
|
|
* "net-info" command
|
|
*/
|
|
static const vshCmdInfo info_network_info[] = {
|
|
{"help", N_("network information")},
|
|
{"desc", N_("Returns basic information about the network")},
|
|
{NULL, NULL}
|
|
};
|
|
|
|
static const vshCmdOptDef opts_network_info[] = {
|
|
{"network", VSH_OT_DATA, VSH_OFLAG_REQ, N_("network name or uuid")},
|
|
{NULL, 0, 0, NULL}
|
|
};
|
|
|
|
static bool
|
|
cmdNetworkInfo(vshControl *ctl, const vshCmd *cmd)
|
|
{
|
|
virNetworkPtr network;
|
|
char uuid[VIR_UUID_STRING_BUFLEN];
|
|
int autostart;
|
|
int persistent = -1;
|
|
int active = -1;
|
|
char *bridge = NULL;
|
|
|
|
if (!(network = vshCommandOptNetwork(ctl, cmd, NULL)))
|
|
return false;
|
|
|
|
vshPrint(ctl, "%-15s %s\n", _("Name"), virNetworkGetName(network));
|
|
|
|
if (virNetworkGetUUIDString(network, uuid) == 0)
|
|
vshPrint(ctl, "%-15s %s\n", _("UUID"), uuid);
|
|
|
|
active = virNetworkIsActive(network);
|
|
if (active >= 0)
|
|
vshPrint(ctl, "%-15s %s\n", _("Active:"), active? _("yes") : _("no"));
|
|
|
|
persistent = virNetworkIsPersistent(network);
|
|
if (persistent < 0)
|
|
vshPrint(ctl, "%-15s %s\n", _("Persistent:"), _("unknown"));
|
|
else
|
|
vshPrint(ctl, "%-15s %s\n", _("Persistent:"), persistent ? _("yes") : _("no"));
|
|
|
|
if (virNetworkGetAutostart(network, &autostart) < 0)
|
|
vshPrint(ctl, "%-15s %s\n", _("Autostart:"), _("no autostart"));
|
|
else
|
|
vshPrint(ctl, "%-15s %s\n", _("Autostart:"), autostart ? _("yes") : _("no"));
|
|
|
|
bridge = virNetworkGetBridgeName(network);
|
|
if (bridge)
|
|
vshPrint(ctl, "%-15s %s\n", _("Bridge:"), bridge);
|
|
|
|
VIR_FREE(bridge);
|
|
virNetworkFree(network);
|
|
return true;
|
|
}
|
|
|
|
static int
|
|
vshNetworkSorter(const void *a, const void *b)
|
|
{
|
|
virNetworkPtr *na = (virNetworkPtr *) a;
|
|
virNetworkPtr *nb = (virNetworkPtr *) b;
|
|
|
|
if (*na && !*nb)
|
|
return -1;
|
|
|
|
if (!*na)
|
|
return *nb != NULL;
|
|
|
|
return vshStrcasecmp(virNetworkGetName(*na),
|
|
virNetworkGetName(*nb));
|
|
}
|
|
|
|
struct vshNetworkList {
|
|
virNetworkPtr *nets;
|
|
size_t nnets;
|
|
};
|
|
typedef struct vshNetworkList *vshNetworkListPtr;
|
|
|
|
static void
|
|
vshNetworkListFree(vshNetworkListPtr list)
|
|
{
|
|
int i;
|
|
|
|
if (list && list->nnets) {
|
|
for (i = 0; i < list->nnets; i++) {
|
|
if (list->nets[i])
|
|
virNetworkFree(list->nets[i]);
|
|
}
|
|
VIR_FREE(list->nets);
|
|
}
|
|
VIR_FREE(list);
|
|
}
|
|
|
|
static vshNetworkListPtr
|
|
vshNetworkListCollect(vshControl *ctl,
|
|
unsigned int flags)
|
|
{
|
|
vshNetworkListPtr list = vshMalloc(ctl, sizeof(*list));
|
|
int i;
|
|
int ret;
|
|
char **names = NULL;
|
|
virNetworkPtr net;
|
|
bool success = false;
|
|
size_t deleted = 0;
|
|
int persistent;
|
|
int autostart;
|
|
int nActiveNets = 0;
|
|
int nInactiveNets = 0;
|
|
int nAllNets = 0;
|
|
|
|
/* try the list with flags support (0.10.2 and later) */
|
|
if ((ret = virConnectListAllNetworks(ctl->conn,
|
|
&list->nets,
|
|
flags)) >= 0) {
|
|
list->nnets = ret;
|
|
goto finished;
|
|
}
|
|
|
|
/* check if the command is actually supported */
|
|
if (last_error && last_error->code == VIR_ERR_NO_SUPPORT)
|
|
goto fallback;
|
|
|
|
if (last_error && last_error->code == VIR_ERR_INVALID_ARG) {
|
|
/* try the new API again but mask non-guaranteed flags */
|
|
unsigned int newflags = flags & (VIR_CONNECT_LIST_NETWORKS_ACTIVE |
|
|
VIR_CONNECT_LIST_NETWORKS_INACTIVE);
|
|
|
|
vshResetLibvirtError();
|
|
if ((ret = virConnectListAllNetworks(ctl->conn, &list->nets,
|
|
newflags)) >= 0) {
|
|
list->nnets = ret;
|
|
goto filter;
|
|
}
|
|
}
|
|
|
|
/* there was an error during the first or second call */
|
|
vshError(ctl, "%s", _("Failed to list networks"));
|
|
goto cleanup;
|
|
|
|
|
|
fallback:
|
|
/* fall back to old method (0.10.1 and older) */
|
|
vshResetLibvirtError();
|
|
|
|
/* Get the number of active networks */
|
|
if (!VSH_MATCH(VIR_CONNECT_LIST_NETWORKS_FILTERS_ACTIVE) ||
|
|
VSH_MATCH(VIR_CONNECT_LIST_NETWORKS_ACTIVE)) {
|
|
if ((nActiveNets = virConnectNumOfNetworks(ctl->conn)) < 0) {
|
|
vshError(ctl, "%s", _("Failed to get the number of active networks"));
|
|
goto cleanup;
|
|
}
|
|
}
|
|
|
|
/* Get the number of inactive networks */
|
|
if (!VSH_MATCH(VIR_CONNECT_LIST_NETWORKS_FILTERS_ACTIVE) ||
|
|
VSH_MATCH(VIR_CONNECT_LIST_NETWORKS_INACTIVE)) {
|
|
if ((nInactiveNets = virConnectNumOfDefinedNetworks(ctl->conn)) < 0) {
|
|
vshError(ctl, "%s", _("Failed to get the number of inactive networks"));
|
|
goto cleanup;
|
|
}
|
|
}
|
|
|
|
nAllNets = nActiveNets + nInactiveNets;
|
|
|
|
if (nAllNets == 0)
|
|
return list;
|
|
|
|
names = vshMalloc(ctl, sizeof(char *) * nAllNets);
|
|
|
|
/* Retrieve a list of active network names */
|
|
if (!VSH_MATCH(VIR_CONNECT_LIST_NETWORKS_FILTERS_ACTIVE) ||
|
|
VSH_MATCH(VIR_CONNECT_LIST_NETWORKS_ACTIVE)) {
|
|
if (virConnectListNetworks(ctl->conn,
|
|
names, nActiveNets) < 0) {
|
|
vshError(ctl, "%s", _("Failed to list active networks"));
|
|
goto cleanup;
|
|
}
|
|
}
|
|
|
|
/* Add the inactive networks to the end of the name list */
|
|
if (!VSH_MATCH(VIR_CONNECT_LIST_NETWORKS_FILTERS_ACTIVE) ||
|
|
VSH_MATCH(VIR_CONNECT_LIST_NETWORKS_ACTIVE)) {
|
|
if (virConnectListDefinedNetworks(ctl->conn,
|
|
&names[nActiveNets],
|
|
nInactiveNets) < 0) {
|
|
vshError(ctl, "%s", _("Failed to list inactive networks"));
|
|
goto cleanup;
|
|
}
|
|
}
|
|
|
|
list->nets = vshMalloc(ctl, sizeof(virNetworkPtr) * (nAllNets));
|
|
list->nnets = 0;
|
|
|
|
/* get active networks */
|
|
for (i = 0; i < nActiveNets; i++) {
|
|
if (!(net = virNetworkLookupByName(ctl->conn, names[i])))
|
|
continue;
|
|
list->nets[list->nnets++] = net;
|
|
}
|
|
|
|
/* get inactive networks */
|
|
for (i = 0; i < nInactiveNets; i++) {
|
|
if (!(net = virNetworkLookupByName(ctl->conn, names[i])))
|
|
continue;
|
|
list->nets[list->nnets++] = net;
|
|
}
|
|
|
|
/* truncate networks that weren't found */
|
|
deleted = nAllNets - list->nnets;
|
|
|
|
filter:
|
|
/* filter list the list if the list was acquired by fallback means */
|
|
for (i = 0; i < list->nnets; i++) {
|
|
net = list->nets[i];
|
|
|
|
/* persistence filter */
|
|
if (VSH_MATCH(VIR_CONNECT_LIST_NETWORKS_FILTERS_PERSISTENT)) {
|
|
if ((persistent = virNetworkIsPersistent(net)) < 0) {
|
|
vshError(ctl, "%s", _("Failed to get network persistence info"));
|
|
goto cleanup;
|
|
}
|
|
|
|
if (!((VSH_MATCH(VIR_CONNECT_LIST_NETWORKS_PERSISTENT) && persistent) ||
|
|
(VSH_MATCH(VIR_CONNECT_LIST_NETWORKS_TRANSIENT) && !persistent)))
|
|
goto remove_entry;
|
|
}
|
|
|
|
/* autostart filter */
|
|
if (VSH_MATCH(VIR_CONNECT_LIST_NETWORKS_FILTERS_AUTOSTART)) {
|
|
if (virNetworkGetAutostart(net, &autostart) < 0) {
|
|
vshError(ctl, "%s", _("Failed to get network autostart state"));
|
|
goto cleanup;
|
|
}
|
|
|
|
if (!((VSH_MATCH(VIR_CONNECT_LIST_NETWORKS_AUTOSTART) && autostart) ||
|
|
(VSH_MATCH(VIR_CONNECT_LIST_NETWORKS_NO_AUTOSTART) && !autostart)))
|
|
goto remove_entry;
|
|
}
|
|
/* the pool matched all filters, it may stay */
|
|
continue;
|
|
|
|
remove_entry:
|
|
/* the pool has to be removed as it failed one of the filters */
|
|
virNetworkFree(list->nets[i]);
|
|
list->nets[i] = NULL;
|
|
deleted++;
|
|
}
|
|
|
|
finished:
|
|
/* sort the list */
|
|
if (list->nets && list->nnets)
|
|
qsort(list->nets, list->nnets,
|
|
sizeof(*list->nets), vshNetworkSorter);
|
|
|
|
/* truncate the list if filter simulation deleted entries */
|
|
if (deleted)
|
|
VIR_SHRINK_N(list->nets, list->nnets, deleted);
|
|
|
|
success = true;
|
|
|
|
cleanup:
|
|
for (i = 0; i < nAllNets; i++)
|
|
VIR_FREE(names[i]);
|
|
VIR_FREE(names);
|
|
|
|
if (!success) {
|
|
vshNetworkListFree(list);
|
|
list = NULL;
|
|
}
|
|
|
|
return list;
|
|
}
|
|
|
|
/*
|
|
* "net-list" command
|
|
*/
|
|
static const vshCmdInfo info_network_list[] = {
|
|
{"help", N_("list networks")},
|
|
{"desc", N_("Returns list of networks.")},
|
|
{NULL, NULL}
|
|
};
|
|
|
|
static const vshCmdOptDef opts_network_list[] = {
|
|
{"inactive", VSH_OT_BOOL, 0, N_("list inactive networks")},
|
|
{"all", VSH_OT_BOOL, 0, N_("list inactive & active networks")},
|
|
{"persistent", VSH_OT_BOOL, 0, N_("list persistent networks")},
|
|
{"transient", VSH_OT_BOOL, 0, N_("list transient networks")},
|
|
{"autostart", VSH_OT_BOOL, 0, N_("list networks with autostart enabled")},
|
|
{"no-autostart", VSH_OT_BOOL, 0, N_("list networks with autostart disabled")},
|
|
{NULL, 0, 0, NULL}
|
|
};
|
|
|
|
static bool
|
|
cmdNetworkList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
|
|
{
|
|
vshNetworkListPtr list = NULL;
|
|
int i;
|
|
bool inactive = vshCommandOptBool(cmd, "inactive");
|
|
bool all = vshCommandOptBool(cmd, "all");
|
|
bool persistent = vshCommandOptBool(cmd, "persistent");
|
|
bool transient = vshCommandOptBool(cmd, "transient");
|
|
bool autostart = vshCommandOptBool(cmd, "autostart");
|
|
bool no_autostart = vshCommandOptBool(cmd, "no-autostart");
|
|
unsigned int flags = VIR_CONNECT_LIST_NETWORKS_ACTIVE;
|
|
|
|
if (inactive)
|
|
flags = VIR_CONNECT_LIST_NETWORKS_INACTIVE;
|
|
|
|
if (all)
|
|
flags = VIR_CONNECT_LIST_NETWORKS_ACTIVE |
|
|
VIR_CONNECT_LIST_NETWORKS_INACTIVE;
|
|
|
|
if (persistent)
|
|
flags |= VIR_CONNECT_LIST_NETWORKS_PERSISTENT;
|
|
|
|
if (transient)
|
|
flags |= VIR_CONNECT_LIST_NETWORKS_TRANSIENT;
|
|
|
|
if (autostart)
|
|
flags |= VIR_CONNECT_LIST_NETWORKS_AUTOSTART;
|
|
|
|
if (no_autostart)
|
|
flags |= VIR_CONNECT_LIST_NETWORKS_NO_AUTOSTART;
|
|
|
|
if (!(list = vshNetworkListCollect(ctl, flags)))
|
|
return false;
|
|
|
|
vshPrintExtra(ctl, "%-20s %-10s %-13s %s\n", _("Name"), _("State"),
|
|
_("Autostart"), _("Persistent"));
|
|
vshPrintExtra(ctl, "--------------------------------------------------\n");
|
|
|
|
for (i = 0; i < list->nnets; i++) {
|
|
virNetworkPtr network = list->nets[i];
|
|
const char *autostartStr;
|
|
int is_autostart = 0;
|
|
|
|
if (virNetworkGetAutostart(network, &is_autostart) < 0)
|
|
autostartStr = _("no autostart");
|
|
else
|
|
autostartStr = is_autostart ? _("yes") : _("no");
|
|
|
|
vshPrint(ctl, "%-20s %-10s %-13s %s\n",
|
|
virNetworkGetName(network),
|
|
virNetworkIsActive(network) ? _("active") : _("inactive"),
|
|
autostartStr,
|
|
virNetworkIsPersistent(network) ? _("yes") : _("no"));
|
|
}
|
|
|
|
vshNetworkListFree(list);
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
* "net-name" command
|
|
*/
|
|
static const vshCmdInfo info_network_name[] = {
|
|
{"help", N_("convert a network UUID to network name")},
|
|
{"desc", ""},
|
|
{NULL, NULL}
|
|
};
|
|
|
|
static const vshCmdOptDef opts_network_name[] = {
|
|
{"network", VSH_OT_DATA, VSH_OFLAG_REQ, N_("network uuid")},
|
|
{NULL, 0, 0, NULL}
|
|
};
|
|
|
|
static bool
|
|
cmdNetworkName(vshControl *ctl, const vshCmd *cmd)
|
|
{
|
|
virNetworkPtr network;
|
|
|
|
if (!(network = vshCommandOptNetworkBy(ctl, cmd, NULL,
|
|
VSH_BYUUID)))
|
|
return false;
|
|
|
|
vshPrint(ctl, "%s\n", virNetworkGetName(network));
|
|
virNetworkFree(network);
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
* "net-start" command
|
|
*/
|
|
static const vshCmdInfo info_network_start[] = {
|
|
{"help", N_("start a (previously defined) inactive network")},
|
|
{"desc", N_("Start a network.")},
|
|
{NULL, NULL}
|
|
};
|
|
|
|
static const vshCmdOptDef opts_network_start[] = {
|
|
{"network", VSH_OT_DATA, VSH_OFLAG_REQ, N_("network name or uuid")},
|
|
{NULL, 0, 0, NULL}
|
|
};
|
|
|
|
static bool
|
|
cmdNetworkStart(vshControl *ctl, const vshCmd *cmd)
|
|
{
|
|
virNetworkPtr network;
|
|
bool ret = true;
|
|
const char *name = NULL;
|
|
|
|
if (!(network = vshCommandOptNetwork(ctl, cmd, &name)))
|
|
return false;
|
|
|
|
if (virNetworkCreate(network) == 0) {
|
|
vshPrint(ctl, _("Network %s started\n"), name);
|
|
} else {
|
|
vshError(ctl, _("Failed to start network %s"), name);
|
|
ret = false;
|
|
}
|
|
virNetworkFree(network);
|
|
return ret;
|
|
}
|
|
|
|
/*
|
|
* "net-undefine" command
|
|
*/
|
|
static const vshCmdInfo info_network_undefine[] = {
|
|
{"help", N_("undefine an inactive network")},
|
|
{"desc", N_("Undefine the configuration for an inactive network.")},
|
|
{NULL, NULL}
|
|
};
|
|
|
|
static const vshCmdOptDef opts_network_undefine[] = {
|
|
{"network", VSH_OT_DATA, VSH_OFLAG_REQ, N_("network name or uuid")},
|
|
{NULL, 0, 0, NULL}
|
|
};
|
|
|
|
static bool
|
|
cmdNetworkUndefine(vshControl *ctl, const vshCmd *cmd)
|
|
{
|
|
virNetworkPtr network;
|
|
bool ret = true;
|
|
const char *name;
|
|
|
|
if (!(network = vshCommandOptNetwork(ctl, cmd, &name)))
|
|
return false;
|
|
|
|
if (virNetworkUndefine(network) == 0) {
|
|
vshPrint(ctl, _("Network %s has been undefined\n"), name);
|
|
} else {
|
|
vshError(ctl, _("Failed to undefine network %s"), name);
|
|
ret = false;
|
|
}
|
|
|
|
virNetworkFree(network);
|
|
return ret;
|
|
}
|
|
|
|
/*
|
|
* "net-uuid" command
|
|
*/
|
|
static const vshCmdInfo info_network_uuid[] = {
|
|
{"help", N_("convert a network name to network UUID")},
|
|
{"desc", ""},
|
|
{NULL, NULL}
|
|
};
|
|
|
|
static const vshCmdOptDef opts_network_uuid[] = {
|
|
{"network", VSH_OT_DATA, VSH_OFLAG_REQ, N_("network name")},
|
|
{NULL, 0, 0, NULL}
|
|
};
|
|
|
|
static bool
|
|
cmdNetworkUuid(vshControl *ctl, const vshCmd *cmd)
|
|
{
|
|
virNetworkPtr network;
|
|
char uuid[VIR_UUID_STRING_BUFLEN];
|
|
|
|
if (!(network = vshCommandOptNetworkBy(ctl, cmd, NULL,
|
|
VSH_BYNAME)))
|
|
return false;
|
|
|
|
if (virNetworkGetUUIDString(network, uuid) != -1)
|
|
vshPrint(ctl, "%s\n", uuid);
|
|
else
|
|
vshError(ctl, "%s", _("failed to get network UUID"));
|
|
|
|
virNetworkFree(network);
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
* "net-edit" command
|
|
*/
|
|
static const vshCmdInfo info_network_edit[] = {
|
|
{"help", N_("edit XML configuration for a network")},
|
|
{"desc", N_("Edit the XML configuration for a network.")},
|
|
{NULL, NULL}
|
|
};
|
|
|
|
static const vshCmdOptDef opts_network_edit[] = {
|
|
{"network", VSH_OT_DATA, VSH_OFLAG_REQ, N_("network name or uuid")},
|
|
{NULL, 0, 0, NULL}
|
|
};
|
|
|
|
static char *vshNetworkGetXMLDesc(virNetworkPtr network)
|
|
{
|
|
unsigned int flags = VIR_NETWORK_XML_INACTIVE;
|
|
char *doc = virNetworkGetXMLDesc(network, flags);
|
|
|
|
if (!doc && last_error->code == VIR_ERR_INVALID_ARG) {
|
|
/* The server side libvirt doesn't support
|
|
* VIR_NETWORK_XML_INACTIVE, so retry without it.
|
|
*/
|
|
vshResetLibvirtError();
|
|
flags &= ~VIR_NETWORK_XML_INACTIVE;
|
|
doc = virNetworkGetXMLDesc(network, flags);
|
|
}
|
|
return doc;
|
|
}
|
|
|
|
static bool
|
|
cmdNetworkEdit(vshControl *ctl, const vshCmd *cmd)
|
|
{
|
|
bool ret = false;
|
|
virNetworkPtr network = NULL;
|
|
virNetworkPtr network_edited = NULL;
|
|
|
|
network = vshCommandOptNetwork(ctl, cmd, NULL);
|
|
if (network == NULL)
|
|
goto cleanup;
|
|
|
|
#define EDIT_GET_XML vshNetworkGetXMLDesc(network)
|
|
#define EDIT_NOT_CHANGED \
|
|
vshPrint(ctl, _("Network %s XML configuration not changed.\n"), \
|
|
virNetworkGetName(network)); \
|
|
ret = true; goto edit_cleanup;
|
|
#define EDIT_DEFINE \
|
|
(network_edited = virNetworkDefineXML(ctl->conn, doc_edited))
|
|
#define EDIT_FREE \
|
|
if (network_edited) \
|
|
virNetworkFree(network_edited);
|
|
#include "virsh-edit.c"
|
|
|
|
vshPrint(ctl, _("Network %s XML configuration edited.\n"),
|
|
virNetworkGetName(network_edited));
|
|
|
|
ret = true;
|
|
|
|
cleanup:
|
|
if (network)
|
|
virNetworkFree(network);
|
|
if (network_edited)
|
|
virNetworkFree(network_edited);
|
|
|
|
return ret;
|
|
}
|
|
|
|
const vshCmdDef networkCmds[] = {
|
|
{"net-autostart", cmdNetworkAutostart, opts_network_autostart,
|
|
info_network_autostart, 0},
|
|
{"net-create", cmdNetworkCreate, opts_network_create,
|
|
info_network_create, 0},
|
|
{"net-define", cmdNetworkDefine, opts_network_define,
|
|
info_network_define, 0},
|
|
{"net-destroy", cmdNetworkDestroy, opts_network_destroy,
|
|
info_network_destroy, 0},
|
|
{"net-dumpxml", cmdNetworkDumpXML, opts_network_dumpxml,
|
|
info_network_dumpxml, 0},
|
|
{"net-edit", cmdNetworkEdit, opts_network_edit, info_network_edit, 0},
|
|
{"net-info", cmdNetworkInfo, opts_network_info, info_network_info, 0},
|
|
{"net-list", cmdNetworkList, opts_network_list, info_network_list, 0},
|
|
{"net-name", cmdNetworkName, opts_network_name, info_network_name, 0},
|
|
{"net-start", cmdNetworkStart, opts_network_start, info_network_start, 0},
|
|
{"net-undefine", cmdNetworkUndefine, opts_network_undefine,
|
|
info_network_undefine, 0},
|
|
{"net-uuid", cmdNetworkUuid, opts_network_uuid, info_network_uuid, 0},
|
|
{NULL, NULL, NULL, NULL, 0}
|
|
};
|