2008-07-11 10:48:34 +00:00
|
|
|
/*
|
|
|
|
* network_conf.c: network XML handling
|
|
|
|
*
|
2011-12-14 10:50:23 +00:00
|
|
|
* Copyright (C) 2006-2012 Red Hat, Inc.
|
2008-07-11 10:48:34 +00:00
|
|
|
* Copyright (C) 2006-2008 Daniel P. Berrange
|
|
|
|
*
|
|
|
|
* 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
|
2012-09-20 22:30:55 +00:00
|
|
|
* License along with this library. If not, see
|
2012-07-21 10:06:23 +00:00
|
|
|
* <http://www.gnu.org/licenses/>.
|
2008-07-11 10:48:34 +00:00
|
|
|
*
|
|
|
|
* Author: Daniel P. Berrange <berrange@redhat.com>
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
2009-12-22 02:06:57 +00:00
|
|
|
#include <unistd.h>
|
2008-07-11 10:48:34 +00:00
|
|
|
#include <arpa/inet.h>
|
|
|
|
#include <sys/types.h>
|
2008-08-12 08:25:48 +00:00
|
|
|
#include <sys/stat.h>
|
2008-07-11 10:48:34 +00:00
|
|
|
#include <fcntl.h>
|
2008-10-28 17:45:41 +00:00
|
|
|
#include <string.h>
|
2008-07-11 10:48:34 +00:00
|
|
|
#include <dirent.h>
|
|
|
|
|
2008-11-04 22:30:33 +00:00
|
|
|
#include "virterror_internal.h"
|
2008-11-04 23:22:06 +00:00
|
|
|
#include "datatypes.h"
|
2008-07-11 10:48:34 +00:00
|
|
|
#include "network_conf.h"
|
Split src/util/network.{c,h} into 5 pieces
The src/util/network.c file is a dumping ground for many different
APIs. Split it up into 5 pieces, along functional lines
- src/util/virnetdevbandwidth.c: virNetDevBandwidth type & helper APIs
- src/util/virnetdevvportprofile.c: virNetDevVPortProfile type & helper APIs
- src/util/virsocketaddr.c: virSocketAddr and APIs
- src/conf/netdev_bandwidth_conf.c: XML parsing / formatting
for virNetDevBandwidth
- src/conf/netdev_vport_profile_conf.c: XML parsing / formatting
for virNetDevVPortProfile
* src/util/network.c, src/util/network.h: Split into 5 pieces
* src/conf/netdev_bandwidth_conf.c, src/conf/netdev_bandwidth_conf.h,
src/conf/netdev_vport_profile_conf.c, src/conf/netdev_vport_profile_conf.h,
src/util/virnetdevbandwidth.c, src/util/virnetdevbandwidth.h,
src/util/virnetdevvportprofile.c, src/util/virnetdevvportprofile.h,
src/util/virsocketaddr.c, src/util/virsocketaddr.h: New pieces
* daemon/libvirtd.h, daemon/remote.c, src/conf/domain_conf.c,
src/conf/domain_conf.h, src/conf/network_conf.c,
src/conf/network_conf.h, src/conf/nwfilter_conf.h,
src/esx/esx_util.h, src/network/bridge_driver.c,
src/qemu/qemu_conf.c, src/rpc/virnetsocket.c,
src/rpc/virnetsocket.h, src/util/dnsmasq.h, src/util/interface.h,
src/util/iptables.h, src/util/macvtap.c, src/util/macvtap.h,
src/util/virnetdev.h, src/util/virnetdevtap.c,
tools/virsh.c: Update include files
2011-11-02 15:40:08 +00:00
|
|
|
#include "netdev_vport_profile_conf.h"
|
|
|
|
#include "netdev_bandwidth_conf.h"
|
2012-08-12 07:51:30 +00:00
|
|
|
#include "netdev_vlan_conf.h"
|
2008-07-11 10:48:34 +00:00
|
|
|
#include "memory.h"
|
|
|
|
#include "xml.h"
|
|
|
|
#include "uuid.h"
|
|
|
|
#include "util.h"
|
|
|
|
#include "buf.h"
|
2008-08-20 12:50:29 +00:00
|
|
|
#include "c-ctype.h"
|
2011-07-19 18:32:58 +00:00
|
|
|
#include "virfile.h"
|
2008-07-11 10:48:34 +00:00
|
|
|
|
2009-03-02 17:37:03 +00:00
|
|
|
#define MAX_BRIDGE_ID 256
|
2009-01-20 17:13:33 +00:00
|
|
|
#define VIR_FROM_THIS VIR_FROM_NETWORK
|
|
|
|
|
2008-07-11 10:48:34 +00:00
|
|
|
VIR_ENUM_IMPL(virNetworkForward,
|
|
|
|
VIR_NETWORK_FORWARD_LAST,
|
2012-08-16 15:41:41 +00:00
|
|
|
"none", "nat", "route", "bridge", "private", "vepa", "passthrough", "hostdev")
|
|
|
|
|
|
|
|
VIR_ENUM_DECL(virNetworkForwardHostdevDevice)
|
|
|
|
VIR_ENUM_IMPL(virNetworkForwardHostdevDevice,
|
|
|
|
VIR_NETWORK_FORWARD_HOSTDEV_DEVICE_LAST,
|
|
|
|
"none", "pci", "netdev")
|
2008-07-11 10:48:34 +00:00
|
|
|
|
2008-10-10 14:50:26 +00:00
|
|
|
virNetworkObjPtr virNetworkFindByUUID(const virNetworkObjListPtr nets,
|
2008-07-11 10:48:34 +00:00
|
|
|
const unsigned char *uuid)
|
|
|
|
{
|
2008-10-10 14:50:26 +00:00
|
|
|
unsigned int i;
|
|
|
|
|
2008-12-04 22:00:14 +00:00
|
|
|
for (i = 0 ; i < nets->count ; i++) {
|
|
|
|
virNetworkObjLock(nets->objs[i]);
|
2008-10-10 14:50:26 +00:00
|
|
|
if (!memcmp(nets->objs[i]->def->uuid, uuid, VIR_UUID_BUFLEN))
|
|
|
|
return nets->objs[i];
|
2008-12-04 22:00:14 +00:00
|
|
|
virNetworkObjUnlock(nets->objs[i]);
|
|
|
|
}
|
2008-07-11 10:48:34 +00:00
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2008-10-10 14:50:26 +00:00
|
|
|
virNetworkObjPtr virNetworkFindByName(const virNetworkObjListPtr nets,
|
2008-07-11 10:48:34 +00:00
|
|
|
const char *name)
|
|
|
|
{
|
2008-10-10 14:50:26 +00:00
|
|
|
unsigned int i;
|
|
|
|
|
2008-12-04 22:00:14 +00:00
|
|
|
for (i = 0 ; i < nets->count ; i++) {
|
|
|
|
virNetworkObjLock(nets->objs[i]);
|
2008-10-10 14:50:26 +00:00
|
|
|
if (STREQ(nets->objs[i]->def->name, name))
|
|
|
|
return nets->objs[i];
|
2008-12-04 22:00:14 +00:00
|
|
|
virNetworkObjUnlock(nets->objs[i]);
|
|
|
|
}
|
2008-07-11 10:48:34 +00:00
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
conf: support abstracted interface info in network XML
The network XML is updated in the following ways:
1) The <forward> element can now contain a list of forward interfaces:
<forward .... >
<interface dev='eth10'/>
<interface dev='eth11'/>
<interface dev='eth12'/>
<interface dev='eth13'/>
</forward>
The first of these takes the place of the dev attribute that is
normally in <forward> - when defining a network you can specify
either one, and on output both will be present. If you specify
both on input, they must match.
2) In addition to forward modes of 'nat' and 'route', these new modes
are supported:
private, passthrough, vepa - when this network is referenced by a
domain's interface, it will have the same effect as if the
interface had been defined as type='direct', e.g.:
<interface type='direct'>
<source mode='${mode}' dev='${dev}>
...
</interface>
where ${mode} is one of the three new modes, and ${dev} is an interface
selected from the list given in <forward>.
bridge - if a <forward> dev (or multiple devs) is defined, and
forward mode is 'bridge' this is just like the modes 'private',
'passthrough', and 'vepa' above. If there is no forward dev
specified but a bridge name is given (e.g. "<bridge
name='br0'/>"), then guest interfaces using this network will use
libvirt's "host bridge" mode, equivalent to this:
<interface type='bridge'>
<source bridge='${bridge-name}'/>
...
</interface>
3) A network can have multiple <portgroup> elements, which may be
selected by the guest interface definition (by adding
"portgroup='${name}'" in the <source> element along with the
network name). Currently a portgroup can only contain a
virtportprofile, but the intent is that other configuration items
may be put there int the future (e.g. bandwidth config). When
building a guest's interface, if the <interface> XML itself has no
virtportprofile, and if the requested network has a portgroup with
a name matching the name given in the <interface> (or if one of the
network's portgroups is marked with the "default='yes'" attribute),
the virtportprofile from that portgroup will be used by the
interface.
4) A network can have a virtportprofile defined at the top level,
which will be used by a guest interface when connecting in one of
the 'direct' modes if the guest interface XML itself hasn't
specified any virtportprofile, and if there are also no matching
portgroups on the network.
2011-07-20 03:01:09 +00:00
|
|
|
static void
|
|
|
|
virPortGroupDefClear(virPortGroupDefPtr def)
|
|
|
|
{
|
|
|
|
VIR_FREE(def->name);
|
|
|
|
VIR_FREE(def->virtPortProfile);
|
Adjust naming of network device bandwidth management APIs
Rename virBandwidth to virNetDevBandwidth, and virRate to
virNetDevBandwidthRate.
* src/util/network.c, src/util/network.h: Rename bandwidth
structs and APIs
* src/conf/domain_conf.c, src/conf/domain_conf.h,
src/conf/network_conf.c, src/conf/network_conf.h,
src/lxc/lxc_driver.c, src/network/bridge_driver.c,
src/qemu/qemu_command.c, src/util/macvtap.c,
src/util/macvtap.h, tools/virsh.c: Update for API changes.
2011-11-02 14:29:05 +00:00
|
|
|
virNetDevBandwidthFree(def->bandwidth);
|
2012-08-12 07:51:30 +00:00
|
|
|
virNetDevVlanClear(&def->vlan);
|
2011-07-26 12:42:37 +00:00
|
|
|
def->bandwidth = NULL;
|
conf: support abstracted interface info in network XML
The network XML is updated in the following ways:
1) The <forward> element can now contain a list of forward interfaces:
<forward .... >
<interface dev='eth10'/>
<interface dev='eth11'/>
<interface dev='eth12'/>
<interface dev='eth13'/>
</forward>
The first of these takes the place of the dev attribute that is
normally in <forward> - when defining a network you can specify
either one, and on output both will be present. If you specify
both on input, they must match.
2) In addition to forward modes of 'nat' and 'route', these new modes
are supported:
private, passthrough, vepa - when this network is referenced by a
domain's interface, it will have the same effect as if the
interface had been defined as type='direct', e.g.:
<interface type='direct'>
<source mode='${mode}' dev='${dev}>
...
</interface>
where ${mode} is one of the three new modes, and ${dev} is an interface
selected from the list given in <forward>.
bridge - if a <forward> dev (or multiple devs) is defined, and
forward mode is 'bridge' this is just like the modes 'private',
'passthrough', and 'vepa' above. If there is no forward dev
specified but a bridge name is given (e.g. "<bridge
name='br0'/>"), then guest interfaces using this network will use
libvirt's "host bridge" mode, equivalent to this:
<interface type='bridge'>
<source bridge='${bridge-name}'/>
...
</interface>
3) A network can have multiple <portgroup> elements, which may be
selected by the guest interface definition (by adding
"portgroup='${name}'" in the <source> element along with the
network name). Currently a portgroup can only contain a
virtportprofile, but the intent is that other configuration items
may be put there int the future (e.g. bandwidth config). When
building a guest's interface, if the <interface> XML itself has no
virtportprofile, and if the requested network has a portgroup with
a name matching the name given in the <interface> (or if one of the
network's portgroups is marked with the "default='yes'" attribute),
the virtportprofile from that portgroup will be used by the
interface.
4) A network can have a virtportprofile defined at the top level,
which will be used by a guest interface when connecting in one of
the 'direct' modes if the guest interface XML itself hasn't
specified any virtportprofile, and if there are also no matching
portgroups on the network.
2011-07-20 03:01:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
virNetworkForwardIfDefClear(virNetworkForwardIfDefPtr def)
|
|
|
|
{
|
2012-08-16 15:41:41 +00:00
|
|
|
if (def->type == VIR_NETWORK_FORWARD_HOSTDEV_DEVICE_NETDEV)
|
|
|
|
VIR_FREE(def->device.dev);
|
conf: support abstracted interface info in network XML
The network XML is updated in the following ways:
1) The <forward> element can now contain a list of forward interfaces:
<forward .... >
<interface dev='eth10'/>
<interface dev='eth11'/>
<interface dev='eth12'/>
<interface dev='eth13'/>
</forward>
The first of these takes the place of the dev attribute that is
normally in <forward> - when defining a network you can specify
either one, and on output both will be present. If you specify
both on input, they must match.
2) In addition to forward modes of 'nat' and 'route', these new modes
are supported:
private, passthrough, vepa - when this network is referenced by a
domain's interface, it will have the same effect as if the
interface had been defined as type='direct', e.g.:
<interface type='direct'>
<source mode='${mode}' dev='${dev}>
...
</interface>
where ${mode} is one of the three new modes, and ${dev} is an interface
selected from the list given in <forward>.
bridge - if a <forward> dev (or multiple devs) is defined, and
forward mode is 'bridge' this is just like the modes 'private',
'passthrough', and 'vepa' above. If there is no forward dev
specified but a bridge name is given (e.g. "<bridge
name='br0'/>"), then guest interfaces using this network will use
libvirt's "host bridge" mode, equivalent to this:
<interface type='bridge'>
<source bridge='${bridge-name}'/>
...
</interface>
3) A network can have multiple <portgroup> elements, which may be
selected by the guest interface definition (by adding
"portgroup='${name}'" in the <source> element along with the
network name). Currently a portgroup can only contain a
virtportprofile, but the intent is that other configuration items
may be put there int the future (e.g. bandwidth config). When
building a guest's interface, if the <interface> XML itself has no
virtportprofile, and if the requested network has a portgroup with
a name matching the name given in the <interface> (or if one of the
network's portgroups is marked with the "default='yes'" attribute),
the virtportprofile from that portgroup will be used by the
interface.
4) A network can have a virtportprofile defined at the top level,
which will be used by a guest interface when connecting in one of
the 'direct' modes if the guest interface XML itself hasn't
specified any virtportprofile, and if there are also no matching
portgroups on the network.
2011-07-20 03:01:09 +00:00
|
|
|
}
|
|
|
|
|
2012-08-05 06:32:49 +00:00
|
|
|
static void
|
|
|
|
virNetworkForwardPfDefClear(virNetworkForwardPfDefPtr def)
|
|
|
|
{
|
|
|
|
VIR_FREE(def->dev);
|
|
|
|
}
|
|
|
|
|
2012-09-14 18:57:34 +00:00
|
|
|
static void
|
|
|
|
virNetworkDHCPHostDefClear(virNetworkDHCPHostDefPtr def)
|
|
|
|
{
|
|
|
|
VIR_FREE(def->mac);
|
|
|
|
VIR_FREE(def->name);
|
|
|
|
}
|
|
|
|
|
2010-11-17 18:36:19 +00:00
|
|
|
static void virNetworkIpDefClear(virNetworkIpDefPtr def)
|
|
|
|
{
|
|
|
|
int ii;
|
|
|
|
|
|
|
|
VIR_FREE(def->family);
|
|
|
|
VIR_FREE(def->ranges);
|
|
|
|
|
2012-09-14 18:57:34 +00:00
|
|
|
for (ii = 0 ; ii < def->nhosts && def->hosts ; ii++)
|
|
|
|
virNetworkDHCPHostDefClear(&def->hosts[ii]);
|
2010-11-17 18:36:19 +00:00
|
|
|
|
|
|
|
VIR_FREE(def->hosts);
|
|
|
|
VIR_FREE(def->tftproot);
|
|
|
|
VIR_FREE(def->bootfile);
|
|
|
|
}
|
|
|
|
|
2011-06-24 10:04:36 +00:00
|
|
|
static void virNetworkDNSDefFree(virNetworkDNSDefPtr def)
|
|
|
|
{
|
|
|
|
if (def) {
|
|
|
|
if (def->txtrecords) {
|
|
|
|
while (def->ntxtrecords--) {
|
|
|
|
VIR_FREE(def->txtrecords[def->ntxtrecords].name);
|
|
|
|
VIR_FREE(def->txtrecords[def->ntxtrecords].value);
|
|
|
|
}
|
|
|
|
}
|
2011-08-11 03:28:05 +00:00
|
|
|
VIR_FREE(def->txtrecords);
|
2011-06-24 10:04:40 +00:00
|
|
|
if (def->nhosts) {
|
|
|
|
while (def->nhosts--) {
|
|
|
|
while (def->hosts[def->nhosts].nnames--)
|
|
|
|
VIR_FREE(def->hosts[def->nhosts].names[def->hosts[def->nhosts].nnames]);
|
|
|
|
VIR_FREE(def->hosts[def->nhosts].names);
|
|
|
|
}
|
|
|
|
}
|
2011-08-11 03:28:05 +00:00
|
|
|
VIR_FREE(def->hosts);
|
2012-01-02 14:23:54 +00:00
|
|
|
if (def->nsrvrecords) {
|
|
|
|
while (def->nsrvrecords--) {
|
|
|
|
VIR_FREE(def->srvrecords[def->nsrvrecords].domain);
|
|
|
|
VIR_FREE(def->srvrecords[def->nsrvrecords].service);
|
|
|
|
VIR_FREE(def->srvrecords[def->nsrvrecords].protocol);
|
|
|
|
VIR_FREE(def->srvrecords[def->nsrvrecords].target);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
VIR_FREE(def->srvrecords);
|
2011-06-24 10:04:36 +00:00
|
|
|
VIR_FREE(def);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-07-11 10:48:34 +00:00
|
|
|
void virNetworkDefFree(virNetworkDefPtr def)
|
|
|
|
{
|
2010-11-17 18:36:19 +00:00
|
|
|
int ii;
|
2008-07-11 10:48:34 +00:00
|
|
|
|
|
|
|
if (!def)
|
|
|
|
return;
|
|
|
|
|
|
|
|
VIR_FREE(def->name);
|
|
|
|
VIR_FREE(def->bridge);
|
2008-09-08 12:45:29 +00:00
|
|
|
VIR_FREE(def->domain);
|
2008-07-11 10:48:34 +00:00
|
|
|
|
2011-12-14 10:50:23 +00:00
|
|
|
for (ii = 0 ; ii < def->nForwardPfs && def->forwardPfs ; ii++) {
|
2012-08-05 06:32:49 +00:00
|
|
|
virNetworkForwardPfDefClear(&def->forwardPfs[ii]);
|
2011-12-14 10:50:23 +00:00
|
|
|
}
|
|
|
|
VIR_FREE(def->forwardPfs);
|
|
|
|
|
conf: support abstracted interface info in network XML
The network XML is updated in the following ways:
1) The <forward> element can now contain a list of forward interfaces:
<forward .... >
<interface dev='eth10'/>
<interface dev='eth11'/>
<interface dev='eth12'/>
<interface dev='eth13'/>
</forward>
The first of these takes the place of the dev attribute that is
normally in <forward> - when defining a network you can specify
either one, and on output both will be present. If you specify
both on input, they must match.
2) In addition to forward modes of 'nat' and 'route', these new modes
are supported:
private, passthrough, vepa - when this network is referenced by a
domain's interface, it will have the same effect as if the
interface had been defined as type='direct', e.g.:
<interface type='direct'>
<source mode='${mode}' dev='${dev}>
...
</interface>
where ${mode} is one of the three new modes, and ${dev} is an interface
selected from the list given in <forward>.
bridge - if a <forward> dev (or multiple devs) is defined, and
forward mode is 'bridge' this is just like the modes 'private',
'passthrough', and 'vepa' above. If there is no forward dev
specified but a bridge name is given (e.g. "<bridge
name='br0'/>"), then guest interfaces using this network will use
libvirt's "host bridge" mode, equivalent to this:
<interface type='bridge'>
<source bridge='${bridge-name}'/>
...
</interface>
3) A network can have multiple <portgroup> elements, which may be
selected by the guest interface definition (by adding
"portgroup='${name}'" in the <source> element along with the
network name). Currently a portgroup can only contain a
virtportprofile, but the intent is that other configuration items
may be put there int the future (e.g. bandwidth config). When
building a guest's interface, if the <interface> XML itself has no
virtportprofile, and if the requested network has a portgroup with
a name matching the name given in the <interface> (or if one of the
network's portgroups is marked with the "default='yes'" attribute),
the virtportprofile from that portgroup will be used by the
interface.
4) A network can have a virtportprofile defined at the top level,
which will be used by a guest interface when connecting in one of
the 'direct' modes if the guest interface XML itself hasn't
specified any virtportprofile, and if there are also no matching
portgroups on the network.
2011-07-20 03:01:09 +00:00
|
|
|
for (ii = 0 ; ii < def->nForwardIfs && def->forwardIfs ; ii++) {
|
|
|
|
virNetworkForwardIfDefClear(&def->forwardIfs[ii]);
|
|
|
|
}
|
|
|
|
VIR_FREE(def->forwardIfs);
|
|
|
|
|
2010-11-17 18:36:19 +00:00
|
|
|
for (ii = 0 ; ii < def->nips && def->ips ; ii++) {
|
|
|
|
virNetworkIpDefClear(&def->ips[ii]);
|
2008-08-20 12:50:29 +00:00
|
|
|
}
|
2010-11-17 18:36:19 +00:00
|
|
|
VIR_FREE(def->ips);
|
2009-09-21 20:50:25 +00:00
|
|
|
|
conf: support abstracted interface info in network XML
The network XML is updated in the following ways:
1) The <forward> element can now contain a list of forward interfaces:
<forward .... >
<interface dev='eth10'/>
<interface dev='eth11'/>
<interface dev='eth12'/>
<interface dev='eth13'/>
</forward>
The first of these takes the place of the dev attribute that is
normally in <forward> - when defining a network you can specify
either one, and on output both will be present. If you specify
both on input, they must match.
2) In addition to forward modes of 'nat' and 'route', these new modes
are supported:
private, passthrough, vepa - when this network is referenced by a
domain's interface, it will have the same effect as if the
interface had been defined as type='direct', e.g.:
<interface type='direct'>
<source mode='${mode}' dev='${dev}>
...
</interface>
where ${mode} is one of the three new modes, and ${dev} is an interface
selected from the list given in <forward>.
bridge - if a <forward> dev (or multiple devs) is defined, and
forward mode is 'bridge' this is just like the modes 'private',
'passthrough', and 'vepa' above. If there is no forward dev
specified but a bridge name is given (e.g. "<bridge
name='br0'/>"), then guest interfaces using this network will use
libvirt's "host bridge" mode, equivalent to this:
<interface type='bridge'>
<source bridge='${bridge-name}'/>
...
</interface>
3) A network can have multiple <portgroup> elements, which may be
selected by the guest interface definition (by adding
"portgroup='${name}'" in the <source> element along with the
network name). Currently a portgroup can only contain a
virtportprofile, but the intent is that other configuration items
may be put there int the future (e.g. bandwidth config). When
building a guest's interface, if the <interface> XML itself has no
virtportprofile, and if the requested network has a portgroup with
a name matching the name given in the <interface> (or if one of the
network's portgroups is marked with the "default='yes'" attribute),
the virtportprofile from that portgroup will be used by the
interface.
4) A network can have a virtportprofile defined at the top level,
which will be used by a guest interface when connecting in one of
the 'direct' modes if the guest interface XML itself hasn't
specified any virtportprofile, and if there are also no matching
portgroups on the network.
2011-07-20 03:01:09 +00:00
|
|
|
for (ii = 0; ii < def->nPortGroups && def->portGroups; ii++) {
|
|
|
|
virPortGroupDefClear(&def->portGroups[ii]);
|
|
|
|
}
|
|
|
|
VIR_FREE(def->portGroups);
|
|
|
|
|
2011-06-24 10:04:36 +00:00
|
|
|
virNetworkDNSDefFree(def->dns);
|
|
|
|
|
2011-08-01 08:06:59 +00:00
|
|
|
VIR_FREE(def->virtPortProfile);
|
|
|
|
|
Adjust naming of network device bandwidth management APIs
Rename virBandwidth to virNetDevBandwidth, and virRate to
virNetDevBandwidthRate.
* src/util/network.c, src/util/network.h: Rename bandwidth
structs and APIs
* src/conf/domain_conf.c, src/conf/domain_conf.h,
src/conf/network_conf.c, src/conf/network_conf.h,
src/lxc/lxc_driver.c, src/network/bridge_driver.c,
src/qemu/qemu_command.c, src/util/macvtap.c,
src/util/macvtap.h, tools/virsh.c: Update for API changes.
2011-11-02 14:29:05 +00:00
|
|
|
virNetDevBandwidthFree(def->bandwidth);
|
2012-08-12 07:51:30 +00:00
|
|
|
virNetDevVlanClear(&def->vlan);
|
2008-07-11 10:48:34 +00:00
|
|
|
VIR_FREE(def);
|
|
|
|
}
|
|
|
|
|
|
|
|
void virNetworkObjFree(virNetworkObjPtr net)
|
|
|
|
{
|
|
|
|
if (!net)
|
|
|
|
return;
|
|
|
|
|
|
|
|
virNetworkDefFree(net->def);
|
|
|
|
virNetworkDefFree(net->newDef);
|
|
|
|
|
2009-01-15 19:56:05 +00:00
|
|
|
virMutexDestroy(&net->lock);
|
|
|
|
|
2008-07-11 10:48:34 +00:00
|
|
|
VIR_FREE(net);
|
|
|
|
}
|
|
|
|
|
2008-10-10 14:50:26 +00:00
|
|
|
void virNetworkObjListFree(virNetworkObjListPtr nets)
|
|
|
|
{
|
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
for (i = 0 ; i < nets->count ; i++)
|
|
|
|
virNetworkObjFree(nets->objs[i]);
|
|
|
|
|
|
|
|
VIR_FREE(nets->objs);
|
|
|
|
nets->count = 0;
|
|
|
|
}
|
|
|
|
|
2012-09-14 15:35:35 +00:00
|
|
|
/*
|
|
|
|
* virNetworkObjAssignDef:
|
|
|
|
* @network: the network object to update
|
|
|
|
* @def: the new NetworkDef (will be consumed by this function iff successful)
|
|
|
|
* @live: is this new def the "live" version, or the "persistent" version
|
|
|
|
*
|
|
|
|
* Replace the appropriate copy of the given network's NetworkDef
|
|
|
|
* with def. Use "live" and current state of the network to determine
|
|
|
|
* which to replace.
|
|
|
|
*
|
|
|
|
* Returns 0 on success, -1 on failure.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
virNetworkObjAssignDef(virNetworkObjPtr network,
|
|
|
|
const virNetworkDefPtr def,
|
|
|
|
bool live)
|
2008-07-11 10:48:34 +00:00
|
|
|
{
|
2012-09-14 15:35:35 +00:00
|
|
|
if (virNetworkObjIsActive(network)) {
|
|
|
|
if (live) {
|
2008-07-11 10:48:34 +00:00
|
|
|
virNetworkDefFree(network->def);
|
|
|
|
network->def = def;
|
2012-09-14 15:35:35 +00:00
|
|
|
} else if (network->persistent) {
|
|
|
|
/* save current configuration to be restored on network shutdown */
|
2010-05-17 20:38:59 +00:00
|
|
|
virNetworkDefFree(network->newDef);
|
2008-07-11 10:48:34 +00:00
|
|
|
network->newDef = def;
|
2012-09-14 15:35:35 +00:00
|
|
|
} else {
|
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
_("cannot save persistent config of transient "
|
|
|
|
"network '%s'"), network->def->name);
|
|
|
|
return -1;
|
2008-07-11 10:48:34 +00:00
|
|
|
}
|
2012-09-14 15:35:35 +00:00
|
|
|
} else if (!live) {
|
2012-10-18 14:28:35 +00:00
|
|
|
virNetworkDefFree(network->newDef);
|
2012-09-14 15:35:35 +00:00
|
|
|
virNetworkDefFree(network->def);
|
2012-10-18 14:28:35 +00:00
|
|
|
network->newDef = NULL;
|
2012-09-14 15:35:35 +00:00
|
|
|
network->def = def;
|
|
|
|
} else {
|
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
_("cannot save live config of inactive "
|
|
|
|
"network '%s'"), network->def->name);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
2008-07-11 10:48:34 +00:00
|
|
|
|
2012-09-14 15:35:35 +00:00
|
|
|
/*
|
|
|
|
* virNetworkAssignDef:
|
|
|
|
* @nets: list of all networks
|
|
|
|
* @def: the new NetworkDef (will be consumed by this function iff successful)
|
|
|
|
* @live: is this new def the "live" version, or the "persistent" version
|
|
|
|
*
|
|
|
|
* Either replace the appropriate copy of the NetworkDef with name
|
|
|
|
* matching def->name or, if not found, create a new NetworkObj with
|
|
|
|
* def. For an existing network, use "live" and current state of the
|
|
|
|
* network to determine which to replace.
|
|
|
|
*
|
|
|
|
* Returns -1 on failure, 0 on success.
|
|
|
|
*/
|
|
|
|
virNetworkObjPtr
|
|
|
|
virNetworkAssignDef(virNetworkObjListPtr nets,
|
|
|
|
const virNetworkDefPtr def,
|
|
|
|
bool live)
|
|
|
|
{
|
|
|
|
virNetworkObjPtr network;
|
|
|
|
|
|
|
|
if ((network = virNetworkFindByName(nets, def->name))) {
|
|
|
|
if (virNetworkObjAssignDef(network, def, live) < 0) {
|
|
|
|
return NULL;
|
|
|
|
}
|
2008-07-11 10:48:34 +00:00
|
|
|
return network;
|
|
|
|
}
|
|
|
|
|
2012-09-14 08:53:54 +00:00
|
|
|
if (VIR_REALLOC_N(nets->objs, nets->count + 1) < 0) {
|
|
|
|
virReportOOMError();
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2008-07-11 10:48:34 +00:00
|
|
|
if (VIR_ALLOC(network) < 0) {
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
2008-07-11 10:48:34 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
2009-01-15 19:56:05 +00:00
|
|
|
if (virMutexInit(&network->lock) < 0) {
|
2012-07-18 10:50:44 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"%s", _("cannot initialize mutex"));
|
2009-01-15 19:56:05 +00:00
|
|
|
VIR_FREE(network);
|
|
|
|
return NULL;
|
|
|
|
}
|
2008-12-04 22:00:14 +00:00
|
|
|
virNetworkObjLock(network);
|
2008-07-11 10:48:34 +00:00
|
|
|
network->def = def;
|
|
|
|
|
2008-10-10 14:50:26 +00:00
|
|
|
nets->objs[nets->count] = network;
|
|
|
|
nets->count++;
|
2008-07-11 10:48:34 +00:00
|
|
|
|
|
|
|
return network;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2012-09-14 15:35:35 +00:00
|
|
|
/*
|
|
|
|
* virNetworkObjSetDefTransient:
|
|
|
|
* @network: network object pointer
|
|
|
|
* @live: if true, run this operation even for an inactive network.
|
|
|
|
* this allows freely updated network->def with runtime defaults
|
|
|
|
* before starting the network, which will be discarded on network
|
|
|
|
* shutdown. Any cleanup paths need to be sure to handle newDef if
|
|
|
|
* the network is never started.
|
|
|
|
*
|
|
|
|
* Mark the active network config as transient. Ensures live-only update
|
|
|
|
* operations do not persist past network destroy.
|
|
|
|
*
|
|
|
|
* Returns 0 on success, -1 on failure
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
virNetworkObjSetDefTransient(virNetworkObjPtr network, bool live)
|
|
|
|
{
|
|
|
|
if (!virNetworkObjIsActive(network) && !live)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (!network->persistent || network->newDef)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
network->newDef = virNetworkDefCopy(network->def, VIR_NETWORK_XML_INACTIVE);
|
|
|
|
return network->newDef ? 0 : -1;
|
|
|
|
}
|
|
|
|
|
network: free/null newDef if network fails to start
https://bugzilla.redhat.com/show_bug.cgi?id=866364
pointed out a crash due to virNetworkObjAssignDef free'ing
network->newDef without NULLing it afterward. A fix for this is in
upstream commit b7e9202401ebaa039b8f05acdefda8c24081537a. While the
NULLing of newDef was a legitimate fix, newDef should have already
been empty (NULL) anyway (as indicated in the comment that was deleted
by that commit).
The reason that newDef had a non-NULL value (i.e. the root cause) was
that networkStartNetwork() had failed after populating
network->newDef, but then neglected to free/NULL newDef in the
cleanup.
(A bit of background here: network->newDef should contain the
persistent config of a network when a network is active (and of course
only when it is persisten), and NULL at all other times. There is also
a network->def which should contain the persistent definition of the
network when it is inactive, and the current live state at all other
times. The idea is that you can make changes to network->newDef which
will take effect the next time the network is restarted, but won't
mess with the current state of the network (virDomainObj has a similar
pair of virDomainDefs that behave in the same fashion). Personally I
think there should be a network->live and network->config, and the
location of the persistent config should *always* be in
network->config, but that's for a later cleanup).
Since I love things to be symmetric, I created a new function called
virNetworkObjUnsetDefTransient(), which reverses the effects of
virNetworkObjSetDefTransient(). I don't really like the name of the
new function, but then I also didn't really like the name of the old
one either (it's just named that way to match a similar function in
the domain conf code).
(cherry picked from commit 78fab2770b19097fe5e92ec339a9dd2d62d04bdb)
2012-10-19 16:13:49 +00:00
|
|
|
/* virNetworkObjUnsetDefTransient:
|
|
|
|
*
|
|
|
|
* This *undoes* what virNetworkObjSetDefTransient did.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
virNetworkObjUnsetDefTransient(virNetworkObjPtr network)
|
|
|
|
{
|
|
|
|
if (network->def) {
|
|
|
|
virNetworkDefFree(network->def);
|
|
|
|
network->def = network->newDef;
|
|
|
|
network->newDef = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-09-14 15:35:35 +00:00
|
|
|
/*
|
|
|
|
* virNetworkObjGetPersistentDef:
|
|
|
|
* @network: network object pointer
|
|
|
|
*
|
|
|
|
* Return the persistent network configuration. If network is transient,
|
|
|
|
* return the running config.
|
|
|
|
*
|
|
|
|
* Returns NULL on error, virNetworkDefPtr on success.
|
|
|
|
*/
|
|
|
|
virNetworkDefPtr
|
|
|
|
virNetworkObjGetPersistentDef(virNetworkObjPtr network)
|
|
|
|
{
|
|
|
|
if (network->newDef)
|
|
|
|
return network->newDef;
|
|
|
|
else
|
|
|
|
return network->def;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* virNetworkObjReplacePersistentDef:
|
|
|
|
* @network: network object pointer
|
|
|
|
* @def: new virNetworkDef to replace current persistent config
|
|
|
|
*
|
|
|
|
* Replace the "persistent" network configuration with the given new
|
|
|
|
* virNetworkDef. This pays attention to whether or not the network
|
|
|
|
* is active.
|
|
|
|
*
|
|
|
|
* Returns -1 on error, 0 on success
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
virNetworkObjReplacePersistentDef(virNetworkObjPtr network,
|
|
|
|
virNetworkDefPtr def)
|
|
|
|
{
|
|
|
|
if (virNetworkObjIsActive(network)) {
|
|
|
|
virNetworkDefFree(network->newDef);
|
|
|
|
network->newDef = def;
|
|
|
|
} else {
|
|
|
|
virNetworkDefFree(network->def);
|
|
|
|
network->def = def;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* virNetworkDefCopy:
|
|
|
|
* @def: NetworkDef to copy
|
|
|
|
* @flags: VIR_NETWORK_XML_INACTIVE if appropriate
|
|
|
|
*
|
|
|
|
* make a deep copy of the given NetworkDef
|
|
|
|
*
|
|
|
|
* Returns a new NetworkDef on success, or NULL on failure.
|
|
|
|
*/
|
|
|
|
virNetworkDefPtr
|
|
|
|
virNetworkDefCopy(virNetworkDefPtr def, unsigned int flags)
|
|
|
|
{
|
|
|
|
char *xml = NULL;
|
|
|
|
virNetworkDefPtr newDef = NULL;
|
|
|
|
|
|
|
|
if (!def) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"%s", _("NULL NetworkDef"));
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* deep copy with a format/parse cycle */
|
|
|
|
if (!(xml = virNetworkDefFormat(def, flags)))
|
|
|
|
goto cleanup;
|
|
|
|
newDef = virNetworkDefParseString(xml);
|
|
|
|
cleanup:
|
|
|
|
VIR_FREE(xml);
|
|
|
|
return newDef;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* virNetworkConfigChangeSetup:
|
|
|
|
*
|
|
|
|
* 1) checks whether network state is consistent with the requested
|
|
|
|
* type of modification.
|
|
|
|
*
|
|
|
|
* 3) make sure there are separate "def" and "newDef" copies of
|
|
|
|
* networkDef if appropriate.
|
|
|
|
*
|
|
|
|
* Returns 0 on success, -1 on error.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
virNetworkConfigChangeSetup(virNetworkObjPtr network, unsigned int flags)
|
|
|
|
{
|
|
|
|
bool isActive;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
isActive = virNetworkObjIsActive(network);
|
|
|
|
|
|
|
|
if (!isActive && (flags & VIR_NETWORK_UPDATE_AFFECT_LIVE)) {
|
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
|
|
|
|
_("network is not running"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (flags & VIR_NETWORK_UPDATE_AFFECT_CONFIG) {
|
|
|
|
if (!network->persistent) {
|
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
|
|
|
|
_("cannot change persistent config of a "
|
|
|
|
"transient network"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
/* this should already have been done by the driver, but do it
|
|
|
|
* anyway just in case.
|
|
|
|
*/
|
|
|
|
if (isActive && (virNetworkObjSetDefTransient(network, false) < 0))
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
cleanup:
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2008-10-10 14:50:26 +00:00
|
|
|
void virNetworkRemoveInactive(virNetworkObjListPtr nets,
|
2008-07-11 10:48:34 +00:00
|
|
|
const virNetworkObjPtr net)
|
|
|
|
{
|
2008-10-10 14:50:26 +00:00
|
|
|
unsigned int i;
|
2008-07-11 10:48:34 +00:00
|
|
|
|
2008-12-04 22:00:14 +00:00
|
|
|
virNetworkObjUnlock(net);
|
2008-10-10 14:50:26 +00:00
|
|
|
for (i = 0 ; i < nets->count ; i++) {
|
2008-12-04 22:00:14 +00:00
|
|
|
virNetworkObjLock(nets->objs[i]);
|
2008-10-10 14:50:26 +00:00
|
|
|
if (nets->objs[i] == net) {
|
2008-12-04 22:00:14 +00:00
|
|
|
virNetworkObjUnlock(nets->objs[i]);
|
2008-10-10 14:50:26 +00:00
|
|
|
virNetworkObjFree(nets->objs[i]);
|
2008-07-11 10:48:34 +00:00
|
|
|
|
2008-10-10 14:50:26 +00:00
|
|
|
if (i < (nets->count - 1))
|
|
|
|
memmove(nets->objs + i, nets->objs + i + 1,
|
|
|
|
sizeof(*(nets->objs)) * (nets->count - (i + 1)));
|
2008-07-11 10:48:34 +00:00
|
|
|
|
2008-10-10 14:50:26 +00:00
|
|
|
if (VIR_REALLOC_N(nets->objs, nets->count - 1) < 0) {
|
|
|
|
; /* Failure to reduce memory allocation isn't fatal */
|
|
|
|
}
|
|
|
|
nets->count--;
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
2008-12-04 22:00:14 +00:00
|
|
|
virNetworkObjUnlock(nets->objs[i]);
|
2008-10-10 14:50:26 +00:00
|
|
|
}
|
2008-07-11 10:48:34 +00:00
|
|
|
}
|
|
|
|
|
2010-11-17 18:36:19 +00:00
|
|
|
/* return ips[index], or NULL if there aren't enough ips */
|
|
|
|
virNetworkIpDefPtr
|
|
|
|
virNetworkDefGetIpByIndex(const virNetworkDefPtr def,
|
|
|
|
int family, size_t n)
|
|
|
|
{
|
|
|
|
int ii;
|
|
|
|
|
|
|
|
if (!def->ips || n >= def->nips)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (family == AF_UNSPEC) {
|
|
|
|
return &def->ips[n];
|
|
|
|
}
|
|
|
|
|
|
|
|
/* find the nth ip of type "family" */
|
|
|
|
for (ii = 0; ii < def->nips; ii++) {
|
Santize naming of socket address APIs
The socket address APIs in src/util/network.h either take the
form virSocketAddrXXX, virSocketXXX or virSocketXXXAddr.
Sanitize this so everything is virSocketAddrXXXX, and ensure
that the virSocketAddr parameter is always the first one.
* src/util/network.c, src/util/network.h: Santize socket
address API naming
* src/conf/domain_conf.c, src/conf/network_conf.c,
src/conf/nwfilter_conf.c, src/network/bridge_driver.c,
src/nwfilter/nwfilter_ebiptables_driver.c,
src/nwfilter/nwfilter_learnipaddr.c,
src/qemu/qemu_command.c, src/rpc/virnetsocket.c,
src/util/dnsmasq.c, src/util/iptables.c,
src/util/virnetdev.c, src/vbox/vbox_tmpl.c: Update for
API renaming
2011-11-02 14:06:59 +00:00
|
|
|
if (VIR_SOCKET_ADDR_IS_FAMILY(&def->ips[ii].address, family)
|
2010-11-17 18:36:19 +00:00
|
|
|
&& (n-- <= 0)) {
|
|
|
|
return &def->ips[ii];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* failed to find enough of the right family */
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2010-11-26 22:20:37 +00:00
|
|
|
/* return number of 1 bits in netmask for the network's ipAddress,
|
|
|
|
* or -1 on error
|
|
|
|
*/
|
2010-11-17 18:36:19 +00:00
|
|
|
int virNetworkIpDefPrefix(const virNetworkIpDefPtr def)
|
2010-11-26 22:20:37 +00:00
|
|
|
{
|
2010-11-17 18:36:19 +00:00
|
|
|
if (def->prefix > 0) {
|
|
|
|
return def->prefix;
|
Santize naming of socket address APIs
The socket address APIs in src/util/network.h either take the
form virSocketAddrXXX, virSocketXXX or virSocketXXXAddr.
Sanitize this so everything is virSocketAddrXXXX, and ensure
that the virSocketAddr parameter is always the first one.
* src/util/network.c, src/util/network.h: Santize socket
address API naming
* src/conf/domain_conf.c, src/conf/network_conf.c,
src/conf/nwfilter_conf.c, src/network/bridge_driver.c,
src/nwfilter/nwfilter_ebiptables_driver.c,
src/nwfilter/nwfilter_learnipaddr.c,
src/qemu/qemu_command.c, src/rpc/virnetsocket.c,
src/util/dnsmasq.c, src/util/iptables.c,
src/util/virnetdev.c, src/vbox/vbox_tmpl.c: Update for
API renaming
2011-11-02 14:06:59 +00:00
|
|
|
} else if (VIR_SOCKET_ADDR_VALID(&def->netmask)) {
|
|
|
|
return virSocketAddrGetNumNetmaskBits(&def->netmask);
|
|
|
|
} else if (VIR_SOCKET_ADDR_IS_FAMILY(&def->address, AF_INET)) {
|
2010-11-26 22:20:37 +00:00
|
|
|
/* Return the natural prefix for the network's ip address.
|
|
|
|
* On Linux we could use the IN_CLASSx() macros, but those
|
|
|
|
* aren't guaranteed on all platforms, so we just deal with
|
|
|
|
* the bits ourselves.
|
|
|
|
*/
|
|
|
|
unsigned char octet
|
2010-11-17 18:36:19 +00:00
|
|
|
= ntohl(def->address.data.inet4.sin_addr.s_addr) >> 24;
|
2010-11-26 22:20:37 +00:00
|
|
|
if ((octet & 0x80) == 0) {
|
|
|
|
/* Class A network */
|
|
|
|
return 8;
|
|
|
|
} else if ((octet & 0xC0) == 0x80) {
|
|
|
|
/* Class B network */
|
|
|
|
return 16;
|
|
|
|
} else if ((octet & 0xE0) == 0xC0) {
|
|
|
|
/* Class C network */
|
|
|
|
return 24;
|
|
|
|
}
|
|
|
|
return -1;
|
Santize naming of socket address APIs
The socket address APIs in src/util/network.h either take the
form virSocketAddrXXX, virSocketXXX or virSocketXXXAddr.
Sanitize this so everything is virSocketAddrXXXX, and ensure
that the virSocketAddr parameter is always the first one.
* src/util/network.c, src/util/network.h: Santize socket
address API naming
* src/conf/domain_conf.c, src/conf/network_conf.c,
src/conf/nwfilter_conf.c, src/network/bridge_driver.c,
src/nwfilter/nwfilter_ebiptables_driver.c,
src/nwfilter/nwfilter_learnipaddr.c,
src/qemu/qemu_command.c, src/rpc/virnetsocket.c,
src/util/dnsmasq.c, src/util/iptables.c,
src/util/virnetdev.c, src/vbox/vbox_tmpl.c: Update for
API renaming
2011-11-02 14:06:59 +00:00
|
|
|
} else if (VIR_SOCKET_ADDR_IS_FAMILY(&def->address, AF_INET6)) {
|
2010-11-17 18:36:19 +00:00
|
|
|
return 64;
|
2010-11-26 22:20:37 +00:00
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Fill in a virSocketAddr with the proper netmask for this
|
|
|
|
* definition, based on either the definition's netmask, or its
|
|
|
|
* prefix. Return -1 on error (and set the netmask family to AF_UNSPEC)
|
|
|
|
*/
|
2010-11-17 18:36:19 +00:00
|
|
|
int virNetworkIpDefNetmask(const virNetworkIpDefPtr def,
|
|
|
|
virSocketAddrPtr netmask)
|
2010-11-26 22:20:37 +00:00
|
|
|
{
|
Santize naming of socket address APIs
The socket address APIs in src/util/network.h either take the
form virSocketAddrXXX, virSocketXXX or virSocketXXXAddr.
Sanitize this so everything is virSocketAddrXXXX, and ensure
that the virSocketAddr parameter is always the first one.
* src/util/network.c, src/util/network.h: Santize socket
address API naming
* src/conf/domain_conf.c, src/conf/network_conf.c,
src/conf/nwfilter_conf.c, src/network/bridge_driver.c,
src/nwfilter/nwfilter_ebiptables_driver.c,
src/nwfilter/nwfilter_learnipaddr.c,
src/qemu/qemu_command.c, src/rpc/virnetsocket.c,
src/util/dnsmasq.c, src/util/iptables.c,
src/util/virnetdev.c, src/vbox/vbox_tmpl.c: Update for
API renaming
2011-11-02 14:06:59 +00:00
|
|
|
if (VIR_SOCKET_ADDR_IS_FAMILY(&def->netmask, AF_INET)) {
|
2010-11-26 22:20:37 +00:00
|
|
|
*netmask = def->netmask;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2010-11-17 18:36:19 +00:00
|
|
|
return virSocketAddrPrefixToNetmask(virNetworkIpDefPrefix(def), netmask,
|
Santize naming of socket address APIs
The socket address APIs in src/util/network.h either take the
form virSocketAddrXXX, virSocketXXX or virSocketXXXAddr.
Sanitize this so everything is virSocketAddrXXXX, and ensure
that the virSocketAddr parameter is always the first one.
* src/util/network.c, src/util/network.h: Santize socket
address API naming
* src/conf/domain_conf.c, src/conf/network_conf.c,
src/conf/nwfilter_conf.c, src/network/bridge_driver.c,
src/nwfilter/nwfilter_ebiptables_driver.c,
src/nwfilter/nwfilter_learnipaddr.c,
src/qemu/qemu_command.c, src/rpc/virnetsocket.c,
src/util/dnsmasq.c, src/util/iptables.c,
src/util/virnetdev.c, src/vbox/vbox_tmpl.c: Update for
API renaming
2011-11-02 14:06:59 +00:00
|
|
|
VIR_SOCKET_ADDR_FAMILY(&def->address));
|
2010-11-26 22:20:37 +00:00
|
|
|
}
|
|
|
|
|
2008-07-11 10:48:34 +00:00
|
|
|
|
|
|
|
static int
|
2012-09-14 18:57:34 +00:00
|
|
|
virNetworkDHCPRangeDefParse(const char *networkName,
|
|
|
|
xmlNodePtr node,
|
|
|
|
virNetworkDHCPRangeDefPtr range)
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
char *start = NULL, *end = NULL;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
if (!(start = virXMLPropString(node, "start"))) {
|
|
|
|
virReportError(VIR_ERR_XML_ERROR,
|
|
|
|
_("Missing 'start' attribute in dhcp range for network '%s'"),
|
|
|
|
networkName);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
if (virSocketAddrParse(&range->start, start, AF_UNSPEC) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (!(end = virXMLPropString(node, "end"))) {
|
|
|
|
virReportError(VIR_ERR_XML_ERROR,
|
|
|
|
_("Missing 'end' attribute in dhcp range for network '%s'"),
|
|
|
|
networkName);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
if (virSocketAddrParse(&range->end, end, AF_UNSPEC) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
/* do a sanity check of the range */
|
|
|
|
if (virSocketAddrGetRange(&range->start, &range->end) < 0) {
|
|
|
|
virReportError(VIR_ERR_XML_ERROR,
|
|
|
|
_("Invalid dhcp range '%s' to '%s' in network '%s'"),
|
|
|
|
start, end, networkName);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
VIR_FREE(start);
|
|
|
|
VIR_FREE(end);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
virNetworkDHCPHostDefParse(const char *networkName,
|
|
|
|
xmlNodePtr node,
|
|
|
|
virNetworkDHCPHostDefPtr host,
|
|
|
|
bool partialOkay)
|
|
|
|
{
|
|
|
|
char *mac = NULL, *name = NULL, *ip = NULL;
|
|
|
|
virMacAddr addr;
|
|
|
|
virSocketAddr inaddr;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
mac = virXMLPropString(node, "mac");
|
|
|
|
if (mac != NULL) {
|
|
|
|
if (virMacAddrParse(mac, &addr) < 0) {
|
|
|
|
virReportError(VIR_ERR_XML_ERROR,
|
|
|
|
_("Cannot parse MAC address '%s' in network '%s'"),
|
|
|
|
mac, networkName);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
if (virMacAddrIsMulticast(&addr)) {
|
|
|
|
virReportError(VIR_ERR_XML_ERROR,
|
|
|
|
_("expected unicast mac address, found "
|
|
|
|
"multicast '%s' in network '%s'"),
|
|
|
|
(const char *)mac, networkName);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
name = virXMLPropString(node, "name");
|
|
|
|
if (name && (!c_isalpha(name[0]))) {
|
|
|
|
virReportError(VIR_ERR_XML_ERROR,
|
|
|
|
_("Cannot use name address '%s' in network '%s'"),
|
|
|
|
name, networkName);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
ip = virXMLPropString(node, "ip");
|
|
|
|
if (ip && (virSocketAddrParse(&inaddr, ip, AF_UNSPEC) < 0)) {
|
|
|
|
virReportError(VIR_ERR_XML_ERROR,
|
|
|
|
_("Invalid IP address in static host definition "
|
|
|
|
"for network '%s'"),
|
|
|
|
networkName);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (partialOkay) {
|
|
|
|
/* for search/match, you just need one of the three */
|
|
|
|
if (!(mac || name || ip)) {
|
|
|
|
virReportError(VIR_ERR_XML_ERROR,
|
|
|
|
_("At least one of name, mac, or ip attribute "
|
|
|
|
"must be specified for static host definition "
|
|
|
|
"in network '%s' "),
|
|
|
|
networkName);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/* normal usage - you need at least one MAC address or one host name */
|
|
|
|
if (!(mac || name)) {
|
|
|
|
virReportError(VIR_ERR_XML_ERROR,
|
|
|
|
_("Static host definition in network '%s' "
|
|
|
|
"must have mac or name attribute"),
|
|
|
|
networkName);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
if (!ip) {
|
|
|
|
virReportError(VIR_ERR_XML_ERROR,
|
|
|
|
_("Missing IP address in static host definition "
|
|
|
|
"for network '%s'"),
|
|
|
|
networkName);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
host->mac = mac;
|
|
|
|
mac = NULL;
|
|
|
|
host->name = name;
|
|
|
|
name = NULL;
|
|
|
|
if (ip)
|
|
|
|
host->ip = inaddr;
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
VIR_FREE(mac);
|
|
|
|
VIR_FREE(name);
|
|
|
|
VIR_FREE(ip);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
virNetworkDHCPDefParse(const char *networkName,
|
|
|
|
virNetworkIpDefPtr def,
|
|
|
|
xmlNodePtr node)
|
2010-11-17 18:36:19 +00:00
|
|
|
{
|
2008-07-11 10:48:34 +00:00
|
|
|
|
|
|
|
xmlNodePtr cur;
|
|
|
|
|
|
|
|
cur = node->children;
|
|
|
|
while (cur != NULL) {
|
2008-08-20 12:50:29 +00:00
|
|
|
if (cur->type == XML_ELEMENT_NODE &&
|
|
|
|
xmlStrEqual(cur->name, BAD_CAST "range")) {
|
2008-07-11 10:48:34 +00:00
|
|
|
|
2008-08-20 12:50:29 +00:00
|
|
|
if (VIR_REALLOC_N(def->ranges, def->nranges + 1) < 0) {
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
2008-08-20 12:50:29 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2012-09-14 18:57:34 +00:00
|
|
|
if (virNetworkDHCPRangeDefParse(networkName, cur,
|
|
|
|
&def->ranges[def->nranges]) < 0) {
|
|
|
|
return -1;
|
|
|
|
}
|
2008-08-20 12:50:29 +00:00
|
|
|
def->nranges++;
|
2012-09-14 18:57:34 +00:00
|
|
|
|
2008-08-20 12:50:29 +00:00
|
|
|
} else if (cur->type == XML_ELEMENT_NODE &&
|
|
|
|
xmlStrEqual(cur->name, BAD_CAST "host")) {
|
|
|
|
|
|
|
|
if (VIR_REALLOC_N(def->hosts, def->nhosts + 1) < 0) {
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
2008-08-20 12:50:29 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2012-09-14 18:57:34 +00:00
|
|
|
if (virNetworkDHCPHostDefParse(networkName, cur,
|
|
|
|
&def->hosts[def->nhosts],
|
|
|
|
false) < 0) {
|
|
|
|
return -1;
|
|
|
|
}
|
2008-08-20 12:50:29 +00:00
|
|
|
def->nhosts++;
|
2009-09-21 20:50:25 +00:00
|
|
|
|
|
|
|
} else if (cur->type == XML_ELEMENT_NODE &&
|
|
|
|
xmlStrEqual(cur->name, BAD_CAST "bootp")) {
|
2010-11-24 20:08:55 +00:00
|
|
|
char *file;
|
|
|
|
char *server;
|
Convert virNetwork to use virSocketAddr everywhere
Instead of storing the IP address string in virNetwork related
structs, store the parsed virSocketAddr. This will make it
easier to add IPv6 support in the future, by letting driver
code directly check what address family is present
* src/conf/network_conf.c, src/conf/network_conf.h,
src/network/bridge_driver.c: Convert to use virSocketAddr
in virNetwork, instead of char *.
* src/util/bridge.c, src/util/bridge.h,
src/util/dnsmasq.c, src/util/dnsmasq.h,
src/util/iptables.c, src/util/iptables.h: Convert to
take a virSocketAddr instead of char * for any IP
address parameters
* src/util/network.h: Add macros to determine if an address
is set, and what address family is set.
2010-10-21 12:14:33 +00:00
|
|
|
virSocketAddr inaddr;
|
2010-10-22 12:28:04 +00:00
|
|
|
memset(&inaddr, 0, sizeof(inaddr));
|
2009-09-21 20:50:25 +00:00
|
|
|
|
2010-11-24 20:08:55 +00:00
|
|
|
if (!(file = virXMLPropString(cur, "file"))) {
|
2009-09-21 20:50:25 +00:00
|
|
|
cur = cur->next;
|
|
|
|
continue;
|
|
|
|
}
|
2010-11-24 20:08:55 +00:00
|
|
|
server = virXMLPropString(cur, "server");
|
Convert virNetwork to use virSocketAddr everywhere
Instead of storing the IP address string in virNetwork related
structs, store the parsed virSocketAddr. This will make it
easier to add IPv6 support in the future, by letting driver
code directly check what address family is present
* src/conf/network_conf.c, src/conf/network_conf.h,
src/network/bridge_driver.c: Convert to use virSocketAddr
in virNetwork, instead of char *.
* src/util/bridge.c, src/util/bridge.h,
src/util/dnsmasq.c, src/util/dnsmasq.h,
src/util/iptables.c, src/util/iptables.h: Convert to
take a virSocketAddr instead of char * for any IP
address parameters
* src/util/network.h: Add macros to determine if an address
is set, and what address family is set.
2010-10-21 12:14:33 +00:00
|
|
|
|
2010-10-22 12:28:04 +00:00
|
|
|
if (server &&
|
Santize naming of socket address APIs
The socket address APIs in src/util/network.h either take the
form virSocketAddrXXX, virSocketXXX or virSocketXXXAddr.
Sanitize this so everything is virSocketAddrXXXX, and ensure
that the virSocketAddr parameter is always the first one.
* src/util/network.c, src/util/network.h: Santize socket
address API naming
* src/conf/domain_conf.c, src/conf/network_conf.c,
src/conf/nwfilter_conf.c, src/network/bridge_driver.c,
src/nwfilter/nwfilter_ebiptables_driver.c,
src/nwfilter/nwfilter_learnipaddr.c,
src/qemu/qemu_command.c, src/rpc/virnetsocket.c,
src/util/dnsmasq.c, src/util/iptables.c,
src/util/virnetdev.c, src/vbox/vbox_tmpl.c: Update for
API renaming
2011-11-02 14:06:59 +00:00
|
|
|
virSocketAddrParse(&inaddr, server, AF_UNSPEC) < 0) {
|
2010-11-24 20:29:38 +00:00
|
|
|
VIR_FREE(file);
|
|
|
|
VIR_FREE(server);
|
Convert virNetwork to use virSocketAddr everywhere
Instead of storing the IP address string in virNetwork related
structs, store the parsed virSocketAddr. This will make it
easier to add IPv6 support in the future, by letting driver
code directly check what address family is present
* src/conf/network_conf.c, src/conf/network_conf.h,
src/network/bridge_driver.c: Convert to use virSocketAddr
in virNetwork, instead of char *.
* src/util/bridge.c, src/util/bridge.h,
src/util/dnsmasq.c, src/util/dnsmasq.h,
src/util/iptables.c, src/util/iptables.h: Convert to
take a virSocketAddr instead of char * for any IP
address parameters
* src/util/network.h: Add macros to determine if an address
is set, and what address family is set.
2010-10-21 12:14:33 +00:00
|
|
|
return -1;
|
2010-11-24 20:29:38 +00:00
|
|
|
}
|
2009-09-21 20:50:25 +00:00
|
|
|
|
2010-11-24 20:08:55 +00:00
|
|
|
def->bootfile = file;
|
Convert virNetwork to use virSocketAddr everywhere
Instead of storing the IP address string in virNetwork related
structs, store the parsed virSocketAddr. This will make it
easier to add IPv6 support in the future, by letting driver
code directly check what address family is present
* src/conf/network_conf.c, src/conf/network_conf.h,
src/network/bridge_driver.c: Convert to use virSocketAddr
in virNetwork, instead of char *.
* src/util/bridge.c, src/util/bridge.h,
src/util/dnsmasq.c, src/util/dnsmasq.h,
src/util/iptables.c, src/util/iptables.h: Convert to
take a virSocketAddr instead of char * for any IP
address parameters
* src/util/network.h: Add macros to determine if an address
is set, and what address family is set.
2010-10-21 12:14:33 +00:00
|
|
|
def->bootserver = inaddr;
|
2010-11-24 20:29:38 +00:00
|
|
|
VIR_FREE(server);
|
2008-07-11 10:48:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
cur = cur->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-06-24 10:04:40 +00:00
|
|
|
static int
|
|
|
|
virNetworkDNSHostsDefParseXML(virNetworkDNSDefPtr def,
|
|
|
|
xmlNodePtr node)
|
|
|
|
{
|
|
|
|
xmlNodePtr cur;
|
|
|
|
char *ip;
|
|
|
|
virSocketAddr inaddr;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
if (!(ip = virXMLPropString(node, "ip")) ||
|
Santize naming of socket address APIs
The socket address APIs in src/util/network.h either take the
form virSocketAddrXXX, virSocketXXX or virSocketXXXAddr.
Sanitize this so everything is virSocketAddrXXXX, and ensure
that the virSocketAddr parameter is always the first one.
* src/util/network.c, src/util/network.h: Santize socket
address API naming
* src/conf/domain_conf.c, src/conf/network_conf.c,
src/conf/nwfilter_conf.c, src/network/bridge_driver.c,
src/nwfilter/nwfilter_ebiptables_driver.c,
src/nwfilter/nwfilter_learnipaddr.c,
src/qemu/qemu_command.c, src/rpc/virnetsocket.c,
src/util/dnsmasq.c, src/util/iptables.c,
src/util/virnetdev.c, src/vbox/vbox_tmpl.c: Update for
API renaming
2011-11-02 14:06:59 +00:00
|
|
|
(virSocketAddrParse(&inaddr, ip, AF_UNSPEC) < 0)) {
|
maint: don't permit format strings without %
Any time we have a string with no % passed through gettext, a
translator can inject a % to cause a stack overread. When there
is nothing to format, it's easier to ask for a string that cannot
be used as a formatter, by using a trivial "%s" format instead.
In the past, we have used --disable-nls to catch some of the
offenders, but that doesn't get run very often, and many more
uses have crept in. Syntax check to the rescue!
The syntax check can catch uses such as
virReportError(code,
_("split "
"string"));
by using a sed script to fold context lines into one pattern
space before checking for a string without %.
This patch is just mechanical insertion of %s; there are probably
several messages touched by this patch where we would be better
off giving the user more information than a fixed string.
* cfg.mk (sc_prohibit_diagnostic_without_format): New rule.
* src/datatypes.c (virUnrefConnect, virGetDomain)
(virUnrefDomain, virGetNetwork, virUnrefNetwork, virGetInterface)
(virUnrefInterface, virGetStoragePool, virUnrefStoragePool)
(virGetStorageVol, virUnrefStorageVol, virGetNodeDevice)
(virGetSecret, virUnrefSecret, virGetNWFilter, virUnrefNWFilter)
(virGetDomainSnapshot, virUnrefDomainSnapshot): Add %s wrapper.
* src/lxc/lxc_driver.c (lxcDomainSetBlkioParameters)
(lxcDomainGetBlkioParameters): Likewise.
* src/conf/domain_conf.c (virSecurityDeviceLabelDefParseXML)
(virDomainDiskDefParseXML, virDomainGraphicsDefParseXML):
Likewise.
* src/conf/network_conf.c (virNetworkDNSHostsDefParseXML)
(virNetworkDefParseXML): Likewise.
* src/conf/nwfilter_conf.c (virNWFilterIsValidChainName):
Likewise.
* src/conf/nwfilter_params.c (virNWFilterVarValueCreateSimple)
(virNWFilterVarAccessParse): Likewise.
* src/libvirt.c (virDomainSave, virDomainSaveFlags)
(virDomainRestore, virDomainRestoreFlags)
(virDomainSaveImageGetXMLDesc, virDomainSaveImageDefineXML)
(virDomainCoreDump, virDomainGetXMLDesc)
(virDomainMigrateVersion1, virDomainMigrateVersion2)
(virDomainMigrateVersion3, virDomainMigrate, virDomainMigrate2)
(virStreamSendAll, virStreamRecvAll)
(virDomainSnapshotGetXMLDesc): Likewise.
* src/nwfilter/nwfilter_dhcpsnoop.c (virNWFilterSnoopReqLeaseDel)
(virNWFilterDHCPSnoopReq): Likewise.
* src/openvz/openvz_driver.c (openvzUpdateDevice): Likewise.
* src/openvz/openvz_util.c (openvzKBPerPages): Likewise.
* src/qemu/qemu_cgroup.c (qemuSetupCgroup): Likewise.
* src/qemu/qemu_command.c (qemuBuildHubDevStr, qemuBuildChrChardevStr)
(qemuBuildCommandLine): Likewise.
* src/qemu/qemu_driver.c (qemuDomainGetPercpuStats): Likewise.
* src/qemu/qemu_hotplug.c (qemuDomainAttachNetDevice): Likewise.
* src/rpc/virnetsaslcontext.c (virNetSASLSessionGetIdentity):
Likewise.
* src/rpc/virnetsocket.c (virNetSocketNewConnectUNIX)
(virNetSocketSendFD, virNetSocketRecvFD): Likewise.
* src/storage/storage_backend_disk.c
(virStorageBackendDiskBuildPool): Likewise.
* src/storage/storage_backend_fs.c
(virStorageBackendFileSystemProbe)
(virStorageBackendFileSystemBuild): Likewise.
* src/storage/storage_backend_rbd.c
(virStorageBackendRBDOpenRADOSConn): Likewise.
* src/storage/storage_driver.c (storageVolumeResize): Likewise.
* src/test/test_driver.c (testInterfaceChangeBegin)
(testInterfaceChangeCommit, testInterfaceChangeRollback):
Likewise.
* src/vbox/vbox_tmpl.c (vboxListAllDomains): Likewise.
* src/xenxs/xen_sxpr.c (xenFormatSxprDisk, xenFormatSxpr):
Likewise.
* src/xenxs/xen_xm.c (xenXMConfigGetUUID, xenFormatXMDisk)
(xenFormatXM): Likewise.
2012-07-23 20:33:08 +00:00
|
|
|
virReportError(VIR_ERR_XML_DETAIL, "%s",
|
2012-07-18 10:50:44 +00:00
|
|
|
_("Missing IP address in DNS host definition"));
|
2011-06-24 10:04:40 +00:00
|
|
|
VIR_FREE(ip);
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
VIR_FREE(ip);
|
|
|
|
|
|
|
|
if (VIR_REALLOC_N(def->hosts, def->nhosts + 1) < 0) {
|
|
|
|
virReportOOMError();
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
def->hosts[def->nhosts].ip = inaddr;
|
|
|
|
def->hosts[def->nhosts].nnames = 0;
|
|
|
|
|
|
|
|
if (VIR_ALLOC(def->hosts[def->nhosts].names) < 0) {
|
|
|
|
virReportOOMError();
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
cur = node->children;
|
|
|
|
while (cur != NULL) {
|
|
|
|
if (cur->type == XML_ELEMENT_NODE &&
|
|
|
|
xmlStrEqual(cur->name, BAD_CAST "hostname")) {
|
|
|
|
if (cur->children != NULL) {
|
|
|
|
if (VIR_REALLOC_N(def->hosts[def->nhosts].names, def->hosts[def->nhosts].nnames + 1) < 0) {
|
|
|
|
virReportOOMError();
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
def->hosts[def->nhosts].names[def->hosts[def->nhosts].nnames] = strdup((char *)cur->children->content);
|
|
|
|
def->hosts[def->nhosts].nnames++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
cur = cur->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
def->nhosts++;
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
error:
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2012-01-02 14:23:54 +00:00
|
|
|
static int
|
|
|
|
virNetworkDNSSrvDefParseXML(virNetworkDNSDefPtr def,
|
|
|
|
xmlNodePtr cur,
|
|
|
|
xmlXPathContextPtr ctxt)
|
|
|
|
{
|
2012-06-28 21:42:50 +00:00
|
|
|
char *domain = NULL;
|
|
|
|
char *service = NULL;
|
|
|
|
char *protocol = NULL;
|
|
|
|
char *target = NULL;
|
2012-01-02 14:23:54 +00:00
|
|
|
int port;
|
|
|
|
int priority;
|
|
|
|
int weight;
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
if (!(service = virXMLPropString(cur, "service"))) {
|
2012-07-18 10:50:44 +00:00
|
|
|
virReportError(VIR_ERR_XML_DETAIL,
|
|
|
|
"%s", _("Missing required service attribute in dns srv record"));
|
2012-01-02 14:23:54 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (strlen(service) > DNS_RECORD_LENGTH_SRV) {
|
2012-07-18 10:50:44 +00:00
|
|
|
virReportError(VIR_ERR_XML_DETAIL,
|
|
|
|
_("Service name is too long, limit is %d bytes"),
|
|
|
|
DNS_RECORD_LENGTH_SRV);
|
2012-01-02 14:23:54 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(protocol = virXMLPropString(cur, "protocol"))) {
|
2012-07-18 10:50:44 +00:00
|
|
|
virReportError(VIR_ERR_XML_DETAIL,
|
|
|
|
_("Missing required protocol attribute in dns srv record '%s'"), service);
|
2012-01-02 14:23:54 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check whether protocol value is the supported one */
|
|
|
|
if (STRNEQ(protocol, "tcp") && (STRNEQ(protocol, "udp"))) {
|
2012-07-18 10:50:44 +00:00
|
|
|
virReportError(VIR_ERR_XML_DETAIL,
|
|
|
|
_("Invalid protocol attribute value '%s'"), protocol);
|
2012-01-02 14:23:54 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (VIR_REALLOC_N(def->srvrecords, def->nsrvrecords + 1) < 0) {
|
|
|
|
virReportOOMError();
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
def->srvrecords[def->nsrvrecords].service = service;
|
|
|
|
def->srvrecords[def->nsrvrecords].protocol = protocol;
|
|
|
|
def->srvrecords[def->nsrvrecords].domain = NULL;
|
|
|
|
def->srvrecords[def->nsrvrecords].target = NULL;
|
|
|
|
def->srvrecords[def->nsrvrecords].port = 0;
|
|
|
|
def->srvrecords[def->nsrvrecords].priority = 0;
|
|
|
|
def->srvrecords[def->nsrvrecords].weight = 0;
|
|
|
|
|
|
|
|
/* Following attributes are optional but we had to make sure they're NULL above */
|
|
|
|
if ((target = virXMLPropString(cur, "target")) && (domain = virXMLPropString(cur, "domain"))) {
|
|
|
|
xmlNodePtr save_ctxt = ctxt->node;
|
|
|
|
|
|
|
|
ctxt->node = cur;
|
|
|
|
if (virXPathInt("string(./@port)", ctxt, &port))
|
|
|
|
def->srvrecords[def->nsrvrecords].port = port;
|
|
|
|
|
|
|
|
if (virXPathInt("string(./@priority)", ctxt, &priority))
|
|
|
|
def->srvrecords[def->nsrvrecords].priority = priority;
|
|
|
|
|
|
|
|
if (virXPathInt("string(./@weight)", ctxt, &weight))
|
|
|
|
def->srvrecords[def->nsrvrecords].weight = weight;
|
|
|
|
ctxt->node = save_ctxt;
|
|
|
|
|
|
|
|
def->srvrecords[def->nsrvrecords].domain = domain;
|
|
|
|
def->srvrecords[def->nsrvrecords].target = target;
|
|
|
|
def->srvrecords[def->nsrvrecords].port = port;
|
|
|
|
def->srvrecords[def->nsrvrecords].priority = priority;
|
|
|
|
def->srvrecords[def->nsrvrecords].weight = weight;
|
|
|
|
}
|
|
|
|
|
|
|
|
def->nsrvrecords++;
|
|
|
|
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
error:
|
|
|
|
VIR_FREE(domain);
|
|
|
|
VIR_FREE(service);
|
|
|
|
VIR_FREE(protocol);
|
|
|
|
VIR_FREE(target);
|
|
|
|
|
|
|
|
ret = -1;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-06-24 10:04:36 +00:00
|
|
|
static int
|
|
|
|
virNetworkDNSDefParseXML(virNetworkDNSDefPtr *dnsdef,
|
2012-01-02 14:23:54 +00:00
|
|
|
xmlNodePtr node,
|
|
|
|
xmlXPathContextPtr ctxt)
|
2011-06-24 10:04:36 +00:00
|
|
|
{
|
|
|
|
xmlNodePtr cur;
|
|
|
|
int ret = -1;
|
|
|
|
char *name = NULL;
|
|
|
|
char *value = NULL;
|
|
|
|
virNetworkDNSDefPtr def = NULL;
|
|
|
|
|
|
|
|
if (VIR_ALLOC(def) < 0) {
|
|
|
|
virReportOOMError();
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
cur = node->children;
|
|
|
|
while (cur != NULL) {
|
|
|
|
if (cur->type == XML_ELEMENT_NODE &&
|
|
|
|
xmlStrEqual(cur->name, BAD_CAST "txt")) {
|
|
|
|
if (!(name = virXMLPropString(cur, "name"))) {
|
2012-07-18 10:50:44 +00:00
|
|
|
virReportError(VIR_ERR_XML_DETAIL,
|
|
|
|
"%s", _("Missing required name attribute in dns txt record"));
|
2011-06-24 10:04:36 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
if (!(value = virXMLPropString(cur, "value"))) {
|
2012-07-18 10:50:44 +00:00
|
|
|
virReportError(VIR_ERR_XML_DETAIL,
|
|
|
|
_("Missing required value attribute in dns txt record '%s'"), name);
|
2011-06-24 10:04:36 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (strchr(name, ' ') != NULL) {
|
2012-07-18 10:50:44 +00:00
|
|
|
virReportError(VIR_ERR_XML_DETAIL,
|
|
|
|
_("spaces are not allowed in DNS TXT record names (name is '%s')"), name);
|
2011-06-24 10:04:36 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (VIR_REALLOC_N(def->txtrecords, def->ntxtrecords + 1) < 0) {
|
|
|
|
virReportOOMError();
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
def->txtrecords[def->ntxtrecords].name = name;
|
|
|
|
def->txtrecords[def->ntxtrecords].value = value;
|
|
|
|
def->ntxtrecords++;
|
|
|
|
name = NULL;
|
|
|
|
value = NULL;
|
2012-01-02 14:23:54 +00:00
|
|
|
} else if (cur->type == XML_ELEMENT_NODE &&
|
|
|
|
xmlStrEqual(cur->name, BAD_CAST "srv")) {
|
|
|
|
ret = virNetworkDNSSrvDefParseXML(def, cur, ctxt);
|
|
|
|
if (ret < 0)
|
|
|
|
goto error;
|
2011-06-24 10:04:40 +00:00
|
|
|
} else if (cur->type == XML_ELEMENT_NODE &&
|
|
|
|
xmlStrEqual(cur->name, BAD_CAST "host")) {
|
|
|
|
ret = virNetworkDNSHostsDefParseXML(def, cur);
|
|
|
|
if (ret < 0)
|
|
|
|
goto error;
|
2011-06-24 10:04:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
cur = cur->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
error:
|
|
|
|
if (ret < 0) {
|
|
|
|
VIR_FREE(name);
|
|
|
|
VIR_FREE(value);
|
|
|
|
virNetworkDNSDefFree(def);
|
|
|
|
} else {
|
|
|
|
*dnsdef = def;
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2009-09-21 20:50:25 +00:00
|
|
|
static int
|
2010-11-17 18:36:19 +00:00
|
|
|
virNetworkIPParseXML(const char *networkName,
|
|
|
|
virNetworkIpDefPtr def,
|
|
|
|
xmlNodePtr node,
|
|
|
|
xmlXPathContextPtr ctxt)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* virNetworkIpDef object is already allocated as part of an array.
|
|
|
|
* On failure clear it out, but don't free it.
|
|
|
|
*/
|
|
|
|
|
|
|
|
xmlNodePtr cur, save;
|
|
|
|
char *address = NULL, *netmask = NULL;
|
|
|
|
unsigned long prefix;
|
|
|
|
int result = -1;
|
|
|
|
|
|
|
|
save = ctxt->node;
|
|
|
|
ctxt->node = node;
|
|
|
|
|
|
|
|
/* grab raw data from XML */
|
|
|
|
def->family = virXPathString("string(./@family)", ctxt);
|
|
|
|
address = virXPathString("string(./@address)", ctxt);
|
|
|
|
if (virXPathULong("string(./@prefix)", ctxt, &prefix) < 0)
|
|
|
|
def->prefix = 0;
|
|
|
|
else
|
|
|
|
def->prefix = prefix;
|
|
|
|
|
|
|
|
netmask = virXPathString("string(./@netmask)", ctxt);
|
|
|
|
|
|
|
|
if (address) {
|
Santize naming of socket address APIs
The socket address APIs in src/util/network.h either take the
form virSocketAddrXXX, virSocketXXX or virSocketXXXAddr.
Sanitize this so everything is virSocketAddrXXXX, and ensure
that the virSocketAddr parameter is always the first one.
* src/util/network.c, src/util/network.h: Santize socket
address API naming
* src/conf/domain_conf.c, src/conf/network_conf.c,
src/conf/nwfilter_conf.c, src/network/bridge_driver.c,
src/nwfilter/nwfilter_ebiptables_driver.c,
src/nwfilter/nwfilter_learnipaddr.c,
src/qemu/qemu_command.c, src/rpc/virnetsocket.c,
src/util/dnsmasq.c, src/util/iptables.c,
src/util/virnetdev.c, src/vbox/vbox_tmpl.c: Update for
API renaming
2011-11-02 14:06:59 +00:00
|
|
|
if (virSocketAddrParse(&def->address, address, AF_UNSPEC) < 0) {
|
2012-07-18 10:50:44 +00:00
|
|
|
virReportError(VIR_ERR_XML_ERROR,
|
|
|
|
_("Bad address '%s' in definition of network '%s'"),
|
|
|
|
address, networkName);
|
2010-11-17 18:36:19 +00:00
|
|
|
goto error;
|
|
|
|
}
|
2009-09-21 20:50:25 +00:00
|
|
|
|
2010-11-17 18:36:19 +00:00
|
|
|
}
|
2009-09-21 20:50:25 +00:00
|
|
|
|
2010-11-17 18:36:19 +00:00
|
|
|
/* validate family vs. address */
|
|
|
|
if (def->family == NULL) {
|
Santize naming of socket address APIs
The socket address APIs in src/util/network.h either take the
form virSocketAddrXXX, virSocketXXX or virSocketXXXAddr.
Sanitize this so everything is virSocketAddrXXXX, and ensure
that the virSocketAddr parameter is always the first one.
* src/util/network.c, src/util/network.h: Santize socket
address API naming
* src/conf/domain_conf.c, src/conf/network_conf.c,
src/conf/nwfilter_conf.c, src/network/bridge_driver.c,
src/nwfilter/nwfilter_ebiptables_driver.c,
src/nwfilter/nwfilter_learnipaddr.c,
src/qemu/qemu_command.c, src/rpc/virnetsocket.c,
src/util/dnsmasq.c, src/util/iptables.c,
src/util/virnetdev.c, src/vbox/vbox_tmpl.c: Update for
API renaming
2011-11-02 14:06:59 +00:00
|
|
|
if (!(VIR_SOCKET_ADDR_IS_FAMILY(&def->address, AF_INET) ||
|
|
|
|
VIR_SOCKET_ADDR_IS_FAMILY(&def->address, AF_UNSPEC))) {
|
2012-07-18 10:50:44 +00:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
_("no family specified for non-IPv4 address '%s' in network '%s'"),
|
|
|
|
address, networkName);
|
2010-11-17 18:36:19 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
} else if (STREQ(def->family, "ipv4")) {
|
Santize naming of socket address APIs
The socket address APIs in src/util/network.h either take the
form virSocketAddrXXX, virSocketXXX or virSocketXXXAddr.
Sanitize this so everything is virSocketAddrXXXX, and ensure
that the virSocketAddr parameter is always the first one.
* src/util/network.c, src/util/network.h: Santize socket
address API naming
* src/conf/domain_conf.c, src/conf/network_conf.c,
src/conf/nwfilter_conf.c, src/network/bridge_driver.c,
src/nwfilter/nwfilter_ebiptables_driver.c,
src/nwfilter/nwfilter_learnipaddr.c,
src/qemu/qemu_command.c, src/rpc/virnetsocket.c,
src/util/dnsmasq.c, src/util/iptables.c,
src/util/virnetdev.c, src/vbox/vbox_tmpl.c: Update for
API renaming
2011-11-02 14:06:59 +00:00
|
|
|
if (!VIR_SOCKET_ADDR_IS_FAMILY(&def->address, AF_INET)) {
|
2012-07-18 10:50:44 +00:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
_("family 'ipv4' specified for non-IPv4 address '%s' in network '%s'"),
|
|
|
|
address, networkName);
|
2010-11-17 18:36:19 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
} else if (STREQ(def->family, "ipv6")) {
|
Santize naming of socket address APIs
The socket address APIs in src/util/network.h either take the
form virSocketAddrXXX, virSocketXXX or virSocketXXXAddr.
Sanitize this so everything is virSocketAddrXXXX, and ensure
that the virSocketAddr parameter is always the first one.
* src/util/network.c, src/util/network.h: Santize socket
address API naming
* src/conf/domain_conf.c, src/conf/network_conf.c,
src/conf/nwfilter_conf.c, src/network/bridge_driver.c,
src/nwfilter/nwfilter_ebiptables_driver.c,
src/nwfilter/nwfilter_learnipaddr.c,
src/qemu/qemu_command.c, src/rpc/virnetsocket.c,
src/util/dnsmasq.c, src/util/iptables.c,
src/util/virnetdev.c, src/vbox/vbox_tmpl.c: Update for
API renaming
2011-11-02 14:06:59 +00:00
|
|
|
if (!VIR_SOCKET_ADDR_IS_FAMILY(&def->address, AF_INET6)) {
|
2012-07-18 10:50:44 +00:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
_("family 'ipv6' specified for non-IPv6 address '%s' in network '%s'"),
|
|
|
|
address, networkName);
|
2010-11-17 18:36:19 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
} else {
|
2012-07-18 10:50:44 +00:00
|
|
|
virReportError(VIR_ERR_XML_ERROR,
|
|
|
|
_("Unrecognized family '%s' in definition of network '%s'"),
|
|
|
|
def->family, networkName);
|
2010-11-17 18:36:19 +00:00
|
|
|
goto error;
|
|
|
|
}
|
2009-09-21 20:50:25 +00:00
|
|
|
|
2010-11-17 18:36:19 +00:00
|
|
|
/* parse/validate netmask */
|
|
|
|
if (netmask) {
|
|
|
|
if (address == NULL) {
|
|
|
|
/* netmask is meaningless without an address */
|
2012-07-18 10:50:44 +00:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
_("netmask specified without address in network '%s'"),
|
|
|
|
networkName);
|
2010-11-17 18:36:19 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
Santize naming of socket address APIs
The socket address APIs in src/util/network.h either take the
form virSocketAddrXXX, virSocketXXX or virSocketXXXAddr.
Sanitize this so everything is virSocketAddrXXXX, and ensure
that the virSocketAddr parameter is always the first one.
* src/util/network.c, src/util/network.h: Santize socket
address API naming
* src/conf/domain_conf.c, src/conf/network_conf.c,
src/conf/nwfilter_conf.c, src/network/bridge_driver.c,
src/nwfilter/nwfilter_ebiptables_driver.c,
src/nwfilter/nwfilter_learnipaddr.c,
src/qemu/qemu_command.c, src/rpc/virnetsocket.c,
src/util/dnsmasq.c, src/util/iptables.c,
src/util/virnetdev.c, src/vbox/vbox_tmpl.c: Update for
API renaming
2011-11-02 14:06:59 +00:00
|
|
|
if (!VIR_SOCKET_ADDR_IS_FAMILY(&def->address, AF_INET)) {
|
2012-07-18 10:50:44 +00:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
_("netmask not supported for address '%s' in network '%s' (IPv4 only)"),
|
|
|
|
address, networkName);
|
2010-11-17 18:36:19 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (def->prefix > 0) {
|
|
|
|
/* can't have both netmask and prefix at the same time */
|
2012-07-18 10:50:44 +00:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
_("network '%s' cannot have both prefix='%u' and a netmask"),
|
|
|
|
networkName, def->prefix);
|
2010-11-17 18:36:19 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
Santize naming of socket address APIs
The socket address APIs in src/util/network.h either take the
form virSocketAddrXXX, virSocketXXX or virSocketXXXAddr.
Sanitize this so everything is virSocketAddrXXXX, and ensure
that the virSocketAddr parameter is always the first one.
* src/util/network.c, src/util/network.h: Santize socket
address API naming
* src/conf/domain_conf.c, src/conf/network_conf.c,
src/conf/nwfilter_conf.c, src/network/bridge_driver.c,
src/nwfilter/nwfilter_ebiptables_driver.c,
src/nwfilter/nwfilter_learnipaddr.c,
src/qemu/qemu_command.c, src/rpc/virnetsocket.c,
src/util/dnsmasq.c, src/util/iptables.c,
src/util/virnetdev.c, src/vbox/vbox_tmpl.c: Update for
API renaming
2011-11-02 14:06:59 +00:00
|
|
|
if (virSocketAddrParse(&def->netmask, netmask, AF_UNSPEC) < 0)
|
2010-11-17 18:36:19 +00:00
|
|
|
goto error;
|
|
|
|
|
Santize naming of socket address APIs
The socket address APIs in src/util/network.h either take the
form virSocketAddrXXX, virSocketXXX or virSocketXXXAddr.
Sanitize this so everything is virSocketAddrXXXX, and ensure
that the virSocketAddr parameter is always the first one.
* src/util/network.c, src/util/network.h: Santize socket
address API naming
* src/conf/domain_conf.c, src/conf/network_conf.c,
src/conf/nwfilter_conf.c, src/network/bridge_driver.c,
src/nwfilter/nwfilter_ebiptables_driver.c,
src/nwfilter/nwfilter_learnipaddr.c,
src/qemu/qemu_command.c, src/rpc/virnetsocket.c,
src/util/dnsmasq.c, src/util/iptables.c,
src/util/virnetdev.c, src/vbox/vbox_tmpl.c: Update for
API renaming
2011-11-02 14:06:59 +00:00
|
|
|
if (!VIR_SOCKET_ADDR_IS_FAMILY(&def->netmask, AF_INET)) {
|
2012-07-18 10:50:44 +00:00
|
|
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
|
_("network '%s' has invalid netmask '%s' for address '%s' (both must be IPv4)"),
|
|
|
|
networkName, netmask, address);
|
2010-11-17 18:36:19 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Santize naming of socket address APIs
The socket address APIs in src/util/network.h either take the
form virSocketAddrXXX, virSocketXXX or virSocketXXXAddr.
Sanitize this so everything is virSocketAddrXXXX, and ensure
that the virSocketAddr parameter is always the first one.
* src/util/network.c, src/util/network.h: Santize socket
address API naming
* src/conf/domain_conf.c, src/conf/network_conf.c,
src/conf/nwfilter_conf.c, src/network/bridge_driver.c,
src/nwfilter/nwfilter_ebiptables_driver.c,
src/nwfilter/nwfilter_learnipaddr.c,
src/qemu/qemu_command.c, src/rpc/virnetsocket.c,
src/util/dnsmasq.c, src/util/iptables.c,
src/util/virnetdev.c, src/vbox/vbox_tmpl.c: Update for
API renaming
2011-11-02 14:06:59 +00:00
|
|
|
if (VIR_SOCKET_ADDR_IS_FAMILY(&def->address, AF_INET)) {
|
2010-11-17 18:36:19 +00:00
|
|
|
/* parse IPv4-related info */
|
|
|
|
cur = node->children;
|
|
|
|
while (cur != NULL) {
|
|
|
|
if (cur->type == XML_ELEMENT_NODE &&
|
|
|
|
xmlStrEqual(cur->name, BAD_CAST "dhcp")) {
|
2012-09-14 18:57:34 +00:00
|
|
|
result = virNetworkDHCPDefParse(networkName, def, cur);
|
2010-11-17 18:36:19 +00:00
|
|
|
if (result)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
} else if (cur->type == XML_ELEMENT_NODE &&
|
|
|
|
xmlStrEqual(cur->name, BAD_CAST "tftp")) {
|
|
|
|
char *root;
|
|
|
|
|
|
|
|
if (!(root = virXMLPropString(cur, "root"))) {
|
|
|
|
cur = cur->next;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
def->tftproot = (char *)root;
|
2009-09-21 20:50:25 +00:00
|
|
|
}
|
|
|
|
|
2010-11-17 18:36:19 +00:00
|
|
|
cur = cur->next;
|
2009-09-21 20:50:25 +00:00
|
|
|
}
|
2010-11-17 18:36:19 +00:00
|
|
|
}
|
2009-09-21 20:50:25 +00:00
|
|
|
|
2010-11-17 18:36:19 +00:00
|
|
|
result = 0;
|
|
|
|
|
|
|
|
error:
|
|
|
|
if (result < 0) {
|
|
|
|
virNetworkIpDefClear(def);
|
2009-09-21 20:50:25 +00:00
|
|
|
}
|
2010-11-17 18:36:19 +00:00
|
|
|
VIR_FREE(address);
|
|
|
|
VIR_FREE(netmask);
|
|
|
|
|
|
|
|
ctxt->node = save;
|
|
|
|
return result;
|
2009-09-21 20:50:25 +00:00
|
|
|
}
|
|
|
|
|
conf: support abstracted interface info in network XML
The network XML is updated in the following ways:
1) The <forward> element can now contain a list of forward interfaces:
<forward .... >
<interface dev='eth10'/>
<interface dev='eth11'/>
<interface dev='eth12'/>
<interface dev='eth13'/>
</forward>
The first of these takes the place of the dev attribute that is
normally in <forward> - when defining a network you can specify
either one, and on output both will be present. If you specify
both on input, they must match.
2) In addition to forward modes of 'nat' and 'route', these new modes
are supported:
private, passthrough, vepa - when this network is referenced by a
domain's interface, it will have the same effect as if the
interface had been defined as type='direct', e.g.:
<interface type='direct'>
<source mode='${mode}' dev='${dev}>
...
</interface>
where ${mode} is one of the three new modes, and ${dev} is an interface
selected from the list given in <forward>.
bridge - if a <forward> dev (or multiple devs) is defined, and
forward mode is 'bridge' this is just like the modes 'private',
'passthrough', and 'vepa' above. If there is no forward dev
specified but a bridge name is given (e.g. "<bridge
name='br0'/>"), then guest interfaces using this network will use
libvirt's "host bridge" mode, equivalent to this:
<interface type='bridge'>
<source bridge='${bridge-name}'/>
...
</interface>
3) A network can have multiple <portgroup> elements, which may be
selected by the guest interface definition (by adding
"portgroup='${name}'" in the <source> element along with the
network name). Currently a portgroup can only contain a
virtportprofile, but the intent is that other configuration items
may be put there int the future (e.g. bandwidth config). When
building a guest's interface, if the <interface> XML itself has no
virtportprofile, and if the requested network has a portgroup with
a name matching the name given in the <interface> (or if one of the
network's portgroups is marked with the "default='yes'" attribute),
the virtportprofile from that portgroup will be used by the
interface.
4) A network can have a virtportprofile defined at the top level,
which will be used by a guest interface when connecting in one of
the 'direct' modes if the guest interface XML itself hasn't
specified any virtportprofile, and if there are also no matching
portgroups on the network.
2011-07-20 03:01:09 +00:00
|
|
|
static int
|
|
|
|
virNetworkPortGroupParseXML(virPortGroupDefPtr def,
|
|
|
|
xmlNodePtr node,
|
|
|
|
xmlXPathContextPtr ctxt)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* virPortGroupDef object is already allocated as part of an array.
|
|
|
|
* On failure clear it out, but don't free it.
|
|
|
|
*/
|
|
|
|
|
|
|
|
xmlNodePtr save;
|
|
|
|
xmlNodePtr virtPortNode;
|
2012-08-12 07:51:30 +00:00
|
|
|
xmlNodePtr vlanNode;
|
2011-07-26 12:42:37 +00:00
|
|
|
xmlNodePtr bandwidth_node;
|
conf: support abstracted interface info in network XML
The network XML is updated in the following ways:
1) The <forward> element can now contain a list of forward interfaces:
<forward .... >
<interface dev='eth10'/>
<interface dev='eth11'/>
<interface dev='eth12'/>
<interface dev='eth13'/>
</forward>
The first of these takes the place of the dev attribute that is
normally in <forward> - when defining a network you can specify
either one, and on output both will be present. If you specify
both on input, they must match.
2) In addition to forward modes of 'nat' and 'route', these new modes
are supported:
private, passthrough, vepa - when this network is referenced by a
domain's interface, it will have the same effect as if the
interface had been defined as type='direct', e.g.:
<interface type='direct'>
<source mode='${mode}' dev='${dev}>
...
</interface>
where ${mode} is one of the three new modes, and ${dev} is an interface
selected from the list given in <forward>.
bridge - if a <forward> dev (or multiple devs) is defined, and
forward mode is 'bridge' this is just like the modes 'private',
'passthrough', and 'vepa' above. If there is no forward dev
specified but a bridge name is given (e.g. "<bridge
name='br0'/>"), then guest interfaces using this network will use
libvirt's "host bridge" mode, equivalent to this:
<interface type='bridge'>
<source bridge='${bridge-name}'/>
...
</interface>
3) A network can have multiple <portgroup> elements, which may be
selected by the guest interface definition (by adding
"portgroup='${name}'" in the <source> element along with the
network name). Currently a portgroup can only contain a
virtportprofile, but the intent is that other configuration items
may be put there int the future (e.g. bandwidth config). When
building a guest's interface, if the <interface> XML itself has no
virtportprofile, and if the requested network has a portgroup with
a name matching the name given in the <interface> (or if one of the
network's portgroups is marked with the "default='yes'" attribute),
the virtportprofile from that portgroup will be used by the
interface.
4) A network can have a virtportprofile defined at the top level,
which will be used by a guest interface when connecting in one of
the 'direct' modes if the guest interface XML itself hasn't
specified any virtportprofile, and if there are also no matching
portgroups on the network.
2011-07-20 03:01:09 +00:00
|
|
|
char *isDefault = NULL;
|
|
|
|
|
|
|
|
int result = -1;
|
|
|
|
|
|
|
|
save = ctxt->node;
|
|
|
|
ctxt->node = node;
|
|
|
|
|
|
|
|
/* grab raw data from XML */
|
|
|
|
def->name = virXPathString("string(./@name)", ctxt);
|
|
|
|
isDefault = virXPathString("string(./@default)", ctxt);
|
|
|
|
def->isDefault = isDefault && STRCASEEQ(isDefault, "yes");
|
|
|
|
|
|
|
|
virtPortNode = virXPathNode("./virtualport", ctxt);
|
|
|
|
if (virtPortNode &&
|
conf: support partially-specified <virtualport> in parser and formatter
Until now, all attributes in a <virtualport> parameter list that were
acceptable for a particular type, were also required. There were no
optional attributes.
One of the aims of supporting <virtualport> in libvirt's virtual
networks and portgroups is to allow specifying the group-wide
parameters in the network's virtualport, and merge that with the
interface's virtualport, which will have the instance-specific info
(i.e. the interfaceid or instanceid).
Additionally, the guest's interface XML shouldn't need to know what
type of network connection will be used prior to runtime - it could be
openvswitch, 802.1Qbh, 802.1Qbg, or none of the above - but should
still be able to specify instance-specific info just in case it turns
out to be applicable.
Finally, up to now, the parser for virtualport has always generated a
random instanceid/interfaceid when appropriate, making it impossible
to leave it blank (which is what's required for virtualports within a
network/portprofile definition).
This patch modifies the parser and formatter of the <virtualport>
element in the following ways:
* because most of the attributes in a virNetDevVPortProfile are fixed
size binary data with no reserved values, there is no way to embed a
"this value wasn't specified" sentinel into the existing data. To
solve this problem, the new *_specified fields in the
virNetDevVPortProfile object that were added in a previous patch of
this series are now set when the corresponding attribute is present
during the parse.
* allow parsing/formatting a <virtualport> that has no type set. In
this case, all fields are settable, but all are also optional.
* add a GENERATE_MISSING_DEFAULTS flag to the parser - if this flag is
set and an instanceid/interfaceid is expected but not provided, a
random one will be generated. This was previously the default
behavior, but is now done only for virtualports inside an
<interface> definition, not for those in <network> or <portgroup>.
* add a REQUIRE_ALL_ATTRIBUTES flag to the parser - if this flag is
set the parser will call the new
virNetDevVPortProfileCheckComplete() functions at the end of the
parser to check for any missing attributes (based on type), and
return failure if anything is missing. This used to be default
behavior. Now it is only used for the virtualport defined inside an
interface's <actual> element (by the time you've figured out the
contents of <actual>, you should have all the necessary data to fill
in the entire virtualport)
* add a REQUIRE_TYPE flag to the parser - if this flag is set, the
parser will return an error if the virtualport has no type
attribute. This also was previously the default behavior, but isn't
needed in the case of the virtualport for a type='network' interface
(i.e. the exact type isn't yet known), or the virtualport of a
portgroup (i.e. the portgroup just has modifiers for the network's
virtualport, which *does* require a type) - in those cases, the
check will be done at domain startup, once the final virtualport is
assembled (this is handled in the next patch).
2012-07-31 18:36:51 +00:00
|
|
|
(!(def->virtPortProfile = virNetDevVPortProfileParse(virtPortNode, 0)))) {
|
conf: support abstracted interface info in network XML
The network XML is updated in the following ways:
1) The <forward> element can now contain a list of forward interfaces:
<forward .... >
<interface dev='eth10'/>
<interface dev='eth11'/>
<interface dev='eth12'/>
<interface dev='eth13'/>
</forward>
The first of these takes the place of the dev attribute that is
normally in <forward> - when defining a network you can specify
either one, and on output both will be present. If you specify
both on input, they must match.
2) In addition to forward modes of 'nat' and 'route', these new modes
are supported:
private, passthrough, vepa - when this network is referenced by a
domain's interface, it will have the same effect as if the
interface had been defined as type='direct', e.g.:
<interface type='direct'>
<source mode='${mode}' dev='${dev}>
...
</interface>
where ${mode} is one of the three new modes, and ${dev} is an interface
selected from the list given in <forward>.
bridge - if a <forward> dev (or multiple devs) is defined, and
forward mode is 'bridge' this is just like the modes 'private',
'passthrough', and 'vepa' above. If there is no forward dev
specified but a bridge name is given (e.g. "<bridge
name='br0'/>"), then guest interfaces using this network will use
libvirt's "host bridge" mode, equivalent to this:
<interface type='bridge'>
<source bridge='${bridge-name}'/>
...
</interface>
3) A network can have multiple <portgroup> elements, which may be
selected by the guest interface definition (by adding
"portgroup='${name}'" in the <source> element along with the
network name). Currently a portgroup can only contain a
virtportprofile, but the intent is that other configuration items
may be put there int the future (e.g. bandwidth config). When
building a guest's interface, if the <interface> XML itself has no
virtportprofile, and if the requested network has a portgroup with
a name matching the name given in the <interface> (or if one of the
network's portgroups is marked with the "default='yes'" attribute),
the virtportprofile from that portgroup will be used by the
interface.
4) A network can have a virtportprofile defined at the top level,
which will be used by a guest interface when connecting in one of
the 'direct' modes if the guest interface XML itself hasn't
specified any virtportprofile, and if there are also no matching
portgroups on the network.
2011-07-20 03:01:09 +00:00
|
|
|
goto error;
|
conf: support partially-specified <virtualport> in parser and formatter
Until now, all attributes in a <virtualport> parameter list that were
acceptable for a particular type, were also required. There were no
optional attributes.
One of the aims of supporting <virtualport> in libvirt's virtual
networks and portgroups is to allow specifying the group-wide
parameters in the network's virtualport, and merge that with the
interface's virtualport, which will have the instance-specific info
(i.e. the interfaceid or instanceid).
Additionally, the guest's interface XML shouldn't need to know what
type of network connection will be used prior to runtime - it could be
openvswitch, 802.1Qbh, 802.1Qbg, or none of the above - but should
still be able to specify instance-specific info just in case it turns
out to be applicable.
Finally, up to now, the parser for virtualport has always generated a
random instanceid/interfaceid when appropriate, making it impossible
to leave it blank (which is what's required for virtualports within a
network/portprofile definition).
This patch modifies the parser and formatter of the <virtualport>
element in the following ways:
* because most of the attributes in a virNetDevVPortProfile are fixed
size binary data with no reserved values, there is no way to embed a
"this value wasn't specified" sentinel into the existing data. To
solve this problem, the new *_specified fields in the
virNetDevVPortProfile object that were added in a previous patch of
this series are now set when the corresponding attribute is present
during the parse.
* allow parsing/formatting a <virtualport> that has no type set. In
this case, all fields are settable, but all are also optional.
* add a GENERATE_MISSING_DEFAULTS flag to the parser - if this flag is
set and an instanceid/interfaceid is expected but not provided, a
random one will be generated. This was previously the default
behavior, but is now done only for virtualports inside an
<interface> definition, not for those in <network> or <portgroup>.
* add a REQUIRE_ALL_ATTRIBUTES flag to the parser - if this flag is
set the parser will call the new
virNetDevVPortProfileCheckComplete() functions at the end of the
parser to check for any missing attributes (based on type), and
return failure if anything is missing. This used to be default
behavior. Now it is only used for the virtualport defined inside an
interface's <actual> element (by the time you've figured out the
contents of <actual>, you should have all the necessary data to fill
in the entire virtualport)
* add a REQUIRE_TYPE flag to the parser - if this flag is set, the
parser will return an error if the virtualport has no type
attribute. This also was previously the default behavior, but isn't
needed in the case of the virtualport for a type='network' interface
(i.e. the exact type isn't yet known), or the virtualport of a
portgroup (i.e. the portgroup just has modifiers for the network's
virtualport, which *does* require a type) - in those cases, the
check will be done at domain startup, once the final virtualport is
assembled (this is handled in the next patch).
2012-07-31 18:36:51 +00:00
|
|
|
}
|
conf: support abstracted interface info in network XML
The network XML is updated in the following ways:
1) The <forward> element can now contain a list of forward interfaces:
<forward .... >
<interface dev='eth10'/>
<interface dev='eth11'/>
<interface dev='eth12'/>
<interface dev='eth13'/>
</forward>
The first of these takes the place of the dev attribute that is
normally in <forward> - when defining a network you can specify
either one, and on output both will be present. If you specify
both on input, they must match.
2) In addition to forward modes of 'nat' and 'route', these new modes
are supported:
private, passthrough, vepa - when this network is referenced by a
domain's interface, it will have the same effect as if the
interface had been defined as type='direct', e.g.:
<interface type='direct'>
<source mode='${mode}' dev='${dev}>
...
</interface>
where ${mode} is one of the three new modes, and ${dev} is an interface
selected from the list given in <forward>.
bridge - if a <forward> dev (or multiple devs) is defined, and
forward mode is 'bridge' this is just like the modes 'private',
'passthrough', and 'vepa' above. If there is no forward dev
specified but a bridge name is given (e.g. "<bridge
name='br0'/>"), then guest interfaces using this network will use
libvirt's "host bridge" mode, equivalent to this:
<interface type='bridge'>
<source bridge='${bridge-name}'/>
...
</interface>
3) A network can have multiple <portgroup> elements, which may be
selected by the guest interface definition (by adding
"portgroup='${name}'" in the <source> element along with the
network name). Currently a portgroup can only contain a
virtportprofile, but the intent is that other configuration items
may be put there int the future (e.g. bandwidth config). When
building a guest's interface, if the <interface> XML itself has no
virtportprofile, and if the requested network has a portgroup with
a name matching the name given in the <interface> (or if one of the
network's portgroups is marked with the "default='yes'" attribute),
the virtportprofile from that portgroup will be used by the
interface.
4) A network can have a virtportprofile defined at the top level,
which will be used by a guest interface when connecting in one of
the 'direct' modes if the guest interface XML itself hasn't
specified any virtportprofile, and if there are also no matching
portgroups on the network.
2011-07-20 03:01:09 +00:00
|
|
|
|
2011-07-26 12:42:37 +00:00
|
|
|
bandwidth_node = virXPathNode("./bandwidth", ctxt);
|
|
|
|
if (bandwidth_node &&
|
Adjust naming of network device bandwidth management APIs
Rename virBandwidth to virNetDevBandwidth, and virRate to
virNetDevBandwidthRate.
* src/util/network.c, src/util/network.h: Rename bandwidth
structs and APIs
* src/conf/domain_conf.c, src/conf/domain_conf.h,
src/conf/network_conf.c, src/conf/network_conf.h,
src/lxc/lxc_driver.c, src/network/bridge_driver.c,
src/qemu/qemu_command.c, src/util/macvtap.c,
src/util/macvtap.h, tools/virsh.c: Update for API changes.
2011-11-02 14:29:05 +00:00
|
|
|
!(def->bandwidth = virNetDevBandwidthParse(bandwidth_node))) {
|
2011-07-26 12:42:37 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
2012-08-12 07:51:30 +00:00
|
|
|
vlanNode = virXPathNode("./vlan", ctxt);
|
|
|
|
if (vlanNode && virNetDevVlanParse(vlanNode, ctxt, &def->vlan) < 0)
|
|
|
|
goto error;
|
|
|
|
|
conf: support abstracted interface info in network XML
The network XML is updated in the following ways:
1) The <forward> element can now contain a list of forward interfaces:
<forward .... >
<interface dev='eth10'/>
<interface dev='eth11'/>
<interface dev='eth12'/>
<interface dev='eth13'/>
</forward>
The first of these takes the place of the dev attribute that is
normally in <forward> - when defining a network you can specify
either one, and on output both will be present. If you specify
both on input, they must match.
2) In addition to forward modes of 'nat' and 'route', these new modes
are supported:
private, passthrough, vepa - when this network is referenced by a
domain's interface, it will have the same effect as if the
interface had been defined as type='direct', e.g.:
<interface type='direct'>
<source mode='${mode}' dev='${dev}>
...
</interface>
where ${mode} is one of the three new modes, and ${dev} is an interface
selected from the list given in <forward>.
bridge - if a <forward> dev (or multiple devs) is defined, and
forward mode is 'bridge' this is just like the modes 'private',
'passthrough', and 'vepa' above. If there is no forward dev
specified but a bridge name is given (e.g. "<bridge
name='br0'/>"), then guest interfaces using this network will use
libvirt's "host bridge" mode, equivalent to this:
<interface type='bridge'>
<source bridge='${bridge-name}'/>
...
</interface>
3) A network can have multiple <portgroup> elements, which may be
selected by the guest interface definition (by adding
"portgroup='${name}'" in the <source> element along with the
network name). Currently a portgroup can only contain a
virtportprofile, but the intent is that other configuration items
may be put there int the future (e.g. bandwidth config). When
building a guest's interface, if the <interface> XML itself has no
virtportprofile, and if the requested network has a portgroup with
a name matching the name given in the <interface> (or if one of the
network's portgroups is marked with the "default='yes'" attribute),
the virtportprofile from that portgroup will be used by the
interface.
4) A network can have a virtportprofile defined at the top level,
which will be used by a guest interface when connecting in one of
the 'direct' modes if the guest interface XML itself hasn't
specified any virtportprofile, and if there are also no matching
portgroups on the network.
2011-07-20 03:01:09 +00:00
|
|
|
result = 0;
|
|
|
|
error:
|
|
|
|
if (result < 0) {
|
|
|
|
virPortGroupDefClear(def);
|
|
|
|
}
|
|
|
|
VIR_FREE(isDefault);
|
|
|
|
|
|
|
|
ctxt->node = save;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2008-07-11 10:48:34 +00:00
|
|
|
static virNetworkDefPtr
|
2010-02-10 10:22:52 +00:00
|
|
|
virNetworkDefParseXML(xmlXPathContextPtr ctxt)
|
2008-07-11 10:48:34 +00:00
|
|
|
{
|
|
|
|
virNetworkDefPtr def;
|
|
|
|
char *tmp;
|
conf: support abstracted interface info in network XML
The network XML is updated in the following ways:
1) The <forward> element can now contain a list of forward interfaces:
<forward .... >
<interface dev='eth10'/>
<interface dev='eth11'/>
<interface dev='eth12'/>
<interface dev='eth13'/>
</forward>
The first of these takes the place of the dev attribute that is
normally in <forward> - when defining a network you can specify
either one, and on output both will be present. If you specify
both on input, they must match.
2) In addition to forward modes of 'nat' and 'route', these new modes
are supported:
private, passthrough, vepa - when this network is referenced by a
domain's interface, it will have the same effect as if the
interface had been defined as type='direct', e.g.:
<interface type='direct'>
<source mode='${mode}' dev='${dev}>
...
</interface>
where ${mode} is one of the three new modes, and ${dev} is an interface
selected from the list given in <forward>.
bridge - if a <forward> dev (or multiple devs) is defined, and
forward mode is 'bridge' this is just like the modes 'private',
'passthrough', and 'vepa' above. If there is no forward dev
specified but a bridge name is given (e.g. "<bridge
name='br0'/>"), then guest interfaces using this network will use
libvirt's "host bridge" mode, equivalent to this:
<interface type='bridge'>
<source bridge='${bridge-name}'/>
...
</interface>
3) A network can have multiple <portgroup> elements, which may be
selected by the guest interface definition (by adding
"portgroup='${name}'" in the <source> element along with the
network name). Currently a portgroup can only contain a
virtportprofile, but the intent is that other configuration items
may be put there int the future (e.g. bandwidth config). When
building a guest's interface, if the <interface> XML itself has no
virtportprofile, and if the requested network has a portgroup with
a name matching the name given in the <interface> (or if one of the
network's portgroups is marked with the "default='yes'" attribute),
the virtportprofile from that portgroup will be used by the
interface.
4) A network can have a virtportprofile defined at the top level,
which will be used by a guest interface when connecting in one of
the 'direct' modes if the guest interface XML itself hasn't
specified any virtportprofile, and if there are also no matching
portgroups on the network.
2011-07-20 03:01:09 +00:00
|
|
|
char *stp = NULL;
|
2010-11-17 18:36:19 +00:00
|
|
|
xmlNodePtr *ipNodes = NULL;
|
conf: support abstracted interface info in network XML
The network XML is updated in the following ways:
1) The <forward> element can now contain a list of forward interfaces:
<forward .... >
<interface dev='eth10'/>
<interface dev='eth11'/>
<interface dev='eth12'/>
<interface dev='eth13'/>
</forward>
The first of these takes the place of the dev attribute that is
normally in <forward> - when defining a network you can specify
either one, and on output both will be present. If you specify
both on input, they must match.
2) In addition to forward modes of 'nat' and 'route', these new modes
are supported:
private, passthrough, vepa - when this network is referenced by a
domain's interface, it will have the same effect as if the
interface had been defined as type='direct', e.g.:
<interface type='direct'>
<source mode='${mode}' dev='${dev}>
...
</interface>
where ${mode} is one of the three new modes, and ${dev} is an interface
selected from the list given in <forward>.
bridge - if a <forward> dev (or multiple devs) is defined, and
forward mode is 'bridge' this is just like the modes 'private',
'passthrough', and 'vepa' above. If there is no forward dev
specified but a bridge name is given (e.g. "<bridge
name='br0'/>"), then guest interfaces using this network will use
libvirt's "host bridge" mode, equivalent to this:
<interface type='bridge'>
<source bridge='${bridge-name}'/>
...
</interface>
3) A network can have multiple <portgroup> elements, which may be
selected by the guest interface definition (by adding
"portgroup='${name}'" in the <source> element along with the
network name). Currently a portgroup can only contain a
virtportprofile, but the intent is that other configuration items
may be put there int the future (e.g. bandwidth config). When
building a guest's interface, if the <interface> XML itself has no
virtportprofile, and if the requested network has a portgroup with
a name matching the name given in the <interface> (or if one of the
network's portgroups is marked with the "default='yes'" attribute),
the virtportprofile from that portgroup will be used by the
interface.
4) A network can have a virtportprofile defined at the top level,
which will be used by a guest interface when connecting in one of
the 'direct' modes if the guest interface XML itself hasn't
specified any virtportprofile, and if there are also no matching
portgroups on the network.
2011-07-20 03:01:09 +00:00
|
|
|
xmlNodePtr *portGroupNodes = NULL;
|
|
|
|
xmlNodePtr *forwardIfNodes = NULL;
|
2011-12-14 10:50:23 +00:00
|
|
|
xmlNodePtr *forwardPfNodes = NULL;
|
2012-08-16 15:41:41 +00:00
|
|
|
xmlNodePtr *forwardAddrNodes = NULL;
|
2011-06-24 10:04:36 +00:00
|
|
|
xmlNodePtr dnsNode = NULL;
|
conf: support abstracted interface info in network XML
The network XML is updated in the following ways:
1) The <forward> element can now contain a list of forward interfaces:
<forward .... >
<interface dev='eth10'/>
<interface dev='eth11'/>
<interface dev='eth12'/>
<interface dev='eth13'/>
</forward>
The first of these takes the place of the dev attribute that is
normally in <forward> - when defining a network you can specify
either one, and on output both will be present. If you specify
both on input, they must match.
2) In addition to forward modes of 'nat' and 'route', these new modes
are supported:
private, passthrough, vepa - when this network is referenced by a
domain's interface, it will have the same effect as if the
interface had been defined as type='direct', e.g.:
<interface type='direct'>
<source mode='${mode}' dev='${dev}>
...
</interface>
where ${mode} is one of the three new modes, and ${dev} is an interface
selected from the list given in <forward>.
bridge - if a <forward> dev (or multiple devs) is defined, and
forward mode is 'bridge' this is just like the modes 'private',
'passthrough', and 'vepa' above. If there is no forward dev
specified but a bridge name is given (e.g. "<bridge
name='br0'/>"), then guest interfaces using this network will use
libvirt's "host bridge" mode, equivalent to this:
<interface type='bridge'>
<source bridge='${bridge-name}'/>
...
</interface>
3) A network can have multiple <portgroup> elements, which may be
selected by the guest interface definition (by adding
"portgroup='${name}'" in the <source> element along with the
network name). Currently a portgroup can only contain a
virtportprofile, but the intent is that other configuration items
may be put there int the future (e.g. bandwidth config). When
building a guest's interface, if the <interface> XML itself has no
virtportprofile, and if the requested network has a portgroup with
a name matching the name given in the <interface> (or if one of the
network's portgroups is marked with the "default='yes'" attribute),
the virtportprofile from that portgroup will be used by the
interface.
4) A network can have a virtportprofile defined at the top level,
which will be used by a guest interface when connecting in one of
the 'direct' modes if the guest interface XML itself hasn't
specified any virtportprofile, and if there are also no matching
portgroups on the network.
2011-07-20 03:01:09 +00:00
|
|
|
xmlNodePtr virtPortNode = NULL;
|
|
|
|
xmlNodePtr forwardNode = NULL;
|
2012-08-16 15:41:41 +00:00
|
|
|
int nIps, nPortGroups, nForwardIfs, nForwardPfs, nForwardAddrs;
|
conf: support abstracted interface info in network XML
The network XML is updated in the following ways:
1) The <forward> element can now contain a list of forward interfaces:
<forward .... >
<interface dev='eth10'/>
<interface dev='eth11'/>
<interface dev='eth12'/>
<interface dev='eth13'/>
</forward>
The first of these takes the place of the dev attribute that is
normally in <forward> - when defining a network you can specify
either one, and on output both will be present. If you specify
both on input, they must match.
2) In addition to forward modes of 'nat' and 'route', these new modes
are supported:
private, passthrough, vepa - when this network is referenced by a
domain's interface, it will have the same effect as if the
interface had been defined as type='direct', e.g.:
<interface type='direct'>
<source mode='${mode}' dev='${dev}>
...
</interface>
where ${mode} is one of the three new modes, and ${dev} is an interface
selected from the list given in <forward>.
bridge - if a <forward> dev (or multiple devs) is defined, and
forward mode is 'bridge' this is just like the modes 'private',
'passthrough', and 'vepa' above. If there is no forward dev
specified but a bridge name is given (e.g. "<bridge
name='br0'/>"), then guest interfaces using this network will use
libvirt's "host bridge" mode, equivalent to this:
<interface type='bridge'>
<source bridge='${bridge-name}'/>
...
</interface>
3) A network can have multiple <portgroup> elements, which may be
selected by the guest interface definition (by adding
"portgroup='${name}'" in the <source> element along with the
network name). Currently a portgroup can only contain a
virtportprofile, but the intent is that other configuration items
may be put there int the future (e.g. bandwidth config). When
building a guest's interface, if the <interface> XML itself has no
virtportprofile, and if the requested network has a portgroup with
a name matching the name given in the <interface> (or if one of the
network's portgroups is marked with the "default='yes'" attribute),
the virtportprofile from that portgroup will be used by the
interface.
4) A network can have a virtportprofile defined at the top level,
which will be used by a guest interface when connecting in one of
the 'direct' modes if the guest interface XML itself hasn't
specified any virtportprofile, and if there are also no matching
portgroups on the network.
2011-07-20 03:01:09 +00:00
|
|
|
char *forwardDev = NULL;
|
2012-08-16 15:41:41 +00:00
|
|
|
char *forwardManaged = NULL;
|
|
|
|
char *type = NULL;
|
conf: support abstracted interface info in network XML
The network XML is updated in the following ways:
1) The <forward> element can now contain a list of forward interfaces:
<forward .... >
<interface dev='eth10'/>
<interface dev='eth11'/>
<interface dev='eth12'/>
<interface dev='eth13'/>
</forward>
The first of these takes the place of the dev attribute that is
normally in <forward> - when defining a network you can specify
either one, and on output both will be present. If you specify
both on input, they must match.
2) In addition to forward modes of 'nat' and 'route', these new modes
are supported:
private, passthrough, vepa - when this network is referenced by a
domain's interface, it will have the same effect as if the
interface had been defined as type='direct', e.g.:
<interface type='direct'>
<source mode='${mode}' dev='${dev}>
...
</interface>
where ${mode} is one of the three new modes, and ${dev} is an interface
selected from the list given in <forward>.
bridge - if a <forward> dev (or multiple devs) is defined, and
forward mode is 'bridge' this is just like the modes 'private',
'passthrough', and 'vepa' above. If there is no forward dev
specified but a bridge name is given (e.g. "<bridge
name='br0'/>"), then guest interfaces using this network will use
libvirt's "host bridge" mode, equivalent to this:
<interface type='bridge'>
<source bridge='${bridge-name}'/>
...
</interface>
3) A network can have multiple <portgroup> elements, which may be
selected by the guest interface definition (by adding
"portgroup='${name}'" in the <source> element along with the
network name). Currently a portgroup can only contain a
virtportprofile, but the intent is that other configuration items
may be put there int the future (e.g. bandwidth config). When
building a guest's interface, if the <interface> XML itself has no
virtportprofile, and if the requested network has a portgroup with
a name matching the name given in the <interface> (or if one of the
network's portgroups is marked with the "default='yes'" attribute),
the virtportprofile from that portgroup will be used by the
interface.
4) A network can have a virtportprofile defined at the top level,
which will be used by a guest interface when connecting in one of
the 'direct' modes if the guest interface XML itself hasn't
specified any virtportprofile, and if there are also no matching
portgroups on the network.
2011-07-20 03:01:09 +00:00
|
|
|
xmlNodePtr save = ctxt->node;
|
2011-07-22 14:07:25 +00:00
|
|
|
xmlNodePtr bandwidthNode = NULL;
|
2012-08-12 07:51:30 +00:00
|
|
|
xmlNodePtr vlanNode;
|
2008-07-11 10:48:34 +00:00
|
|
|
|
|
|
|
if (VIR_ALLOC(def) < 0) {
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
2008-07-11 10:48:34 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Extract network name */
|
2010-02-04 21:52:34 +00:00
|
|
|
def->name = virXPathString("string(./name[1])", ctxt);
|
2008-07-11 10:48:34 +00:00
|
|
|
if (!def->name) {
|
2012-07-18 10:50:44 +00:00
|
|
|
virReportError(VIR_ERR_NO_NAME, NULL);
|
2008-07-11 10:48:34 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Extract network uuid */
|
2010-02-04 21:52:34 +00:00
|
|
|
tmp = virXPathString("string(./uuid[1])", ctxt);
|
2008-07-11 10:48:34 +00:00
|
|
|
if (!tmp) {
|
2009-09-04 17:15:51 +00:00
|
|
|
if (virUUIDGenerate(def->uuid)) {
|
2012-07-18 10:50:44 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"%s", _("Failed to generate UUID"));
|
2008-07-11 10:48:34 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (virUUIDParse(tmp, def->uuid) < 0) {
|
|
|
|
VIR_FREE(tmp);
|
2012-07-18 10:50:44 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"%s", _("malformed uuid element"));
|
2008-07-11 10:48:34 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
VIR_FREE(tmp);
|
2012-08-05 20:11:50 +00:00
|
|
|
def->uuid_specified = true;
|
2008-07-11 10:48:34 +00:00
|
|
|
}
|
|
|
|
|
2008-09-08 12:45:29 +00:00
|
|
|
/* Parse network domain information */
|
2010-02-04 21:52:34 +00:00
|
|
|
def->domain = virXPathString("string(./domain[1]/@name)", ctxt);
|
2008-09-08 12:45:29 +00:00
|
|
|
|
2011-07-22 14:07:25 +00:00
|
|
|
if ((bandwidthNode = virXPathNode("./bandwidth", ctxt)) != NULL &&
|
Adjust naming of network device bandwidth management APIs
Rename virBandwidth to virNetDevBandwidth, and virRate to
virNetDevBandwidthRate.
* src/util/network.c, src/util/network.h: Rename bandwidth
structs and APIs
* src/conf/domain_conf.c, src/conf/domain_conf.h,
src/conf/network_conf.c, src/conf/network_conf.h,
src/lxc/lxc_driver.c, src/network/bridge_driver.c,
src/qemu/qemu_command.c, src/util/macvtap.c,
src/util/macvtap.h, tools/virsh.c: Update for API changes.
2011-11-02 14:29:05 +00:00
|
|
|
(def->bandwidth = virNetDevBandwidthParse(bandwidthNode)) == NULL)
|
2011-07-22 14:07:25 +00:00
|
|
|
goto error;
|
|
|
|
|
2012-08-12 07:51:30 +00:00
|
|
|
vlanNode = virXPathNode("./vlan", ctxt);
|
|
|
|
if (vlanNode && virNetDevVlanParse(vlanNode, ctxt, &def->vlan) < 0)
|
|
|
|
goto error;
|
|
|
|
|
2008-07-11 10:48:34 +00:00
|
|
|
/* Parse bridge information */
|
2010-02-04 21:52:34 +00:00
|
|
|
def->bridge = virXPathString("string(./bridge[1]/@name)", ctxt);
|
conf: support abstracted interface info in network XML
The network XML is updated in the following ways:
1) The <forward> element can now contain a list of forward interfaces:
<forward .... >
<interface dev='eth10'/>
<interface dev='eth11'/>
<interface dev='eth12'/>
<interface dev='eth13'/>
</forward>
The first of these takes the place of the dev attribute that is
normally in <forward> - when defining a network you can specify
either one, and on output both will be present. If you specify
both on input, they must match.
2) In addition to forward modes of 'nat' and 'route', these new modes
are supported:
private, passthrough, vepa - when this network is referenced by a
domain's interface, it will have the same effect as if the
interface had been defined as type='direct', e.g.:
<interface type='direct'>
<source mode='${mode}' dev='${dev}>
...
</interface>
where ${mode} is one of the three new modes, and ${dev} is an interface
selected from the list given in <forward>.
bridge - if a <forward> dev (or multiple devs) is defined, and
forward mode is 'bridge' this is just like the modes 'private',
'passthrough', and 'vepa' above. If there is no forward dev
specified but a bridge name is given (e.g. "<bridge
name='br0'/>"), then guest interfaces using this network will use
libvirt's "host bridge" mode, equivalent to this:
<interface type='bridge'>
<source bridge='${bridge-name}'/>
...
</interface>
3) A network can have multiple <portgroup> elements, which may be
selected by the guest interface definition (by adding
"portgroup='${name}'" in the <source> element along with the
network name). Currently a portgroup can only contain a
virtportprofile, but the intent is that other configuration items
may be put there int the future (e.g. bandwidth config). When
building a guest's interface, if the <interface> XML itself has no
virtportprofile, and if the requested network has a portgroup with
a name matching the name given in the <interface> (or if one of the
network's portgroups is marked with the "default='yes'" attribute),
the virtportprofile from that portgroup will be used by the
interface.
4) A network can have a virtportprofile defined at the top level,
which will be used by a guest interface when connecting in one of
the 'direct' modes if the guest interface XML itself hasn't
specified any virtportprofile, and if there are also no matching
portgroups on the network.
2011-07-20 03:01:09 +00:00
|
|
|
stp = virXPathString("string(./bridge[1]/@stp)", ctxt);
|
2008-07-11 10:48:34 +00:00
|
|
|
|
2010-02-04 21:52:34 +00:00
|
|
|
if (virXPathULong("string(./bridge[1]/@delay)", ctxt, &def->delay) < 0)
|
2008-07-11 10:48:34 +00:00
|
|
|
def->delay = 0;
|
|
|
|
|
Give each virtual network bridge its own fixed MAC address
This fixes https://bugzilla.redhat.com/show_bug.cgi?id=609463
The problem was that, since a bridge always acquires the MAC address
of the connected interface with the numerically lowest MAC, as guests
are started and stopped, it was possible for the MAC address to change
over time, and this change in the network was being detected by
Windows 7 (it sees the MAC of the default route change), so on each
reboot it would bring up a dialog box asking about this "new network".
The solution is to create a dummy tap interface with a MAC guaranteed
to be lower than any guest interface's MAC, and attach that tap to the
bridge as soon as it's created. Since all guest MAC addresses start
with 0xFE, we can just generate a MAC with the standard "0x52, 0x54,
0" prefix, and it's guaranteed to always win (physical interfaces are
never connected to these bridges, so we don't need to worry about
competing numerically with them).
Note that the dummy tap is never set to IFF_UP state - that's not
necessary in order for the bridge to take its MAC, and not setting it
to UP eliminates the clutter of having an (eg) "virbr0-nic" displayed
in the output of the ifconfig command.
I chose to not auto-generate the MAC address in the network XML
parser, as there are likely to be consumers of that API that don't
need or want to have a MAC address associated with the
bridge.
Instead, in bridge_driver.c when the network is being defined, if
there is no MAC, one is generated. To account for virtual network
configs that already exist when upgrading from an older version of
libvirt, I've added a %post script to the specfile that searches for
all network definitions in both the config directory
(/etc/libvirt/qemu/networks) and the state directory
(/var/lib/libvirt/network) that are missing a mac address, generates a
random address, and adds it to the config (and a matching address to
the state file, if there is one).
docs/formatnetwork.html.in: document <mac address.../>
docs/schemas/network.rng: add nac address to schema
libvirt.spec.in: %post script to update existing networks
src/conf/network_conf.[ch]: parse and format <mac address.../>
src/libvirt_private.syms: export a couple private symbols we need
src/network/bridge_driver.c:
auto-generate mac address when needed,
create dummy interface if mac address is present.
tests/networkxml2xmlin/isolated-network.xml
tests/networkxml2xmlin/routed-network.xml
tests/networkxml2xmlout/isolated-network.xml
tests/networkxml2xmlout/routed-network.xml: add mac address to some tests
2011-02-09 08:28:12 +00:00
|
|
|
tmp = virXPathString("string(./mac[1]/@address)", ctxt);
|
|
|
|
if (tmp) {
|
2012-07-17 12:07:59 +00:00
|
|
|
if (virMacAddrParse(tmp, &def->mac) < 0) {
|
2012-07-18 10:50:44 +00:00
|
|
|
virReportError(VIR_ERR_XML_ERROR,
|
|
|
|
_("Invalid bridge mac address '%s' in network '%s'"),
|
|
|
|
tmp, def->name);
|
Give each virtual network bridge its own fixed MAC address
This fixes https://bugzilla.redhat.com/show_bug.cgi?id=609463
The problem was that, since a bridge always acquires the MAC address
of the connected interface with the numerically lowest MAC, as guests
are started and stopped, it was possible for the MAC address to change
over time, and this change in the network was being detected by
Windows 7 (it sees the MAC of the default route change), so on each
reboot it would bring up a dialog box asking about this "new network".
The solution is to create a dummy tap interface with a MAC guaranteed
to be lower than any guest interface's MAC, and attach that tap to the
bridge as soon as it's created. Since all guest MAC addresses start
with 0xFE, we can just generate a MAC with the standard "0x52, 0x54,
0" prefix, and it's guaranteed to always win (physical interfaces are
never connected to these bridges, so we don't need to worry about
competing numerically with them).
Note that the dummy tap is never set to IFF_UP state - that's not
necessary in order for the bridge to take its MAC, and not setting it
to UP eliminates the clutter of having an (eg) "virbr0-nic" displayed
in the output of the ifconfig command.
I chose to not auto-generate the MAC address in the network XML
parser, as there are likely to be consumers of that API that don't
need or want to have a MAC address associated with the
bridge.
Instead, in bridge_driver.c when the network is being defined, if
there is no MAC, one is generated. To account for virtual network
configs that already exist when upgrading from an older version of
libvirt, I've added a %post script to the specfile that searches for
all network definitions in both the config directory
(/etc/libvirt/qemu/networks) and the state directory
(/var/lib/libvirt/network) that are missing a mac address, generates a
random address, and adds it to the config (and a matching address to
the state file, if there is one).
docs/formatnetwork.html.in: document <mac address.../>
docs/schemas/network.rng: add nac address to schema
libvirt.spec.in: %post script to update existing networks
src/conf/network_conf.[ch]: parse and format <mac address.../>
src/libvirt_private.syms: export a couple private symbols we need
src/network/bridge_driver.c:
auto-generate mac address when needed,
create dummy interface if mac address is present.
tests/networkxml2xmlin/isolated-network.xml
tests/networkxml2xmlin/routed-network.xml
tests/networkxml2xmlout/isolated-network.xml
tests/networkxml2xmlout/routed-network.xml: add mac address to some tests
2011-02-09 08:28:12 +00:00
|
|
|
VIR_FREE(tmp);
|
|
|
|
goto error;
|
|
|
|
}
|
2012-07-17 12:07:59 +00:00
|
|
|
if (virMacAddrIsMulticast(&def->mac)) {
|
2012-07-18 10:50:44 +00:00
|
|
|
virReportError(VIR_ERR_XML_ERROR,
|
|
|
|
_("Invalid multicast bridge mac address '%s' in network '%s'"),
|
|
|
|
tmp, def->name);
|
2012-03-19 16:49:17 +00:00
|
|
|
VIR_FREE(tmp);
|
|
|
|
goto error;
|
|
|
|
}
|
Give each virtual network bridge its own fixed MAC address
This fixes https://bugzilla.redhat.com/show_bug.cgi?id=609463
The problem was that, since a bridge always acquires the MAC address
of the connected interface with the numerically lowest MAC, as guests
are started and stopped, it was possible for the MAC address to change
over time, and this change in the network was being detected by
Windows 7 (it sees the MAC of the default route change), so on each
reboot it would bring up a dialog box asking about this "new network".
The solution is to create a dummy tap interface with a MAC guaranteed
to be lower than any guest interface's MAC, and attach that tap to the
bridge as soon as it's created. Since all guest MAC addresses start
with 0xFE, we can just generate a MAC with the standard "0x52, 0x54,
0" prefix, and it's guaranteed to always win (physical interfaces are
never connected to these bridges, so we don't need to worry about
competing numerically with them).
Note that the dummy tap is never set to IFF_UP state - that's not
necessary in order for the bridge to take its MAC, and not setting it
to UP eliminates the clutter of having an (eg) "virbr0-nic" displayed
in the output of the ifconfig command.
I chose to not auto-generate the MAC address in the network XML
parser, as there are likely to be consumers of that API that don't
need or want to have a MAC address associated with the
bridge.
Instead, in bridge_driver.c when the network is being defined, if
there is no MAC, one is generated. To account for virtual network
configs that already exist when upgrading from an older version of
libvirt, I've added a %post script to the specfile that searches for
all network definitions in both the config directory
(/etc/libvirt/qemu/networks) and the state directory
(/var/lib/libvirt/network) that are missing a mac address, generates a
random address, and adds it to the config (and a matching address to
the state file, if there is one).
docs/formatnetwork.html.in: document <mac address.../>
docs/schemas/network.rng: add nac address to schema
libvirt.spec.in: %post script to update existing networks
src/conf/network_conf.[ch]: parse and format <mac address.../>
src/libvirt_private.syms: export a couple private symbols we need
src/network/bridge_driver.c:
auto-generate mac address when needed,
create dummy interface if mac address is present.
tests/networkxml2xmlin/isolated-network.xml
tests/networkxml2xmlin/routed-network.xml
tests/networkxml2xmlout/isolated-network.xml
tests/networkxml2xmlout/routed-network.xml: add mac address to some tests
2011-02-09 08:28:12 +00:00
|
|
|
VIR_FREE(tmp);
|
|
|
|
def->mac_specified = true;
|
|
|
|
}
|
|
|
|
|
2011-06-24 10:04:36 +00:00
|
|
|
dnsNode = virXPathNode("./dns", ctxt);
|
|
|
|
if (dnsNode != NULL) {
|
2012-01-02 14:23:54 +00:00
|
|
|
if (virNetworkDNSDefParseXML(&def->dns, dnsNode, ctxt) < 0)
|
2011-06-24 10:04:36 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
conf: support abstracted interface info in network XML
The network XML is updated in the following ways:
1) The <forward> element can now contain a list of forward interfaces:
<forward .... >
<interface dev='eth10'/>
<interface dev='eth11'/>
<interface dev='eth12'/>
<interface dev='eth13'/>
</forward>
The first of these takes the place of the dev attribute that is
normally in <forward> - when defining a network you can specify
either one, and on output both will be present. If you specify
both on input, they must match.
2) In addition to forward modes of 'nat' and 'route', these new modes
are supported:
private, passthrough, vepa - when this network is referenced by a
domain's interface, it will have the same effect as if the
interface had been defined as type='direct', e.g.:
<interface type='direct'>
<source mode='${mode}' dev='${dev}>
...
</interface>
where ${mode} is one of the three new modes, and ${dev} is an interface
selected from the list given in <forward>.
bridge - if a <forward> dev (or multiple devs) is defined, and
forward mode is 'bridge' this is just like the modes 'private',
'passthrough', and 'vepa' above. If there is no forward dev
specified but a bridge name is given (e.g. "<bridge
name='br0'/>"), then guest interfaces using this network will use
libvirt's "host bridge" mode, equivalent to this:
<interface type='bridge'>
<source bridge='${bridge-name}'/>
...
</interface>
3) A network can have multiple <portgroup> elements, which may be
selected by the guest interface definition (by adding
"portgroup='${name}'" in the <source> element along with the
network name). Currently a portgroup can only contain a
virtportprofile, but the intent is that other configuration items
may be put there int the future (e.g. bandwidth config). When
building a guest's interface, if the <interface> XML itself has no
virtportprofile, and if the requested network has a portgroup with
a name matching the name given in the <interface> (or if one of the
network's portgroups is marked with the "default='yes'" attribute),
the virtportprofile from that portgroup will be used by the
interface.
4) A network can have a virtportprofile defined at the top level,
which will be used by a guest interface when connecting in one of
the 'direct' modes if the guest interface XML itself hasn't
specified any virtportprofile, and if there are also no matching
portgroups on the network.
2011-07-20 03:01:09 +00:00
|
|
|
virtPortNode = virXPathNode("./virtualport", ctxt);
|
|
|
|
if (virtPortNode &&
|
conf: support partially-specified <virtualport> in parser and formatter
Until now, all attributes in a <virtualport> parameter list that were
acceptable for a particular type, were also required. There were no
optional attributes.
One of the aims of supporting <virtualport> in libvirt's virtual
networks and portgroups is to allow specifying the group-wide
parameters in the network's virtualport, and merge that with the
interface's virtualport, which will have the instance-specific info
(i.e. the interfaceid or instanceid).
Additionally, the guest's interface XML shouldn't need to know what
type of network connection will be used prior to runtime - it could be
openvswitch, 802.1Qbh, 802.1Qbg, or none of the above - but should
still be able to specify instance-specific info just in case it turns
out to be applicable.
Finally, up to now, the parser for virtualport has always generated a
random instanceid/interfaceid when appropriate, making it impossible
to leave it blank (which is what's required for virtualports within a
network/portprofile definition).
This patch modifies the parser and formatter of the <virtualport>
element in the following ways:
* because most of the attributes in a virNetDevVPortProfile are fixed
size binary data with no reserved values, there is no way to embed a
"this value wasn't specified" sentinel into the existing data. To
solve this problem, the new *_specified fields in the
virNetDevVPortProfile object that were added in a previous patch of
this series are now set when the corresponding attribute is present
during the parse.
* allow parsing/formatting a <virtualport> that has no type set. In
this case, all fields are settable, but all are also optional.
* add a GENERATE_MISSING_DEFAULTS flag to the parser - if this flag is
set and an instanceid/interfaceid is expected but not provided, a
random one will be generated. This was previously the default
behavior, but is now done only for virtualports inside an
<interface> definition, not for those in <network> or <portgroup>.
* add a REQUIRE_ALL_ATTRIBUTES flag to the parser - if this flag is
set the parser will call the new
virNetDevVPortProfileCheckComplete() functions at the end of the
parser to check for any missing attributes (based on type), and
return failure if anything is missing. This used to be default
behavior. Now it is only used for the virtualport defined inside an
interface's <actual> element (by the time you've figured out the
contents of <actual>, you should have all the necessary data to fill
in the entire virtualport)
* add a REQUIRE_TYPE flag to the parser - if this flag is set, the
parser will return an error if the virtualport has no type
attribute. This also was previously the default behavior, but isn't
needed in the case of the virtualport for a type='network' interface
(i.e. the exact type isn't yet known), or the virtualport of a
portgroup (i.e. the portgroup just has modifiers for the network's
virtualport, which *does* require a type) - in those cases, the
check will be done at domain startup, once the final virtualport is
assembled (this is handled in the next patch).
2012-07-31 18:36:51 +00:00
|
|
|
(!(def->virtPortProfile = virNetDevVPortProfileParse(virtPortNode,
|
|
|
|
VIR_VPORT_XML_REQUIRE_TYPE)))) {
|
conf: support abstracted interface info in network XML
The network XML is updated in the following ways:
1) The <forward> element can now contain a list of forward interfaces:
<forward .... >
<interface dev='eth10'/>
<interface dev='eth11'/>
<interface dev='eth12'/>
<interface dev='eth13'/>
</forward>
The first of these takes the place of the dev attribute that is
normally in <forward> - when defining a network you can specify
either one, and on output both will be present. If you specify
both on input, they must match.
2) In addition to forward modes of 'nat' and 'route', these new modes
are supported:
private, passthrough, vepa - when this network is referenced by a
domain's interface, it will have the same effect as if the
interface had been defined as type='direct', e.g.:
<interface type='direct'>
<source mode='${mode}' dev='${dev}>
...
</interface>
where ${mode} is one of the three new modes, and ${dev} is an interface
selected from the list given in <forward>.
bridge - if a <forward> dev (or multiple devs) is defined, and
forward mode is 'bridge' this is just like the modes 'private',
'passthrough', and 'vepa' above. If there is no forward dev
specified but a bridge name is given (e.g. "<bridge
name='br0'/>"), then guest interfaces using this network will use
libvirt's "host bridge" mode, equivalent to this:
<interface type='bridge'>
<source bridge='${bridge-name}'/>
...
</interface>
3) A network can have multiple <portgroup> elements, which may be
selected by the guest interface definition (by adding
"portgroup='${name}'" in the <source> element along with the
network name). Currently a portgroup can only contain a
virtportprofile, but the intent is that other configuration items
may be put there int the future (e.g. bandwidth config). When
building a guest's interface, if the <interface> XML itself has no
virtportprofile, and if the requested network has a portgroup with
a name matching the name given in the <interface> (or if one of the
network's portgroups is marked with the "default='yes'" attribute),
the virtportprofile from that portgroup will be used by the
interface.
4) A network can have a virtportprofile defined at the top level,
which will be used by a guest interface when connecting in one of
the 'direct' modes if the guest interface XML itself hasn't
specified any virtportprofile, and if there are also no matching
portgroups on the network.
2011-07-20 03:01:09 +00:00
|
|
|
goto error;
|
conf: support partially-specified <virtualport> in parser and formatter
Until now, all attributes in a <virtualport> parameter list that were
acceptable for a particular type, were also required. There were no
optional attributes.
One of the aims of supporting <virtualport> in libvirt's virtual
networks and portgroups is to allow specifying the group-wide
parameters in the network's virtualport, and merge that with the
interface's virtualport, which will have the instance-specific info
(i.e. the interfaceid or instanceid).
Additionally, the guest's interface XML shouldn't need to know what
type of network connection will be used prior to runtime - it could be
openvswitch, 802.1Qbh, 802.1Qbg, or none of the above - but should
still be able to specify instance-specific info just in case it turns
out to be applicable.
Finally, up to now, the parser for virtualport has always generated a
random instanceid/interfaceid when appropriate, making it impossible
to leave it blank (which is what's required for virtualports within a
network/portprofile definition).
This patch modifies the parser and formatter of the <virtualport>
element in the following ways:
* because most of the attributes in a virNetDevVPortProfile are fixed
size binary data with no reserved values, there is no way to embed a
"this value wasn't specified" sentinel into the existing data. To
solve this problem, the new *_specified fields in the
virNetDevVPortProfile object that were added in a previous patch of
this series are now set when the corresponding attribute is present
during the parse.
* allow parsing/formatting a <virtualport> that has no type set. In
this case, all fields are settable, but all are also optional.
* add a GENERATE_MISSING_DEFAULTS flag to the parser - if this flag is
set and an instanceid/interfaceid is expected but not provided, a
random one will be generated. This was previously the default
behavior, but is now done only for virtualports inside an
<interface> definition, not for those in <network> or <portgroup>.
* add a REQUIRE_ALL_ATTRIBUTES flag to the parser - if this flag is
set the parser will call the new
virNetDevVPortProfileCheckComplete() functions at the end of the
parser to check for any missing attributes (based on type), and
return failure if anything is missing. This used to be default
behavior. Now it is only used for the virtualport defined inside an
interface's <actual> element (by the time you've figured out the
contents of <actual>, you should have all the necessary data to fill
in the entire virtualport)
* add a REQUIRE_TYPE flag to the parser - if this flag is set, the
parser will return an error if the virtualport has no type
attribute. This also was previously the default behavior, but isn't
needed in the case of the virtualport for a type='network' interface
(i.e. the exact type isn't yet known), or the virtualport of a
portgroup (i.e. the portgroup just has modifiers for the network's
virtualport, which *does* require a type) - in those cases, the
check will be done at domain startup, once the final virtualport is
assembled (this is handled in the next patch).
2012-07-31 18:36:51 +00:00
|
|
|
}
|
conf: support abstracted interface info in network XML
The network XML is updated in the following ways:
1) The <forward> element can now contain a list of forward interfaces:
<forward .... >
<interface dev='eth10'/>
<interface dev='eth11'/>
<interface dev='eth12'/>
<interface dev='eth13'/>
</forward>
The first of these takes the place of the dev attribute that is
normally in <forward> - when defining a network you can specify
either one, and on output both will be present. If you specify
both on input, they must match.
2) In addition to forward modes of 'nat' and 'route', these new modes
are supported:
private, passthrough, vepa - when this network is referenced by a
domain's interface, it will have the same effect as if the
interface had been defined as type='direct', e.g.:
<interface type='direct'>
<source mode='${mode}' dev='${dev}>
...
</interface>
where ${mode} is one of the three new modes, and ${dev} is an interface
selected from the list given in <forward>.
bridge - if a <forward> dev (or multiple devs) is defined, and
forward mode is 'bridge' this is just like the modes 'private',
'passthrough', and 'vepa' above. If there is no forward dev
specified but a bridge name is given (e.g. "<bridge
name='br0'/>"), then guest interfaces using this network will use
libvirt's "host bridge" mode, equivalent to this:
<interface type='bridge'>
<source bridge='${bridge-name}'/>
...
</interface>
3) A network can have multiple <portgroup> elements, which may be
selected by the guest interface definition (by adding
"portgroup='${name}'" in the <source> element along with the
network name). Currently a portgroup can only contain a
virtportprofile, but the intent is that other configuration items
may be put there int the future (e.g. bandwidth config). When
building a guest's interface, if the <interface> XML itself has no
virtportprofile, and if the requested network has a portgroup with
a name matching the name given in the <interface> (or if one of the
network's portgroups is marked with the "default='yes'" attribute),
the virtportprofile from that portgroup will be used by the
interface.
4) A network can have a virtportprofile defined at the top level,
which will be used by a guest interface when connecting in one of
the 'direct' modes if the guest interface XML itself hasn't
specified any virtportprofile, and if there are also no matching
portgroups on the network.
2011-07-20 03:01:09 +00:00
|
|
|
|
|
|
|
nPortGroups = virXPathNodeSet("./portgroup", ctxt, &portGroupNodes);
|
|
|
|
if (nPortGroups < 0)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
if (nPortGroups > 0) {
|
|
|
|
int ii;
|
|
|
|
|
|
|
|
/* allocate array to hold all the portgroups */
|
|
|
|
if (VIR_ALLOC_N(def->portGroups, nPortGroups) < 0) {
|
|
|
|
virReportOOMError();
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
/* parse each portgroup */
|
|
|
|
for (ii = 0; ii < nPortGroups; ii++) {
|
|
|
|
int ret = virNetworkPortGroupParseXML(&def->portGroups[ii],
|
|
|
|
portGroupNodes[ii], ctxt);
|
|
|
|
if (ret < 0)
|
|
|
|
goto error;
|
|
|
|
def->nPortGroups++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
VIR_FREE(portGroupNodes);
|
|
|
|
|
2010-11-17 18:36:19 +00:00
|
|
|
nIps = virXPathNodeSet("./ip", ctxt, &ipNodes);
|
2011-05-12 19:45:22 +00:00
|
|
|
if (nIps < 0)
|
|
|
|
goto error;
|
|
|
|
|
2010-11-17 18:36:19 +00:00
|
|
|
if (nIps > 0) {
|
|
|
|
int ii;
|
2008-07-11 10:48:34 +00:00
|
|
|
|
2010-11-17 18:36:19 +00:00
|
|
|
/* allocate array to hold all the addrs */
|
|
|
|
if (VIR_ALLOC_N(def->ips, nIps) < 0) {
|
|
|
|
virReportOOMError();
|
2008-07-11 10:48:34 +00:00
|
|
|
goto error;
|
|
|
|
}
|
2010-11-17 18:36:19 +00:00
|
|
|
/* parse each addr */
|
|
|
|
for (ii = 0; ii < nIps; ii++) {
|
|
|
|
int ret = virNetworkIPParseXML(def->name, &def->ips[ii],
|
|
|
|
ipNodes[ii], ctxt);
|
|
|
|
if (ret < 0)
|
|
|
|
goto error;
|
|
|
|
def->nips++;
|
2008-07-11 10:48:34 +00:00
|
|
|
}
|
2010-11-30 20:53:17 +00:00
|
|
|
}
|
2011-01-10 22:35:37 +00:00
|
|
|
VIR_FREE(ipNodes);
|
2008-07-11 10:48:34 +00:00
|
|
|
|
conf: support abstracted interface info in network XML
The network XML is updated in the following ways:
1) The <forward> element can now contain a list of forward interfaces:
<forward .... >
<interface dev='eth10'/>
<interface dev='eth11'/>
<interface dev='eth12'/>
<interface dev='eth13'/>
</forward>
The first of these takes the place of the dev attribute that is
normally in <forward> - when defining a network you can specify
either one, and on output both will be present. If you specify
both on input, they must match.
2) In addition to forward modes of 'nat' and 'route', these new modes
are supported:
private, passthrough, vepa - when this network is referenced by a
domain's interface, it will have the same effect as if the
interface had been defined as type='direct', e.g.:
<interface type='direct'>
<source mode='${mode}' dev='${dev}>
...
</interface>
where ${mode} is one of the three new modes, and ${dev} is an interface
selected from the list given in <forward>.
bridge - if a <forward> dev (or multiple devs) is defined, and
forward mode is 'bridge' this is just like the modes 'private',
'passthrough', and 'vepa' above. If there is no forward dev
specified but a bridge name is given (e.g. "<bridge
name='br0'/>"), then guest interfaces using this network will use
libvirt's "host bridge" mode, equivalent to this:
<interface type='bridge'>
<source bridge='${bridge-name}'/>
...
</interface>
3) A network can have multiple <portgroup> elements, which may be
selected by the guest interface definition (by adding
"portgroup='${name}'" in the <source> element along with the
network name). Currently a portgroup can only contain a
virtportprofile, but the intent is that other configuration items
may be put there int the future (e.g. bandwidth config). When
building a guest's interface, if the <interface> XML itself has no
virtportprofile, and if the requested network has a portgroup with
a name matching the name given in the <interface> (or if one of the
network's portgroups is marked with the "default='yes'" attribute),
the virtportprofile from that portgroup will be used by the
interface.
4) A network can have a virtportprofile defined at the top level,
which will be used by a guest interface when connecting in one of
the 'direct' modes if the guest interface XML itself hasn't
specified any virtportprofile, and if there are also no matching
portgroups on the network.
2011-07-20 03:01:09 +00:00
|
|
|
forwardNode = virXPathNode("./forward", ctxt);
|
|
|
|
if (!forwardNode) {
|
|
|
|
def->forwardType = VIR_NETWORK_FORWARD_NONE;
|
|
|
|
def->stp = (stp && STREQ(stp, "off")) ? 0 : 1;
|
|
|
|
} else {
|
|
|
|
ctxt->node = forwardNode;
|
|
|
|
tmp = virXPathString("string(./@mode)", ctxt);
|
2008-07-11 10:48:34 +00:00
|
|
|
if (tmp) {
|
|
|
|
if ((def->forwardType = virNetworkForwardTypeFromString(tmp)) < 0) {
|
2012-07-18 10:50:44 +00:00
|
|
|
virReportError(VIR_ERR_XML_ERROR,
|
|
|
|
_("unknown forwarding type '%s'"), tmp);
|
2008-07-11 10:48:34 +00:00
|
|
|
VIR_FREE(tmp);
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
VIR_FREE(tmp);
|
|
|
|
} else {
|
|
|
|
def->forwardType = VIR_NETWORK_FORWARD_NAT;
|
|
|
|
}
|
|
|
|
|
conf: support abstracted interface info in network XML
The network XML is updated in the following ways:
1) The <forward> element can now contain a list of forward interfaces:
<forward .... >
<interface dev='eth10'/>
<interface dev='eth11'/>
<interface dev='eth12'/>
<interface dev='eth13'/>
</forward>
The first of these takes the place of the dev attribute that is
normally in <forward> - when defining a network you can specify
either one, and on output both will be present. If you specify
both on input, they must match.
2) In addition to forward modes of 'nat' and 'route', these new modes
are supported:
private, passthrough, vepa - when this network is referenced by a
domain's interface, it will have the same effect as if the
interface had been defined as type='direct', e.g.:
<interface type='direct'>
<source mode='${mode}' dev='${dev}>
...
</interface>
where ${mode} is one of the three new modes, and ${dev} is an interface
selected from the list given in <forward>.
bridge - if a <forward> dev (or multiple devs) is defined, and
forward mode is 'bridge' this is just like the modes 'private',
'passthrough', and 'vepa' above. If there is no forward dev
specified but a bridge name is given (e.g. "<bridge
name='br0'/>"), then guest interfaces using this network will use
libvirt's "host bridge" mode, equivalent to this:
<interface type='bridge'>
<source bridge='${bridge-name}'/>
...
</interface>
3) A network can have multiple <portgroup> elements, which may be
selected by the guest interface definition (by adding
"portgroup='${name}'" in the <source> element along with the
network name). Currently a portgroup can only contain a
virtportprofile, but the intent is that other configuration items
may be put there int the future (e.g. bandwidth config). When
building a guest's interface, if the <interface> XML itself has no
virtportprofile, and if the requested network has a portgroup with
a name matching the name given in the <interface> (or if one of the
network's portgroups is marked with the "default='yes'" attribute),
the virtportprofile from that portgroup will be used by the
interface.
4) A network can have a virtportprofile defined at the top level,
which will be used by a guest interface when connecting in one of
the 'direct' modes if the guest interface XML itself hasn't
specified any virtportprofile, and if there are also no matching
portgroups on the network.
2011-07-20 03:01:09 +00:00
|
|
|
forwardDev = virXPathString("string(./@dev)", ctxt);
|
2012-08-16 15:41:41 +00:00
|
|
|
forwardManaged = virXPathString("string(./@managed)", ctxt);
|
|
|
|
if(forwardManaged != NULL) {
|
|
|
|
if (STRCASEEQ(forwardManaged, "yes"))
|
|
|
|
def->managed = 1;
|
|
|
|
}
|
2008-07-11 10:48:34 +00:00
|
|
|
|
conf: support abstracted interface info in network XML
The network XML is updated in the following ways:
1) The <forward> element can now contain a list of forward interfaces:
<forward .... >
<interface dev='eth10'/>
<interface dev='eth11'/>
<interface dev='eth12'/>
<interface dev='eth13'/>
</forward>
The first of these takes the place of the dev attribute that is
normally in <forward> - when defining a network you can specify
either one, and on output both will be present. If you specify
both on input, they must match.
2) In addition to forward modes of 'nat' and 'route', these new modes
are supported:
private, passthrough, vepa - when this network is referenced by a
domain's interface, it will have the same effect as if the
interface had been defined as type='direct', e.g.:
<interface type='direct'>
<source mode='${mode}' dev='${dev}>
...
</interface>
where ${mode} is one of the three new modes, and ${dev} is an interface
selected from the list given in <forward>.
bridge - if a <forward> dev (or multiple devs) is defined, and
forward mode is 'bridge' this is just like the modes 'private',
'passthrough', and 'vepa' above. If there is no forward dev
specified but a bridge name is given (e.g. "<bridge
name='br0'/>"), then guest interfaces using this network will use
libvirt's "host bridge" mode, equivalent to this:
<interface type='bridge'>
<source bridge='${bridge-name}'/>
...
</interface>
3) A network can have multiple <portgroup> elements, which may be
selected by the guest interface definition (by adding
"portgroup='${name}'" in the <source> element along with the
network name). Currently a portgroup can only contain a
virtportprofile, but the intent is that other configuration items
may be put there int the future (e.g. bandwidth config). When
building a guest's interface, if the <interface> XML itself has no
virtportprofile, and if the requested network has a portgroup with
a name matching the name given in the <interface> (or if one of the
network's portgroups is marked with the "default='yes'" attribute),
the virtportprofile from that portgroup will be used by the
interface.
4) A network can have a virtportprofile defined at the top level,
which will be used by a guest interface when connecting in one of
the 'direct' modes if the guest interface XML itself hasn't
specified any virtportprofile, and if there are also no matching
portgroups on the network.
2011-07-20 03:01:09 +00:00
|
|
|
/* all of these modes can use a pool of physical interfaces */
|
|
|
|
nForwardIfs = virXPathNodeSet("./interface", ctxt, &forwardIfNodes);
|
2011-12-14 10:50:23 +00:00
|
|
|
nForwardPfs = virXPathNodeSet("./pf", ctxt, &forwardPfNodes);
|
2012-08-16 15:41:41 +00:00
|
|
|
nForwardAddrs = virXPathNodeSet("./address", ctxt, &forwardAddrNodes);
|
2011-12-14 10:50:23 +00:00
|
|
|
|
2012-08-16 15:41:41 +00:00
|
|
|
if (nForwardIfs < 0 || nForwardPfs < 0 || nForwardAddrs < 0) {
|
maint: don't permit format strings without %
Any time we have a string with no % passed through gettext, a
translator can inject a % to cause a stack overread. When there
is nothing to format, it's easier to ask for a string that cannot
be used as a formatter, by using a trivial "%s" format instead.
In the past, we have used --disable-nls to catch some of the
offenders, but that doesn't get run very often, and many more
uses have crept in. Syntax check to the rescue!
The syntax check can catch uses such as
virReportError(code,
_("split "
"string"));
by using a sed script to fold context lines into one pattern
space before checking for a string without %.
This patch is just mechanical insertion of %s; there are probably
several messages touched by this patch where we would be better
off giving the user more information than a fixed string.
* cfg.mk (sc_prohibit_diagnostic_without_format): New rule.
* src/datatypes.c (virUnrefConnect, virGetDomain)
(virUnrefDomain, virGetNetwork, virUnrefNetwork, virGetInterface)
(virUnrefInterface, virGetStoragePool, virUnrefStoragePool)
(virGetStorageVol, virUnrefStorageVol, virGetNodeDevice)
(virGetSecret, virUnrefSecret, virGetNWFilter, virUnrefNWFilter)
(virGetDomainSnapshot, virUnrefDomainSnapshot): Add %s wrapper.
* src/lxc/lxc_driver.c (lxcDomainSetBlkioParameters)
(lxcDomainGetBlkioParameters): Likewise.
* src/conf/domain_conf.c (virSecurityDeviceLabelDefParseXML)
(virDomainDiskDefParseXML, virDomainGraphicsDefParseXML):
Likewise.
* src/conf/network_conf.c (virNetworkDNSHostsDefParseXML)
(virNetworkDefParseXML): Likewise.
* src/conf/nwfilter_conf.c (virNWFilterIsValidChainName):
Likewise.
* src/conf/nwfilter_params.c (virNWFilterVarValueCreateSimple)
(virNWFilterVarAccessParse): Likewise.
* src/libvirt.c (virDomainSave, virDomainSaveFlags)
(virDomainRestore, virDomainRestoreFlags)
(virDomainSaveImageGetXMLDesc, virDomainSaveImageDefineXML)
(virDomainCoreDump, virDomainGetXMLDesc)
(virDomainMigrateVersion1, virDomainMigrateVersion2)
(virDomainMigrateVersion3, virDomainMigrate, virDomainMigrate2)
(virStreamSendAll, virStreamRecvAll)
(virDomainSnapshotGetXMLDesc): Likewise.
* src/nwfilter/nwfilter_dhcpsnoop.c (virNWFilterSnoopReqLeaseDel)
(virNWFilterDHCPSnoopReq): Likewise.
* src/openvz/openvz_driver.c (openvzUpdateDevice): Likewise.
* src/openvz/openvz_util.c (openvzKBPerPages): Likewise.
* src/qemu/qemu_cgroup.c (qemuSetupCgroup): Likewise.
* src/qemu/qemu_command.c (qemuBuildHubDevStr, qemuBuildChrChardevStr)
(qemuBuildCommandLine): Likewise.
* src/qemu/qemu_driver.c (qemuDomainGetPercpuStats): Likewise.
* src/qemu/qemu_hotplug.c (qemuDomainAttachNetDevice): Likewise.
* src/rpc/virnetsaslcontext.c (virNetSASLSessionGetIdentity):
Likewise.
* src/rpc/virnetsocket.c (virNetSocketNewConnectUNIX)
(virNetSocketSendFD, virNetSocketRecvFD): Likewise.
* src/storage/storage_backend_disk.c
(virStorageBackendDiskBuildPool): Likewise.
* src/storage/storage_backend_fs.c
(virStorageBackendFileSystemProbe)
(virStorageBackendFileSystemBuild): Likewise.
* src/storage/storage_backend_rbd.c
(virStorageBackendRBDOpenRADOSConn): Likewise.
* src/storage/storage_driver.c (storageVolumeResize): Likewise.
* src/test/test_driver.c (testInterfaceChangeBegin)
(testInterfaceChangeCommit, testInterfaceChangeRollback):
Likewise.
* src/vbox/vbox_tmpl.c (vboxListAllDomains): Likewise.
* src/xenxs/xen_sxpr.c (xenFormatSxprDisk, xenFormatSxpr):
Likewise.
* src/xenxs/xen_xm.c (xenXMConfigGetUUID, xenFormatXMDisk)
(xenFormatXM): Likewise.
2012-07-23 20:33:08 +00:00
|
|
|
virReportError(VIR_ERR_XML_ERROR, "%s",
|
2012-07-18 10:50:44 +00:00
|
|
|
_("No interface pool or SRIOV physical device given"));
|
conf: support abstracted interface info in network XML
The network XML is updated in the following ways:
1) The <forward> element can now contain a list of forward interfaces:
<forward .... >
<interface dev='eth10'/>
<interface dev='eth11'/>
<interface dev='eth12'/>
<interface dev='eth13'/>
</forward>
The first of these takes the place of the dev attribute that is
normally in <forward> - when defining a network you can specify
either one, and on output both will be present. If you specify
both on input, they must match.
2) In addition to forward modes of 'nat' and 'route', these new modes
are supported:
private, passthrough, vepa - when this network is referenced by a
domain's interface, it will have the same effect as if the
interface had been defined as type='direct', e.g.:
<interface type='direct'>
<source mode='${mode}' dev='${dev}>
...
</interface>
where ${mode} is one of the three new modes, and ${dev} is an interface
selected from the list given in <forward>.
bridge - if a <forward> dev (or multiple devs) is defined, and
forward mode is 'bridge' this is just like the modes 'private',
'passthrough', and 'vepa' above. If there is no forward dev
specified but a bridge name is given (e.g. "<bridge
name='br0'/>"), then guest interfaces using this network will use
libvirt's "host bridge" mode, equivalent to this:
<interface type='bridge'>
<source bridge='${bridge-name}'/>
...
</interface>
3) A network can have multiple <portgroup> elements, which may be
selected by the guest interface definition (by adding
"portgroup='${name}'" in the <source> element along with the
network name). Currently a portgroup can only contain a
virtportprofile, but the intent is that other configuration items
may be put there int the future (e.g. bandwidth config). When
building a guest's interface, if the <interface> XML itself has no
virtportprofile, and if the requested network has a portgroup with
a name matching the name given in the <interface> (or if one of the
network's portgroups is marked with the "default='yes'" attribute),
the virtportprofile from that portgroup will be used by the
interface.
4) A network can have a virtportprofile defined at the top level,
which will be used by a guest interface when connecting in one of
the 'direct' modes if the guest interface XML itself hasn't
specified any virtportprofile, and if there are also no matching
portgroups on the network.
2011-07-20 03:01:09 +00:00
|
|
|
goto error;
|
2011-12-14 10:50:23 +00:00
|
|
|
}
|
|
|
|
|
2012-08-16 15:41:41 +00:00
|
|
|
if ((nForwardIfs > 0) && (nForwardAddrs > 0)) {
|
|
|
|
virReportError(VIR_ERR_XML_ERROR, "%s",
|
|
|
|
_("Address and interface attributes are mutually exclusive"));
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((nForwardPfs > 0) && ((nForwardIfs > 0) || (nForwardAddrs > 0))) {
|
|
|
|
virReportError(VIR_ERR_XML_ERROR, "%s",
|
|
|
|
_("Address/interface attributes and Physical function are mutually exclusive "));
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
2011-12-14 10:50:23 +00:00
|
|
|
if (nForwardPfs == 1) {
|
|
|
|
if (VIR_ALLOC_N(def->forwardPfs, nForwardPfs) < 0) {
|
|
|
|
virReportOOMError();
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (forwardDev) {
|
maint: don't permit format strings without %
Any time we have a string with no % passed through gettext, a
translator can inject a % to cause a stack overread. When there
is nothing to format, it's easier to ask for a string that cannot
be used as a formatter, by using a trivial "%s" format instead.
In the past, we have used --disable-nls to catch some of the
offenders, but that doesn't get run very often, and many more
uses have crept in. Syntax check to the rescue!
The syntax check can catch uses such as
virReportError(code,
_("split "
"string"));
by using a sed script to fold context lines into one pattern
space before checking for a string without %.
This patch is just mechanical insertion of %s; there are probably
several messages touched by this patch where we would be better
off giving the user more information than a fixed string.
* cfg.mk (sc_prohibit_diagnostic_without_format): New rule.
* src/datatypes.c (virUnrefConnect, virGetDomain)
(virUnrefDomain, virGetNetwork, virUnrefNetwork, virGetInterface)
(virUnrefInterface, virGetStoragePool, virUnrefStoragePool)
(virGetStorageVol, virUnrefStorageVol, virGetNodeDevice)
(virGetSecret, virUnrefSecret, virGetNWFilter, virUnrefNWFilter)
(virGetDomainSnapshot, virUnrefDomainSnapshot): Add %s wrapper.
* src/lxc/lxc_driver.c (lxcDomainSetBlkioParameters)
(lxcDomainGetBlkioParameters): Likewise.
* src/conf/domain_conf.c (virSecurityDeviceLabelDefParseXML)
(virDomainDiskDefParseXML, virDomainGraphicsDefParseXML):
Likewise.
* src/conf/network_conf.c (virNetworkDNSHostsDefParseXML)
(virNetworkDefParseXML): Likewise.
* src/conf/nwfilter_conf.c (virNWFilterIsValidChainName):
Likewise.
* src/conf/nwfilter_params.c (virNWFilterVarValueCreateSimple)
(virNWFilterVarAccessParse): Likewise.
* src/libvirt.c (virDomainSave, virDomainSaveFlags)
(virDomainRestore, virDomainRestoreFlags)
(virDomainSaveImageGetXMLDesc, virDomainSaveImageDefineXML)
(virDomainCoreDump, virDomainGetXMLDesc)
(virDomainMigrateVersion1, virDomainMigrateVersion2)
(virDomainMigrateVersion3, virDomainMigrate, virDomainMigrate2)
(virStreamSendAll, virStreamRecvAll)
(virDomainSnapshotGetXMLDesc): Likewise.
* src/nwfilter/nwfilter_dhcpsnoop.c (virNWFilterSnoopReqLeaseDel)
(virNWFilterDHCPSnoopReq): Likewise.
* src/openvz/openvz_driver.c (openvzUpdateDevice): Likewise.
* src/openvz/openvz_util.c (openvzKBPerPages): Likewise.
* src/qemu/qemu_cgroup.c (qemuSetupCgroup): Likewise.
* src/qemu/qemu_command.c (qemuBuildHubDevStr, qemuBuildChrChardevStr)
(qemuBuildCommandLine): Likewise.
* src/qemu/qemu_driver.c (qemuDomainGetPercpuStats): Likewise.
* src/qemu/qemu_hotplug.c (qemuDomainAttachNetDevice): Likewise.
* src/rpc/virnetsaslcontext.c (virNetSASLSessionGetIdentity):
Likewise.
* src/rpc/virnetsocket.c (virNetSocketNewConnectUNIX)
(virNetSocketSendFD, virNetSocketRecvFD): Likewise.
* src/storage/storage_backend_disk.c
(virStorageBackendDiskBuildPool): Likewise.
* src/storage/storage_backend_fs.c
(virStorageBackendFileSystemProbe)
(virStorageBackendFileSystemBuild): Likewise.
* src/storage/storage_backend_rbd.c
(virStorageBackendRBDOpenRADOSConn): Likewise.
* src/storage/storage_driver.c (storageVolumeResize): Likewise.
* src/test/test_driver.c (testInterfaceChangeBegin)
(testInterfaceChangeCommit, testInterfaceChangeRollback):
Likewise.
* src/vbox/vbox_tmpl.c (vboxListAllDomains): Likewise.
* src/xenxs/xen_sxpr.c (xenFormatSxprDisk, xenFormatSxpr):
Likewise.
* src/xenxs/xen_xm.c (xenXMConfigGetUUID, xenFormatXMDisk)
(xenFormatXM): Likewise.
2012-07-23 20:33:08 +00:00
|
|
|
virReportError(VIR_ERR_XML_ERROR, "%s",
|
2012-07-18 10:50:44 +00:00
|
|
|
_("A forward Dev should not be used when using a SRIOV PF"));
|
2011-12-14 10:50:23 +00:00
|
|
|
goto error;
|
|
|
|
}
|
conf: support abstracted interface info in network XML
The network XML is updated in the following ways:
1) The <forward> element can now contain a list of forward interfaces:
<forward .... >
<interface dev='eth10'/>
<interface dev='eth11'/>
<interface dev='eth12'/>
<interface dev='eth13'/>
</forward>
The first of these takes the place of the dev attribute that is
normally in <forward> - when defining a network you can specify
either one, and on output both will be present. If you specify
both on input, they must match.
2) In addition to forward modes of 'nat' and 'route', these new modes
are supported:
private, passthrough, vepa - when this network is referenced by a
domain's interface, it will have the same effect as if the
interface had been defined as type='direct', e.g.:
<interface type='direct'>
<source mode='${mode}' dev='${dev}>
...
</interface>
where ${mode} is one of the three new modes, and ${dev} is an interface
selected from the list given in <forward>.
bridge - if a <forward> dev (or multiple devs) is defined, and
forward mode is 'bridge' this is just like the modes 'private',
'passthrough', and 'vepa' above. If there is no forward dev
specified but a bridge name is given (e.g. "<bridge
name='br0'/>"), then guest interfaces using this network will use
libvirt's "host bridge" mode, equivalent to this:
<interface type='bridge'>
<source bridge='${bridge-name}'/>
...
</interface>
3) A network can have multiple <portgroup> elements, which may be
selected by the guest interface definition (by adding
"portgroup='${name}'" in the <source> element along with the
network name). Currently a portgroup can only contain a
virtportprofile, but the intent is that other configuration items
may be put there int the future (e.g. bandwidth config). When
building a guest's interface, if the <interface> XML itself has no
virtportprofile, and if the requested network has a portgroup with
a name matching the name given in the <interface> (or if one of the
network's portgroups is marked with the "default='yes'" attribute),
the virtportprofile from that portgroup will be used by the
interface.
4) A network can have a virtportprofile defined at the top level,
which will be used by a guest interface when connecting in one of
the 'direct' modes if the guest interface XML itself hasn't
specified any virtportprofile, and if there are also no matching
portgroups on the network.
2011-07-20 03:01:09 +00:00
|
|
|
|
2011-12-14 10:50:23 +00:00
|
|
|
forwardDev = virXMLPropString(*forwardPfNodes, "dev");
|
|
|
|
if (!forwardDev) {
|
2012-07-18 10:50:44 +00:00
|
|
|
virReportError(VIR_ERR_XML_ERROR,
|
|
|
|
_("Missing required dev attribute in network '%s' pf element"),
|
|
|
|
def->name);
|
2011-12-14 10:50:23 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
def->forwardPfs->dev = forwardDev;
|
|
|
|
forwardDev = NULL;
|
|
|
|
def->nForwardPfs++;
|
|
|
|
} else if (nForwardPfs > 1) {
|
maint: don't permit format strings without %
Any time we have a string with no % passed through gettext, a
translator can inject a % to cause a stack overread. When there
is nothing to format, it's easier to ask for a string that cannot
be used as a formatter, by using a trivial "%s" format instead.
In the past, we have used --disable-nls to catch some of the
offenders, but that doesn't get run very often, and many more
uses have crept in. Syntax check to the rescue!
The syntax check can catch uses such as
virReportError(code,
_("split "
"string"));
by using a sed script to fold context lines into one pattern
space before checking for a string without %.
This patch is just mechanical insertion of %s; there are probably
several messages touched by this patch where we would be better
off giving the user more information than a fixed string.
* cfg.mk (sc_prohibit_diagnostic_without_format): New rule.
* src/datatypes.c (virUnrefConnect, virGetDomain)
(virUnrefDomain, virGetNetwork, virUnrefNetwork, virGetInterface)
(virUnrefInterface, virGetStoragePool, virUnrefStoragePool)
(virGetStorageVol, virUnrefStorageVol, virGetNodeDevice)
(virGetSecret, virUnrefSecret, virGetNWFilter, virUnrefNWFilter)
(virGetDomainSnapshot, virUnrefDomainSnapshot): Add %s wrapper.
* src/lxc/lxc_driver.c (lxcDomainSetBlkioParameters)
(lxcDomainGetBlkioParameters): Likewise.
* src/conf/domain_conf.c (virSecurityDeviceLabelDefParseXML)
(virDomainDiskDefParseXML, virDomainGraphicsDefParseXML):
Likewise.
* src/conf/network_conf.c (virNetworkDNSHostsDefParseXML)
(virNetworkDefParseXML): Likewise.
* src/conf/nwfilter_conf.c (virNWFilterIsValidChainName):
Likewise.
* src/conf/nwfilter_params.c (virNWFilterVarValueCreateSimple)
(virNWFilterVarAccessParse): Likewise.
* src/libvirt.c (virDomainSave, virDomainSaveFlags)
(virDomainRestore, virDomainRestoreFlags)
(virDomainSaveImageGetXMLDesc, virDomainSaveImageDefineXML)
(virDomainCoreDump, virDomainGetXMLDesc)
(virDomainMigrateVersion1, virDomainMigrateVersion2)
(virDomainMigrateVersion3, virDomainMigrate, virDomainMigrate2)
(virStreamSendAll, virStreamRecvAll)
(virDomainSnapshotGetXMLDesc): Likewise.
* src/nwfilter/nwfilter_dhcpsnoop.c (virNWFilterSnoopReqLeaseDel)
(virNWFilterDHCPSnoopReq): Likewise.
* src/openvz/openvz_driver.c (openvzUpdateDevice): Likewise.
* src/openvz/openvz_util.c (openvzKBPerPages): Likewise.
* src/qemu/qemu_cgroup.c (qemuSetupCgroup): Likewise.
* src/qemu/qemu_command.c (qemuBuildHubDevStr, qemuBuildChrChardevStr)
(qemuBuildCommandLine): Likewise.
* src/qemu/qemu_driver.c (qemuDomainGetPercpuStats): Likewise.
* src/qemu/qemu_hotplug.c (qemuDomainAttachNetDevice): Likewise.
* src/rpc/virnetsaslcontext.c (virNetSASLSessionGetIdentity):
Likewise.
* src/rpc/virnetsocket.c (virNetSocketNewConnectUNIX)
(virNetSocketSendFD, virNetSocketRecvFD): Likewise.
* src/storage/storage_backend_disk.c
(virStorageBackendDiskBuildPool): Likewise.
* src/storage/storage_backend_fs.c
(virStorageBackendFileSystemProbe)
(virStorageBackendFileSystemBuild): Likewise.
* src/storage/storage_backend_rbd.c
(virStorageBackendRBDOpenRADOSConn): Likewise.
* src/storage/storage_driver.c (storageVolumeResize): Likewise.
* src/test/test_driver.c (testInterfaceChangeBegin)
(testInterfaceChangeCommit, testInterfaceChangeRollback):
Likewise.
* src/vbox/vbox_tmpl.c (vboxListAllDomains): Likewise.
* src/xenxs/xen_sxpr.c (xenFormatSxprDisk, xenFormatSxpr):
Likewise.
* src/xenxs/xen_xm.c (xenXMConfigGetUUID, xenFormatXMDisk)
(xenFormatXM): Likewise.
2012-07-23 20:33:08 +00:00
|
|
|
virReportError(VIR_ERR_XML_ERROR, "%s",
|
2012-07-18 10:50:44 +00:00
|
|
|
_("Use of more than one physical interface is not allowed"));
|
2011-12-14 10:50:23 +00:00
|
|
|
goto error;
|
|
|
|
}
|
2012-08-16 15:41:41 +00:00
|
|
|
if (nForwardAddrs > 0) {
|
|
|
|
int ii;
|
|
|
|
|
|
|
|
if (VIR_ALLOC_N(def->forwardIfs, nForwardAddrs) < 0) {
|
|
|
|
virReportOOMError();
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (forwardDev) {
|
|
|
|
virReportError(VIR_ERR_XML_ERROR, "%s",
|
|
|
|
_("A forward Dev should not be used when using address attribute"));
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (ii = 0; ii < nForwardAddrs; ii++) {
|
|
|
|
type = virXMLPropString(forwardAddrNodes[ii], "type");
|
|
|
|
|
|
|
|
if (type) {
|
|
|
|
if ((def->forwardIfs[ii].type = virNetworkForwardHostdevDeviceTypeFromString(type)) < 0) {
|
|
|
|
virReportError(VIR_ERR_XML_ERROR,
|
|
|
|
_("unknown address type '%s'"), type);
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
virReportError(VIR_ERR_XML_ERROR,
|
|
|
|
"%s", _("No type specified for device address"));
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (def->forwardIfs[ii].type) {
|
|
|
|
case VIR_NETWORK_FORWARD_HOSTDEV_DEVICE_PCI:
|
|
|
|
if (virDevicePCIAddressParseXML(forwardAddrNodes[ii], &(def->forwardIfs[ii].device.pci)) < 0)
|
|
|
|
goto error;
|
|
|
|
break;
|
|
|
|
|
|
|
|
/* Add USB case here */
|
|
|
|
|
|
|
|
default:
|
|
|
|
virReportError(VIR_ERR_XML_ERROR,
|
|
|
|
_("unknown address type '%s'"), type);
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
VIR_FREE(type);
|
|
|
|
def->nForwardIfs++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (nForwardIfs > 0 || forwardDev) {
|
conf: support abstracted interface info in network XML
The network XML is updated in the following ways:
1) The <forward> element can now contain a list of forward interfaces:
<forward .... >
<interface dev='eth10'/>
<interface dev='eth11'/>
<interface dev='eth12'/>
<interface dev='eth13'/>
</forward>
The first of these takes the place of the dev attribute that is
normally in <forward> - when defining a network you can specify
either one, and on output both will be present. If you specify
both on input, they must match.
2) In addition to forward modes of 'nat' and 'route', these new modes
are supported:
private, passthrough, vepa - when this network is referenced by a
domain's interface, it will have the same effect as if the
interface had been defined as type='direct', e.g.:
<interface type='direct'>
<source mode='${mode}' dev='${dev}>
...
</interface>
where ${mode} is one of the three new modes, and ${dev} is an interface
selected from the list given in <forward>.
bridge - if a <forward> dev (or multiple devs) is defined, and
forward mode is 'bridge' this is just like the modes 'private',
'passthrough', and 'vepa' above. If there is no forward dev
specified but a bridge name is given (e.g. "<bridge
name='br0'/>"), then guest interfaces using this network will use
libvirt's "host bridge" mode, equivalent to this:
<interface type='bridge'>
<source bridge='${bridge-name}'/>
...
</interface>
3) A network can have multiple <portgroup> elements, which may be
selected by the guest interface definition (by adding
"portgroup='${name}'" in the <source> element along with the
network name). Currently a portgroup can only contain a
virtportprofile, but the intent is that other configuration items
may be put there int the future (e.g. bandwidth config). When
building a guest's interface, if the <interface> XML itself has no
virtportprofile, and if the requested network has a portgroup with
a name matching the name given in the <interface> (or if one of the
network's portgroups is marked with the "default='yes'" attribute),
the virtportprofile from that portgroup will be used by the
interface.
4) A network can have a virtportprofile defined at the top level,
which will be used by a guest interface when connecting in one of
the 'direct' modes if the guest interface XML itself hasn't
specified any virtportprofile, and if there are also no matching
portgroups on the network.
2011-07-20 03:01:09 +00:00
|
|
|
int ii;
|
2008-07-11 10:48:34 +00:00
|
|
|
|
conf: support abstracted interface info in network XML
The network XML is updated in the following ways:
1) The <forward> element can now contain a list of forward interfaces:
<forward .... >
<interface dev='eth10'/>
<interface dev='eth11'/>
<interface dev='eth12'/>
<interface dev='eth13'/>
</forward>
The first of these takes the place of the dev attribute that is
normally in <forward> - when defining a network you can specify
either one, and on output both will be present. If you specify
both on input, they must match.
2) In addition to forward modes of 'nat' and 'route', these new modes
are supported:
private, passthrough, vepa - when this network is referenced by a
domain's interface, it will have the same effect as if the
interface had been defined as type='direct', e.g.:
<interface type='direct'>
<source mode='${mode}' dev='${dev}>
...
</interface>
where ${mode} is one of the three new modes, and ${dev} is an interface
selected from the list given in <forward>.
bridge - if a <forward> dev (or multiple devs) is defined, and
forward mode is 'bridge' this is just like the modes 'private',
'passthrough', and 'vepa' above. If there is no forward dev
specified but a bridge name is given (e.g. "<bridge
name='br0'/>"), then guest interfaces using this network will use
libvirt's "host bridge" mode, equivalent to this:
<interface type='bridge'>
<source bridge='${bridge-name}'/>
...
</interface>
3) A network can have multiple <portgroup> elements, which may be
selected by the guest interface definition (by adding
"portgroup='${name}'" in the <source> element along with the
network name). Currently a portgroup can only contain a
virtportprofile, but the intent is that other configuration items
may be put there int the future (e.g. bandwidth config). When
building a guest's interface, if the <interface> XML itself has no
virtportprofile, and if the requested network has a portgroup with
a name matching the name given in the <interface> (or if one of the
network's portgroups is marked with the "default='yes'" attribute),
the virtportprofile from that portgroup will be used by the
interface.
4) A network can have a virtportprofile defined at the top level,
which will be used by a guest interface when connecting in one of
the 'direct' modes if the guest interface XML itself hasn't
specified any virtportprofile, and if there are also no matching
portgroups on the network.
2011-07-20 03:01:09 +00:00
|
|
|
/* allocate array to hold all the portgroups */
|
|
|
|
if (VIR_ALLOC_N(def->forwardIfs, MAX(nForwardIfs, 1)) < 0) {
|
|
|
|
virReportOOMError();
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (forwardDev) {
|
2012-08-16 15:41:41 +00:00
|
|
|
def->forwardIfs[0].device.dev = forwardDev;
|
|
|
|
def->forwardIfs[0].type = VIR_NETWORK_FORWARD_HOSTDEV_DEVICE_NETDEV;
|
conf: support abstracted interface info in network XML
The network XML is updated in the following ways:
1) The <forward> element can now contain a list of forward interfaces:
<forward .... >
<interface dev='eth10'/>
<interface dev='eth11'/>
<interface dev='eth12'/>
<interface dev='eth13'/>
</forward>
The first of these takes the place of the dev attribute that is
normally in <forward> - when defining a network you can specify
either one, and on output both will be present. If you specify
both on input, they must match.
2) In addition to forward modes of 'nat' and 'route', these new modes
are supported:
private, passthrough, vepa - when this network is referenced by a
domain's interface, it will have the same effect as if the
interface had been defined as type='direct', e.g.:
<interface type='direct'>
<source mode='${mode}' dev='${dev}>
...
</interface>
where ${mode} is one of the three new modes, and ${dev} is an interface
selected from the list given in <forward>.
bridge - if a <forward> dev (or multiple devs) is defined, and
forward mode is 'bridge' this is just like the modes 'private',
'passthrough', and 'vepa' above. If there is no forward dev
specified but a bridge name is given (e.g. "<bridge
name='br0'/>"), then guest interfaces using this network will use
libvirt's "host bridge" mode, equivalent to this:
<interface type='bridge'>
<source bridge='${bridge-name}'/>
...
</interface>
3) A network can have multiple <portgroup> elements, which may be
selected by the guest interface definition (by adding
"portgroup='${name}'" in the <source> element along with the
network name). Currently a portgroup can only contain a
virtportprofile, but the intent is that other configuration items
may be put there int the future (e.g. bandwidth config). When
building a guest's interface, if the <interface> XML itself has no
virtportprofile, and if the requested network has a portgroup with
a name matching the name given in the <interface> (or if one of the
network's portgroups is marked with the "default='yes'" attribute),
the virtportprofile from that portgroup will be used by the
interface.
4) A network can have a virtportprofile defined at the top level,
which will be used by a guest interface when connecting in one of
the 'direct' modes if the guest interface XML itself hasn't
specified any virtportprofile, and if there are also no matching
portgroups on the network.
2011-07-20 03:01:09 +00:00
|
|
|
forwardDev = NULL;
|
|
|
|
def->nForwardIfs++;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* parse each forwardIf */
|
|
|
|
for (ii = 0; ii < nForwardIfs; ii++) {
|
|
|
|
forwardDev = virXMLPropString(forwardIfNodes[ii], "dev");
|
|
|
|
if (!forwardDev) {
|
2012-07-18 10:50:44 +00:00
|
|
|
virReportError(VIR_ERR_XML_ERROR,
|
|
|
|
_("Missing required dev attribute in network '%s' forward interface element"),
|
|
|
|
def->name);
|
conf: support abstracted interface info in network XML
The network XML is updated in the following ways:
1) The <forward> element can now contain a list of forward interfaces:
<forward .... >
<interface dev='eth10'/>
<interface dev='eth11'/>
<interface dev='eth12'/>
<interface dev='eth13'/>
</forward>
The first of these takes the place of the dev attribute that is
normally in <forward> - when defining a network you can specify
either one, and on output both will be present. If you specify
both on input, they must match.
2) In addition to forward modes of 'nat' and 'route', these new modes
are supported:
private, passthrough, vepa - when this network is referenced by a
domain's interface, it will have the same effect as if the
interface had been defined as type='direct', e.g.:
<interface type='direct'>
<source mode='${mode}' dev='${dev}>
...
</interface>
where ${mode} is one of the three new modes, and ${dev} is an interface
selected from the list given in <forward>.
bridge - if a <forward> dev (or multiple devs) is defined, and
forward mode is 'bridge' this is just like the modes 'private',
'passthrough', and 'vepa' above. If there is no forward dev
specified but a bridge name is given (e.g. "<bridge
name='br0'/>"), then guest interfaces using this network will use
libvirt's "host bridge" mode, equivalent to this:
<interface type='bridge'>
<source bridge='${bridge-name}'/>
...
</interface>
3) A network can have multiple <portgroup> elements, which may be
selected by the guest interface definition (by adding
"portgroup='${name}'" in the <source> element along with the
network name). Currently a portgroup can only contain a
virtportprofile, but the intent is that other configuration items
may be put there int the future (e.g. bandwidth config). When
building a guest's interface, if the <interface> XML itself has no
virtportprofile, and if the requested network has a portgroup with
a name matching the name given in the <interface> (or if one of the
network's portgroups is marked with the "default='yes'" attribute),
the virtportprofile from that portgroup will be used by the
interface.
4) A network can have a virtportprofile defined at the top level,
which will be used by a guest interface when connecting in one of
the 'direct' modes if the guest interface XML itself hasn't
specified any virtportprofile, and if there are also no matching
portgroups on the network.
2011-07-20 03:01:09 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((ii == 0) && (def->nForwardIfs == 1)) {
|
|
|
|
/* both forwardDev and an interface element are present.
|
|
|
|
* If they don't match, it's an error. */
|
2012-08-16 15:41:41 +00:00
|
|
|
if (STRNEQ(forwardDev, def->forwardIfs[0].device.dev)) {
|
2012-07-18 10:50:44 +00:00
|
|
|
virReportError(VIR_ERR_XML_ERROR,
|
|
|
|
_("forward dev '%s' must match first interface element dev '%s' in network '%s'"),
|
2012-08-16 15:41:41 +00:00
|
|
|
def->forwardIfs[0].device.dev,
|
2012-07-18 10:50:44 +00:00
|
|
|
forwardDev, def->name);
|
conf: support abstracted interface info in network XML
The network XML is updated in the following ways:
1) The <forward> element can now contain a list of forward interfaces:
<forward .... >
<interface dev='eth10'/>
<interface dev='eth11'/>
<interface dev='eth12'/>
<interface dev='eth13'/>
</forward>
The first of these takes the place of the dev attribute that is
normally in <forward> - when defining a network you can specify
either one, and on output both will be present. If you specify
both on input, they must match.
2) In addition to forward modes of 'nat' and 'route', these new modes
are supported:
private, passthrough, vepa - when this network is referenced by a
domain's interface, it will have the same effect as if the
interface had been defined as type='direct', e.g.:
<interface type='direct'>
<source mode='${mode}' dev='${dev}>
...
</interface>
where ${mode} is one of the three new modes, and ${dev} is an interface
selected from the list given in <forward>.
bridge - if a <forward> dev (or multiple devs) is defined, and
forward mode is 'bridge' this is just like the modes 'private',
'passthrough', and 'vepa' above. If there is no forward dev
specified but a bridge name is given (e.g. "<bridge
name='br0'/>"), then guest interfaces using this network will use
libvirt's "host bridge" mode, equivalent to this:
<interface type='bridge'>
<source bridge='${bridge-name}'/>
...
</interface>
3) A network can have multiple <portgroup> elements, which may be
selected by the guest interface definition (by adding
"portgroup='${name}'" in the <source> element along with the
network name). Currently a portgroup can only contain a
virtportprofile, but the intent is that other configuration items
may be put there int the future (e.g. bandwidth config). When
building a guest's interface, if the <interface> XML itself has no
virtportprofile, and if the requested network has a portgroup with
a name matching the name given in the <interface> (or if one of the
network's portgroups is marked with the "default='yes'" attribute),
the virtportprofile from that portgroup will be used by the
interface.
4) A network can have a virtportprofile defined at the top level,
which will be used by a guest interface when connecting in one of
the 'direct' modes if the guest interface XML itself hasn't
specified any virtportprofile, and if there are also no matching
portgroups on the network.
2011-07-20 03:01:09 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
VIR_FREE(forwardDev);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2012-08-16 15:41:41 +00:00
|
|
|
def->forwardIfs[ii].device.dev = forwardDev;
|
conf: support abstracted interface info in network XML
The network XML is updated in the following ways:
1) The <forward> element can now contain a list of forward interfaces:
<forward .... >
<interface dev='eth10'/>
<interface dev='eth11'/>
<interface dev='eth12'/>
<interface dev='eth13'/>
</forward>
The first of these takes the place of the dev attribute that is
normally in <forward> - when defining a network you can specify
either one, and on output both will be present. If you specify
both on input, they must match.
2) In addition to forward modes of 'nat' and 'route', these new modes
are supported:
private, passthrough, vepa - when this network is referenced by a
domain's interface, it will have the same effect as if the
interface had been defined as type='direct', e.g.:
<interface type='direct'>
<source mode='${mode}' dev='${dev}>
...
</interface>
where ${mode} is one of the three new modes, and ${dev} is an interface
selected from the list given in <forward>.
bridge - if a <forward> dev (or multiple devs) is defined, and
forward mode is 'bridge' this is just like the modes 'private',
'passthrough', and 'vepa' above. If there is no forward dev
specified but a bridge name is given (e.g. "<bridge
name='br0'/>"), then guest interfaces using this network will use
libvirt's "host bridge" mode, equivalent to this:
<interface type='bridge'>
<source bridge='${bridge-name}'/>
...
</interface>
3) A network can have multiple <portgroup> elements, which may be
selected by the guest interface definition (by adding
"portgroup='${name}'" in the <source> element along with the
network name). Currently a portgroup can only contain a
virtportprofile, but the intent is that other configuration items
may be put there int the future (e.g. bandwidth config). When
building a guest's interface, if the <interface> XML itself has no
virtportprofile, and if the requested network has a portgroup with
a name matching the name given in the <interface> (or if one of the
network's portgroups is marked with the "default='yes'" attribute),
the virtportprofile from that portgroup will be used by the
interface.
4) A network can have a virtportprofile defined at the top level,
which will be used by a guest interface when connecting in one of
the 'direct' modes if the guest interface XML itself hasn't
specified any virtportprofile, and if there are also no matching
portgroups on the network.
2011-07-20 03:01:09 +00:00
|
|
|
forwardDev = NULL;
|
2012-08-16 15:41:41 +00:00
|
|
|
def->forwardIfs[ii].type = VIR_NETWORK_FORWARD_HOSTDEV_DEVICE_NETDEV;
|
conf: support abstracted interface info in network XML
The network XML is updated in the following ways:
1) The <forward> element can now contain a list of forward interfaces:
<forward .... >
<interface dev='eth10'/>
<interface dev='eth11'/>
<interface dev='eth12'/>
<interface dev='eth13'/>
</forward>
The first of these takes the place of the dev attribute that is
normally in <forward> - when defining a network you can specify
either one, and on output both will be present. If you specify
both on input, they must match.
2) In addition to forward modes of 'nat' and 'route', these new modes
are supported:
private, passthrough, vepa - when this network is referenced by a
domain's interface, it will have the same effect as if the
interface had been defined as type='direct', e.g.:
<interface type='direct'>
<source mode='${mode}' dev='${dev}>
...
</interface>
where ${mode} is one of the three new modes, and ${dev} is an interface
selected from the list given in <forward>.
bridge - if a <forward> dev (or multiple devs) is defined, and
forward mode is 'bridge' this is just like the modes 'private',
'passthrough', and 'vepa' above. If there is no forward dev
specified but a bridge name is given (e.g. "<bridge
name='br0'/>"), then guest interfaces using this network will use
libvirt's "host bridge" mode, equivalent to this:
<interface type='bridge'>
<source bridge='${bridge-name}'/>
...
</interface>
3) A network can have multiple <portgroup> elements, which may be
selected by the guest interface definition (by adding
"portgroup='${name}'" in the <source> element along with the
network name). Currently a portgroup can only contain a
virtportprofile, but the intent is that other configuration items
may be put there int the future (e.g. bandwidth config). When
building a guest's interface, if the <interface> XML itself has no
virtportprofile, and if the requested network has a portgroup with
a name matching the name given in the <interface> (or if one of the
network's portgroups is marked with the "default='yes'" attribute),
the virtportprofile from that portgroup will be used by the
interface.
4) A network can have a virtportprofile defined at the top level,
which will be used by a guest interface when connecting in one of
the 'direct' modes if the guest interface XML itself hasn't
specified any virtportprofile, and if there are also no matching
portgroups on the network.
2011-07-20 03:01:09 +00:00
|
|
|
def->nForwardIfs++;
|
|
|
|
}
|
|
|
|
}
|
2012-08-16 15:41:41 +00:00
|
|
|
VIR_FREE(type);
|
2011-12-14 10:50:23 +00:00
|
|
|
VIR_FREE(forwardDev);
|
2012-08-16 15:41:41 +00:00
|
|
|
VIR_FREE(forwardManaged);
|
2011-12-14 10:50:23 +00:00
|
|
|
VIR_FREE(forwardPfNodes);
|
conf: support abstracted interface info in network XML
The network XML is updated in the following ways:
1) The <forward> element can now contain a list of forward interfaces:
<forward .... >
<interface dev='eth10'/>
<interface dev='eth11'/>
<interface dev='eth12'/>
<interface dev='eth13'/>
</forward>
The first of these takes the place of the dev attribute that is
normally in <forward> - when defining a network you can specify
either one, and on output both will be present. If you specify
both on input, they must match.
2) In addition to forward modes of 'nat' and 'route', these new modes
are supported:
private, passthrough, vepa - when this network is referenced by a
domain's interface, it will have the same effect as if the
interface had been defined as type='direct', e.g.:
<interface type='direct'>
<source mode='${mode}' dev='${dev}>
...
</interface>
where ${mode} is one of the three new modes, and ${dev} is an interface
selected from the list given in <forward>.
bridge - if a <forward> dev (or multiple devs) is defined, and
forward mode is 'bridge' this is just like the modes 'private',
'passthrough', and 'vepa' above. If there is no forward dev
specified but a bridge name is given (e.g. "<bridge
name='br0'/>"), then guest interfaces using this network will use
libvirt's "host bridge" mode, equivalent to this:
<interface type='bridge'>
<source bridge='${bridge-name}'/>
...
</interface>
3) A network can have multiple <portgroup> elements, which may be
selected by the guest interface definition (by adding
"portgroup='${name}'" in the <source> element along with the
network name). Currently a portgroup can only contain a
virtportprofile, but the intent is that other configuration items
may be put there int the future (e.g. bandwidth config). When
building a guest's interface, if the <interface> XML itself has no
virtportprofile, and if the requested network has a portgroup with
a name matching the name given in the <interface> (or if one of the
network's portgroups is marked with the "default='yes'" attribute),
the virtportprofile from that portgroup will be used by the
interface.
4) A network can have a virtportprofile defined at the top level,
which will be used by a guest interface when connecting in one of
the 'direct' modes if the guest interface XML itself hasn't
specified any virtportprofile, and if there are also no matching
portgroups on the network.
2011-07-20 03:01:09 +00:00
|
|
|
VIR_FREE(forwardIfNodes);
|
2012-08-16 15:41:41 +00:00
|
|
|
VIR_FREE(forwardAddrNodes);
|
conf: support abstracted interface info in network XML
The network XML is updated in the following ways:
1) The <forward> element can now contain a list of forward interfaces:
<forward .... >
<interface dev='eth10'/>
<interface dev='eth11'/>
<interface dev='eth12'/>
<interface dev='eth13'/>
</forward>
The first of these takes the place of the dev attribute that is
normally in <forward> - when defining a network you can specify
either one, and on output both will be present. If you specify
both on input, they must match.
2) In addition to forward modes of 'nat' and 'route', these new modes
are supported:
private, passthrough, vepa - when this network is referenced by a
domain's interface, it will have the same effect as if the
interface had been defined as type='direct', e.g.:
<interface type='direct'>
<source mode='${mode}' dev='${dev}>
...
</interface>
where ${mode} is one of the three new modes, and ${dev} is an interface
selected from the list given in <forward>.
bridge - if a <forward> dev (or multiple devs) is defined, and
forward mode is 'bridge' this is just like the modes 'private',
'passthrough', and 'vepa' above. If there is no forward dev
specified but a bridge name is given (e.g. "<bridge
name='br0'/>"), then guest interfaces using this network will use
libvirt's "host bridge" mode, equivalent to this:
<interface type='bridge'>
<source bridge='${bridge-name}'/>
...
</interface>
3) A network can have multiple <portgroup> elements, which may be
selected by the guest interface definition (by adding
"portgroup='${name}'" in the <source> element along with the
network name). Currently a portgroup can only contain a
virtportprofile, but the intent is that other configuration items
may be put there int the future (e.g. bandwidth config). When
building a guest's interface, if the <interface> XML itself has no
virtportprofile, and if the requested network has a portgroup with
a name matching the name given in the <interface> (or if one of the
network's portgroups is marked with the "default='yes'" attribute),
the virtportprofile from that portgroup will be used by the
interface.
4) A network can have a virtportprofile defined at the top level,
which will be used by a guest interface when connecting in one of
the 'direct' modes if the guest interface XML itself hasn't
specified any virtportprofile, and if there are also no matching
portgroups on the network.
2011-07-20 03:01:09 +00:00
|
|
|
switch (def->forwardType) {
|
|
|
|
case VIR_NETWORK_FORWARD_ROUTE:
|
|
|
|
case VIR_NETWORK_FORWARD_NAT:
|
|
|
|
/* It's pointless to specify L3 forwarding without specifying
|
|
|
|
* the network we're on.
|
|
|
|
*/
|
|
|
|
if (def->nips == 0) {
|
2012-07-18 10:50:44 +00:00
|
|
|
virReportError(VIR_ERR_XML_ERROR,
|
|
|
|
_("%s forwarding requested, but no IP address provided for network '%s'"),
|
|
|
|
virNetworkForwardTypeToString(def->forwardType),
|
|
|
|
def->name);
|
conf: support abstracted interface info in network XML
The network XML is updated in the following ways:
1) The <forward> element can now contain a list of forward interfaces:
<forward .... >
<interface dev='eth10'/>
<interface dev='eth11'/>
<interface dev='eth12'/>
<interface dev='eth13'/>
</forward>
The first of these takes the place of the dev attribute that is
normally in <forward> - when defining a network you can specify
either one, and on output both will be present. If you specify
both on input, they must match.
2) In addition to forward modes of 'nat' and 'route', these new modes
are supported:
private, passthrough, vepa - when this network is referenced by a
domain's interface, it will have the same effect as if the
interface had been defined as type='direct', e.g.:
<interface type='direct'>
<source mode='${mode}' dev='${dev}>
...
</interface>
where ${mode} is one of the three new modes, and ${dev} is an interface
selected from the list given in <forward>.
bridge - if a <forward> dev (or multiple devs) is defined, and
forward mode is 'bridge' this is just like the modes 'private',
'passthrough', and 'vepa' above. If there is no forward dev
specified but a bridge name is given (e.g. "<bridge
name='br0'/>"), then guest interfaces using this network will use
libvirt's "host bridge" mode, equivalent to this:
<interface type='bridge'>
<source bridge='${bridge-name}'/>
...
</interface>
3) A network can have multiple <portgroup> elements, which may be
selected by the guest interface definition (by adding
"portgroup='${name}'" in the <source> element along with the
network name). Currently a portgroup can only contain a
virtportprofile, but the intent is that other configuration items
may be put there int the future (e.g. bandwidth config). When
building a guest's interface, if the <interface> XML itself has no
virtportprofile, and if the requested network has a portgroup with
a name matching the name given in the <interface> (or if one of the
network's portgroups is marked with the "default='yes'" attribute),
the virtportprofile from that portgroup will be used by the
interface.
4) A network can have a virtportprofile defined at the top level,
which will be used by a guest interface when connecting in one of
the 'direct' modes if the guest interface XML itself hasn't
specified any virtportprofile, and if there are also no matching
portgroups on the network.
2011-07-20 03:01:09 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
if (def->nForwardIfs > 1) {
|
2012-07-18 10:50:44 +00:00
|
|
|
virReportError(VIR_ERR_XML_ERROR,
|
|
|
|
_("multiple forwarding interfaces specified for network '%s', only one is supported"),
|
|
|
|
def->name);
|
conf: support abstracted interface info in network XML
The network XML is updated in the following ways:
1) The <forward> element can now contain a list of forward interfaces:
<forward .... >
<interface dev='eth10'/>
<interface dev='eth11'/>
<interface dev='eth12'/>
<interface dev='eth13'/>
</forward>
The first of these takes the place of the dev attribute that is
normally in <forward> - when defining a network you can specify
either one, and on output both will be present. If you specify
both on input, they must match.
2) In addition to forward modes of 'nat' and 'route', these new modes
are supported:
private, passthrough, vepa - when this network is referenced by a
domain's interface, it will have the same effect as if the
interface had been defined as type='direct', e.g.:
<interface type='direct'>
<source mode='${mode}' dev='${dev}>
...
</interface>
where ${mode} is one of the three new modes, and ${dev} is an interface
selected from the list given in <forward>.
bridge - if a <forward> dev (or multiple devs) is defined, and
forward mode is 'bridge' this is just like the modes 'private',
'passthrough', and 'vepa' above. If there is no forward dev
specified but a bridge name is given (e.g. "<bridge
name='br0'/>"), then guest interfaces using this network will use
libvirt's "host bridge" mode, equivalent to this:
<interface type='bridge'>
<source bridge='${bridge-name}'/>
...
</interface>
3) A network can have multiple <portgroup> elements, which may be
selected by the guest interface definition (by adding
"portgroup='${name}'" in the <source> element along with the
network name). Currently a portgroup can only contain a
virtportprofile, but the intent is that other configuration items
may be put there int the future (e.g. bandwidth config). When
building a guest's interface, if the <interface> XML itself has no
virtportprofile, and if the requested network has a portgroup with
a name matching the name given in the <interface> (or if one of the
network's portgroups is marked with the "default='yes'" attribute),
the virtportprofile from that portgroup will be used by the
interface.
4) A network can have a virtportprofile defined at the top level,
which will be used by a guest interface when connecting in one of
the 'direct' modes if the guest interface XML itself hasn't
specified any virtportprofile, and if there are also no matching
portgroups on the network.
2011-07-20 03:01:09 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
def->stp = (stp && STREQ(stp, "off")) ? 0 : 1;
|
|
|
|
break;
|
|
|
|
case VIR_NETWORK_FORWARD_PRIVATE:
|
|
|
|
case VIR_NETWORK_FORWARD_VEPA:
|
|
|
|
case VIR_NETWORK_FORWARD_PASSTHROUGH:
|
2012-08-16 15:41:41 +00:00
|
|
|
case VIR_NETWORK_FORWARD_HOSTDEV:
|
conf: support abstracted interface info in network XML
The network XML is updated in the following ways:
1) The <forward> element can now contain a list of forward interfaces:
<forward .... >
<interface dev='eth10'/>
<interface dev='eth11'/>
<interface dev='eth12'/>
<interface dev='eth13'/>
</forward>
The first of these takes the place of the dev attribute that is
normally in <forward> - when defining a network you can specify
either one, and on output both will be present. If you specify
both on input, they must match.
2) In addition to forward modes of 'nat' and 'route', these new modes
are supported:
private, passthrough, vepa - when this network is referenced by a
domain's interface, it will have the same effect as if the
interface had been defined as type='direct', e.g.:
<interface type='direct'>
<source mode='${mode}' dev='${dev}>
...
</interface>
where ${mode} is one of the three new modes, and ${dev} is an interface
selected from the list given in <forward>.
bridge - if a <forward> dev (or multiple devs) is defined, and
forward mode is 'bridge' this is just like the modes 'private',
'passthrough', and 'vepa' above. If there is no forward dev
specified but a bridge name is given (e.g. "<bridge
name='br0'/>"), then guest interfaces using this network will use
libvirt's "host bridge" mode, equivalent to this:
<interface type='bridge'>
<source bridge='${bridge-name}'/>
...
</interface>
3) A network can have multiple <portgroup> elements, which may be
selected by the guest interface definition (by adding
"portgroup='${name}'" in the <source> element along with the
network name). Currently a portgroup can only contain a
virtportprofile, but the intent is that other configuration items
may be put there int the future (e.g. bandwidth config). When
building a guest's interface, if the <interface> XML itself has no
virtportprofile, and if the requested network has a portgroup with
a name matching the name given in the <interface> (or if one of the
network's portgroups is marked with the "default='yes'" attribute),
the virtportprofile from that portgroup will be used by the
interface.
4) A network can have a virtportprofile defined at the top level,
which will be used by a guest interface when connecting in one of
the 'direct' modes if the guest interface XML itself hasn't
specified any virtportprofile, and if there are also no matching
portgroups on the network.
2011-07-20 03:01:09 +00:00
|
|
|
if (def->bridge) {
|
2012-07-18 10:50:44 +00:00
|
|
|
virReportError(VIR_ERR_XML_ERROR,
|
|
|
|
_("bridge name not allowed in %s mode (network '%s')"),
|
|
|
|
virNetworkForwardTypeToString(def->forwardType),
|
|
|
|
def->name);
|
conf: support abstracted interface info in network XML
The network XML is updated in the following ways:
1) The <forward> element can now contain a list of forward interfaces:
<forward .... >
<interface dev='eth10'/>
<interface dev='eth11'/>
<interface dev='eth12'/>
<interface dev='eth13'/>
</forward>
The first of these takes the place of the dev attribute that is
normally in <forward> - when defining a network you can specify
either one, and on output both will be present. If you specify
both on input, they must match.
2) In addition to forward modes of 'nat' and 'route', these new modes
are supported:
private, passthrough, vepa - when this network is referenced by a
domain's interface, it will have the same effect as if the
interface had been defined as type='direct', e.g.:
<interface type='direct'>
<source mode='${mode}' dev='${dev}>
...
</interface>
where ${mode} is one of the three new modes, and ${dev} is an interface
selected from the list given in <forward>.
bridge - if a <forward> dev (or multiple devs) is defined, and
forward mode is 'bridge' this is just like the modes 'private',
'passthrough', and 'vepa' above. If there is no forward dev
specified but a bridge name is given (e.g. "<bridge
name='br0'/>"), then guest interfaces using this network will use
libvirt's "host bridge" mode, equivalent to this:
<interface type='bridge'>
<source bridge='${bridge-name}'/>
...
</interface>
3) A network can have multiple <portgroup> elements, which may be
selected by the guest interface definition (by adding
"portgroup='${name}'" in the <source> element along with the
network name). Currently a portgroup can only contain a
virtportprofile, but the intent is that other configuration items
may be put there int the future (e.g. bandwidth config). When
building a guest's interface, if the <interface> XML itself has no
virtportprofile, and if the requested network has a portgroup with
a name matching the name given in the <interface> (or if one of the
network's portgroups is marked with the "default='yes'" attribute),
the virtportprofile from that portgroup will be used by the
interface.
4) A network can have a virtportprofile defined at the top level,
which will be used by a guest interface when connecting in one of
the 'direct' modes if the guest interface XML itself hasn't
specified any virtportprofile, and if there are also no matching
portgroups on the network.
2011-07-20 03:01:09 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
/* fall through to next case */
|
|
|
|
case VIR_NETWORK_FORWARD_BRIDGE:
|
|
|
|
if (def->delay || stp) {
|
2012-07-18 10:50:44 +00:00
|
|
|
virReportError(VIR_ERR_XML_ERROR,
|
|
|
|
_("bridge delay/stp options only allowed in route, nat, and isolated mode, not in %s (network '%s')"),
|
|
|
|
virNetworkForwardTypeToString(def->forwardType),
|
|
|
|
def->name);
|
conf: support abstracted interface info in network XML
The network XML is updated in the following ways:
1) The <forward> element can now contain a list of forward interfaces:
<forward .... >
<interface dev='eth10'/>
<interface dev='eth11'/>
<interface dev='eth12'/>
<interface dev='eth13'/>
</forward>
The first of these takes the place of the dev attribute that is
normally in <forward> - when defining a network you can specify
either one, and on output both will be present. If you specify
both on input, they must match.
2) In addition to forward modes of 'nat' and 'route', these new modes
are supported:
private, passthrough, vepa - when this network is referenced by a
domain's interface, it will have the same effect as if the
interface had been defined as type='direct', e.g.:
<interface type='direct'>
<source mode='${mode}' dev='${dev}>
...
</interface>
where ${mode} is one of the three new modes, and ${dev} is an interface
selected from the list given in <forward>.
bridge - if a <forward> dev (or multiple devs) is defined, and
forward mode is 'bridge' this is just like the modes 'private',
'passthrough', and 'vepa' above. If there is no forward dev
specified but a bridge name is given (e.g. "<bridge
name='br0'/>"), then guest interfaces using this network will use
libvirt's "host bridge" mode, equivalent to this:
<interface type='bridge'>
<source bridge='${bridge-name}'/>
...
</interface>
3) A network can have multiple <portgroup> elements, which may be
selected by the guest interface definition (by adding
"portgroup='${name}'" in the <source> element along with the
network name). Currently a portgroup can only contain a
virtportprofile, but the intent is that other configuration items
may be put there int the future (e.g. bandwidth config). When
building a guest's interface, if the <interface> XML itself has no
virtportprofile, and if the requested network has a portgroup with
a name matching the name given in the <interface> (or if one of the
network's portgroups is marked with the "default='yes'" attribute),
the virtportprofile from that portgroup will be used by the
interface.
4) A network can have a virtportprofile defined at the top level,
which will be used by a guest interface when connecting in one of
the 'direct' modes if the guest interface XML itself hasn't
specified any virtportprofile, and if there are also no matching
portgroups on the network.
2011-07-20 03:01:09 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
VIR_FREE(stp);
|
|
|
|
ctxt->node = save;
|
2008-07-11 10:48:34 +00:00
|
|
|
return def;
|
|
|
|
|
|
|
|
error:
|
conf: support abstracted interface info in network XML
The network XML is updated in the following ways:
1) The <forward> element can now contain a list of forward interfaces:
<forward .... >
<interface dev='eth10'/>
<interface dev='eth11'/>
<interface dev='eth12'/>
<interface dev='eth13'/>
</forward>
The first of these takes the place of the dev attribute that is
normally in <forward> - when defining a network you can specify
either one, and on output both will be present. If you specify
both on input, they must match.
2) In addition to forward modes of 'nat' and 'route', these new modes
are supported:
private, passthrough, vepa - when this network is referenced by a
domain's interface, it will have the same effect as if the
interface had been defined as type='direct', e.g.:
<interface type='direct'>
<source mode='${mode}' dev='${dev}>
...
</interface>
where ${mode} is one of the three new modes, and ${dev} is an interface
selected from the list given in <forward>.
bridge - if a <forward> dev (or multiple devs) is defined, and
forward mode is 'bridge' this is just like the modes 'private',
'passthrough', and 'vepa' above. If there is no forward dev
specified but a bridge name is given (e.g. "<bridge
name='br0'/>"), then guest interfaces using this network will use
libvirt's "host bridge" mode, equivalent to this:
<interface type='bridge'>
<source bridge='${bridge-name}'/>
...
</interface>
3) A network can have multiple <portgroup> elements, which may be
selected by the guest interface definition (by adding
"portgroup='${name}'" in the <source> element along with the
network name). Currently a portgroup can only contain a
virtportprofile, but the intent is that other configuration items
may be put there int the future (e.g. bandwidth config). When
building a guest's interface, if the <interface> XML itself has no
virtportprofile, and if the requested network has a portgroup with
a name matching the name given in the <interface> (or if one of the
network's portgroups is marked with the "default='yes'" attribute),
the virtportprofile from that portgroup will be used by the
interface.
4) A network can have a virtportprofile defined at the top level,
which will be used by a guest interface when connecting in one of
the 'direct' modes if the guest interface XML itself hasn't
specified any virtportprofile, and if there are also no matching
portgroups on the network.
2011-07-20 03:01:09 +00:00
|
|
|
VIR_FREE(stp);
|
2008-07-11 10:48:34 +00:00
|
|
|
virNetworkDefFree(def);
|
2011-01-10 22:35:37 +00:00
|
|
|
VIR_FREE(ipNodes);
|
conf: support abstracted interface info in network XML
The network XML is updated in the following ways:
1) The <forward> element can now contain a list of forward interfaces:
<forward .... >
<interface dev='eth10'/>
<interface dev='eth11'/>
<interface dev='eth12'/>
<interface dev='eth13'/>
</forward>
The first of these takes the place of the dev attribute that is
normally in <forward> - when defining a network you can specify
either one, and on output both will be present. If you specify
both on input, they must match.
2) In addition to forward modes of 'nat' and 'route', these new modes
are supported:
private, passthrough, vepa - when this network is referenced by a
domain's interface, it will have the same effect as if the
interface had been defined as type='direct', e.g.:
<interface type='direct'>
<source mode='${mode}' dev='${dev}>
...
</interface>
where ${mode} is one of the three new modes, and ${dev} is an interface
selected from the list given in <forward>.
bridge - if a <forward> dev (or multiple devs) is defined, and
forward mode is 'bridge' this is just like the modes 'private',
'passthrough', and 'vepa' above. If there is no forward dev
specified but a bridge name is given (e.g. "<bridge
name='br0'/>"), then guest interfaces using this network will use
libvirt's "host bridge" mode, equivalent to this:
<interface type='bridge'>
<source bridge='${bridge-name}'/>
...
</interface>
3) A network can have multiple <portgroup> elements, which may be
selected by the guest interface definition (by adding
"portgroup='${name}'" in the <source> element along with the
network name). Currently a portgroup can only contain a
virtportprofile, but the intent is that other configuration items
may be put there int the future (e.g. bandwidth config). When
building a guest's interface, if the <interface> XML itself has no
virtportprofile, and if the requested network has a portgroup with
a name matching the name given in the <interface> (or if one of the
network's portgroups is marked with the "default='yes'" attribute),
the virtportprofile from that portgroup will be used by the
interface.
4) A network can have a virtportprofile defined at the top level,
which will be used by a guest interface when connecting in one of
the 'direct' modes if the guest interface XML itself hasn't
specified any virtportprofile, and if there are also no matching
portgroups on the network.
2011-07-20 03:01:09 +00:00
|
|
|
VIR_FREE(portGroupNodes);
|
|
|
|
VIR_FREE(forwardIfNodes);
|
2011-12-14 10:50:23 +00:00
|
|
|
VIR_FREE(forwardPfNodes);
|
conf: support abstracted interface info in network XML
The network XML is updated in the following ways:
1) The <forward> element can now contain a list of forward interfaces:
<forward .... >
<interface dev='eth10'/>
<interface dev='eth11'/>
<interface dev='eth12'/>
<interface dev='eth13'/>
</forward>
The first of these takes the place of the dev attribute that is
normally in <forward> - when defining a network you can specify
either one, and on output both will be present. If you specify
both on input, they must match.
2) In addition to forward modes of 'nat' and 'route', these new modes
are supported:
private, passthrough, vepa - when this network is referenced by a
domain's interface, it will have the same effect as if the
interface had been defined as type='direct', e.g.:
<interface type='direct'>
<source mode='${mode}' dev='${dev}>
...
</interface>
where ${mode} is one of the three new modes, and ${dev} is an interface
selected from the list given in <forward>.
bridge - if a <forward> dev (or multiple devs) is defined, and
forward mode is 'bridge' this is just like the modes 'private',
'passthrough', and 'vepa' above. If there is no forward dev
specified but a bridge name is given (e.g. "<bridge
name='br0'/>"), then guest interfaces using this network will use
libvirt's "host bridge" mode, equivalent to this:
<interface type='bridge'>
<source bridge='${bridge-name}'/>
...
</interface>
3) A network can have multiple <portgroup> elements, which may be
selected by the guest interface definition (by adding
"portgroup='${name}'" in the <source> element along with the
network name). Currently a portgroup can only contain a
virtportprofile, but the intent is that other configuration items
may be put there int the future (e.g. bandwidth config). When
building a guest's interface, if the <interface> XML itself has no
virtportprofile, and if the requested network has a portgroup with
a name matching the name given in the <interface> (or if one of the
network's portgroups is marked with the "default='yes'" attribute),
the virtportprofile from that portgroup will be used by the
interface.
4) A network can have a virtportprofile defined at the top level,
which will be used by a guest interface when connecting in one of
the 'direct' modes if the guest interface XML itself hasn't
specified any virtportprofile, and if there are also no matching
portgroups on the network.
2011-07-20 03:01:09 +00:00
|
|
|
VIR_FREE(forwardDev);
|
|
|
|
ctxt->node = save;
|
2008-07-11 10:48:34 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2010-02-24 20:53:16 +00:00
|
|
|
static virNetworkDefPtr
|
|
|
|
virNetworkDefParse(const char *xmlStr,
|
|
|
|
const char *filename)
|
2008-07-11 10:48:34 +00:00
|
|
|
{
|
2010-02-24 20:53:16 +00:00
|
|
|
xmlDocPtr xml;
|
2008-08-01 09:39:44 +00:00
|
|
|
virNetworkDefPtr def = NULL;
|
2008-07-11 10:48:34 +00:00
|
|
|
|
2011-09-14 14:17:57 +00:00
|
|
|
if ((xml = virXMLParse(filename, xmlStr, _("(network_definition)")))) {
|
2010-02-24 20:53:16 +00:00
|
|
|
def = virNetworkDefParseNode(xml, xmlDocGetRootElement(xml));
|
|
|
|
xmlFreeDoc(xml);
|
2008-07-11 10:48:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return def;
|
|
|
|
}
|
|
|
|
|
2010-02-24 20:53:16 +00:00
|
|
|
virNetworkDefPtr virNetworkDefParseString(const char *xmlStr)
|
2008-07-11 10:48:34 +00:00
|
|
|
{
|
2010-02-24 20:53:16 +00:00
|
|
|
return virNetworkDefParse(xmlStr, NULL);
|
|
|
|
}
|
2008-07-11 10:48:34 +00:00
|
|
|
|
2010-02-24 20:53:16 +00:00
|
|
|
virNetworkDefPtr virNetworkDefParseFile(const char *filename)
|
|
|
|
{
|
|
|
|
return virNetworkDefParse(NULL, filename);
|
2008-07-11 10:48:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-02-10 10:22:52 +00:00
|
|
|
virNetworkDefPtr virNetworkDefParseNode(xmlDocPtr xml,
|
2008-07-11 10:48:34 +00:00
|
|
|
xmlNodePtr root)
|
|
|
|
{
|
|
|
|
xmlXPathContextPtr ctxt = NULL;
|
|
|
|
virNetworkDefPtr def = NULL;
|
|
|
|
|
|
|
|
if (!xmlStrEqual(root->name, BAD_CAST "network")) {
|
2012-07-18 10:50:44 +00:00
|
|
|
virReportError(VIR_ERR_XML_ERROR,
|
|
|
|
_("unexpected root element <%s>, "
|
|
|
|
"expecting <network>"),
|
|
|
|
root->name);
|
2008-07-11 10:48:34 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
ctxt = xmlXPathNewContext(xml);
|
|
|
|
if (ctxt == NULL) {
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
2008-07-11 10:48:34 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
ctxt->node = root;
|
2010-02-10 10:22:52 +00:00
|
|
|
def = virNetworkDefParseXML(ctxt);
|
2008-07-11 10:48:34 +00:00
|
|
|
|
|
|
|
cleanup:
|
|
|
|
xmlXPathFreeContext(ctxt);
|
|
|
|
return def;
|
|
|
|
}
|
|
|
|
|
2011-06-24 10:04:36 +00:00
|
|
|
static int
|
|
|
|
virNetworkDNSDefFormat(virBufferPtr buf,
|
|
|
|
virNetworkDNSDefPtr def)
|
|
|
|
{
|
|
|
|
int result = 0;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (def == NULL)
|
|
|
|
goto out;
|
|
|
|
|
2012-08-16 15:41:41 +00:00
|
|
|
virBufferAddLit(buf, "<dns>\n");
|
|
|
|
virBufferAdjustIndent(buf, 2);
|
2011-06-24 10:04:36 +00:00
|
|
|
|
|
|
|
for (i = 0 ; i < def->ntxtrecords ; i++) {
|
2012-08-16 15:41:41 +00:00
|
|
|
virBufferAsprintf(buf, "<txt name='%s' value='%s' />\n",
|
2011-06-24 10:04:36 +00:00
|
|
|
def->txtrecords[i].name,
|
|
|
|
def->txtrecords[i].value);
|
|
|
|
}
|
|
|
|
|
2012-01-02 14:23:54 +00:00
|
|
|
for (i = 0 ; i < def->nsrvrecords ; i++) {
|
|
|
|
if (def->srvrecords[i].service && def->srvrecords[i].protocol) {
|
2012-08-16 15:41:41 +00:00
|
|
|
virBufferAsprintf(buf, "<srv service='%s' protocol='%s'",
|
2012-01-02 14:23:54 +00:00
|
|
|
def->srvrecords[i].service,
|
|
|
|
def->srvrecords[i].protocol);
|
|
|
|
|
|
|
|
if (def->srvrecords[i].domain)
|
|
|
|
virBufferAsprintf(buf, " domain='%s'", def->srvrecords[i].domain);
|
|
|
|
if (def->srvrecords[i].target)
|
|
|
|
virBufferAsprintf(buf, " target='%s'", def->srvrecords[i].target);
|
|
|
|
if (def->srvrecords[i].port)
|
|
|
|
virBufferAsprintf(buf, " port='%d'", def->srvrecords[i].port);
|
|
|
|
if (def->srvrecords[i].priority)
|
|
|
|
virBufferAsprintf(buf, " priority='%d'", def->srvrecords[i].priority);
|
|
|
|
if (def->srvrecords[i].weight)
|
|
|
|
virBufferAsprintf(buf, " weight='%d'", def->srvrecords[i].weight);
|
|
|
|
|
|
|
|
virBufferAsprintf(buf, "/>\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-06-24 10:04:40 +00:00
|
|
|
if (def->nhosts) {
|
|
|
|
int ii, j;
|
|
|
|
|
|
|
|
for (ii = 0 ; ii < def->nhosts; ii++) {
|
Santize naming of socket address APIs
The socket address APIs in src/util/network.h either take the
form virSocketAddrXXX, virSocketXXX or virSocketXXXAddr.
Sanitize this so everything is virSocketAddrXXXX, and ensure
that the virSocketAddr parameter is always the first one.
* src/util/network.c, src/util/network.h: Santize socket
address API naming
* src/conf/domain_conf.c, src/conf/network_conf.c,
src/conf/nwfilter_conf.c, src/network/bridge_driver.c,
src/nwfilter/nwfilter_ebiptables_driver.c,
src/nwfilter/nwfilter_learnipaddr.c,
src/qemu/qemu_command.c, src/rpc/virnetsocket.c,
src/util/dnsmasq.c, src/util/iptables.c,
src/util/virnetdev.c, src/vbox/vbox_tmpl.c: Update for
API renaming
2011-11-02 14:06:59 +00:00
|
|
|
char *ip = virSocketAddrFormat(&def->hosts[ii].ip);
|
2011-06-24 10:04:40 +00:00
|
|
|
|
2012-08-16 15:41:41 +00:00
|
|
|
virBufferAsprintf(buf, "<host ip='%s'>\n", ip);
|
|
|
|
virBufferAdjustIndent(buf, 2);
|
2011-06-24 10:04:40 +00:00
|
|
|
for (j = 0; j < def->hosts[ii].nnames; j++)
|
2012-08-16 15:41:41 +00:00
|
|
|
virBufferAsprintf(buf, "<hostname>%s</hostname>\n",
|
|
|
|
def->hosts[ii].names[j]);
|
2011-06-24 10:04:40 +00:00
|
|
|
|
2012-08-16 15:41:41 +00:00
|
|
|
virBufferAdjustIndent(buf, -2);
|
|
|
|
virBufferAsprintf(buf, "</host>\n");
|
2011-06-29 02:45:01 +00:00
|
|
|
VIR_FREE(ip);
|
2011-06-24 10:04:40 +00:00
|
|
|
}
|
|
|
|
}
|
2012-08-16 15:41:41 +00:00
|
|
|
virBufferAdjustIndent(buf, -2);
|
|
|
|
virBufferAddLit(buf, "</dns>\n");
|
2011-06-24 10:04:36 +00:00
|
|
|
out:
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2010-11-17 18:36:19 +00:00
|
|
|
static int
|
|
|
|
virNetworkIpDefFormat(virBufferPtr buf,
|
|
|
|
const virNetworkIpDefPtr def)
|
|
|
|
{
|
|
|
|
int result = -1;
|
|
|
|
|
2012-08-16 15:41:41 +00:00
|
|
|
virBufferAddLit(buf, "<ip");
|
2010-11-17 18:36:19 +00:00
|
|
|
|
|
|
|
if (def->family) {
|
2011-04-30 16:34:49 +00:00
|
|
|
virBufferAsprintf(buf, " family='%s'", def->family);
|
2010-11-17 18:36:19 +00:00
|
|
|
}
|
Santize naming of socket address APIs
The socket address APIs in src/util/network.h either take the
form virSocketAddrXXX, virSocketXXX or virSocketXXXAddr.
Sanitize this so everything is virSocketAddrXXXX, and ensure
that the virSocketAddr parameter is always the first one.
* src/util/network.c, src/util/network.h: Santize socket
address API naming
* src/conf/domain_conf.c, src/conf/network_conf.c,
src/conf/nwfilter_conf.c, src/network/bridge_driver.c,
src/nwfilter/nwfilter_ebiptables_driver.c,
src/nwfilter/nwfilter_learnipaddr.c,
src/qemu/qemu_command.c, src/rpc/virnetsocket.c,
src/util/dnsmasq.c, src/util/iptables.c,
src/util/virnetdev.c, src/vbox/vbox_tmpl.c: Update for
API renaming
2011-11-02 14:06:59 +00:00
|
|
|
if (VIR_SOCKET_ADDR_VALID(&def->address)) {
|
|
|
|
char *addr = virSocketAddrFormat(&def->address);
|
2010-11-17 18:36:19 +00:00
|
|
|
if (!addr)
|
|
|
|
goto error;
|
2011-04-30 16:34:49 +00:00
|
|
|
virBufferAsprintf(buf, " address='%s'", addr);
|
2010-11-17 18:36:19 +00:00
|
|
|
VIR_FREE(addr);
|
|
|
|
}
|
Santize naming of socket address APIs
The socket address APIs in src/util/network.h either take the
form virSocketAddrXXX, virSocketXXX or virSocketXXXAddr.
Sanitize this so everything is virSocketAddrXXXX, and ensure
that the virSocketAddr parameter is always the first one.
* src/util/network.c, src/util/network.h: Santize socket
address API naming
* src/conf/domain_conf.c, src/conf/network_conf.c,
src/conf/nwfilter_conf.c, src/network/bridge_driver.c,
src/nwfilter/nwfilter_ebiptables_driver.c,
src/nwfilter/nwfilter_learnipaddr.c,
src/qemu/qemu_command.c, src/rpc/virnetsocket.c,
src/util/dnsmasq.c, src/util/iptables.c,
src/util/virnetdev.c, src/vbox/vbox_tmpl.c: Update for
API renaming
2011-11-02 14:06:59 +00:00
|
|
|
if (VIR_SOCKET_ADDR_VALID(&def->netmask)) {
|
|
|
|
char *addr = virSocketAddrFormat(&def->netmask);
|
2010-11-17 18:36:19 +00:00
|
|
|
if (!addr)
|
|
|
|
goto error;
|
2011-04-30 16:34:49 +00:00
|
|
|
virBufferAsprintf(buf, " netmask='%s'", addr);
|
2010-11-17 18:36:19 +00:00
|
|
|
VIR_FREE(addr);
|
|
|
|
}
|
|
|
|
if (def->prefix > 0) {
|
2011-04-30 16:34:49 +00:00
|
|
|
virBufferAsprintf(buf," prefix='%u'", def->prefix);
|
2010-11-17 18:36:19 +00:00
|
|
|
}
|
|
|
|
virBufferAddLit(buf, ">\n");
|
2012-08-16 15:41:41 +00:00
|
|
|
virBufferAdjustIndent(buf, 2);
|
2010-11-17 18:36:19 +00:00
|
|
|
|
|
|
|
if (def->tftproot) {
|
2012-08-16 15:41:41 +00:00
|
|
|
virBufferEscapeString(buf, "<tftp root='%s' />\n",
|
2010-11-17 18:36:19 +00:00
|
|
|
def->tftproot);
|
|
|
|
}
|
|
|
|
if ((def->nranges || def->nhosts)) {
|
|
|
|
int ii;
|
2012-08-16 15:41:41 +00:00
|
|
|
virBufferAddLit(buf, "<dhcp>\n");
|
|
|
|
virBufferAdjustIndent(buf, 2);
|
|
|
|
|
2010-11-17 18:36:19 +00:00
|
|
|
for (ii = 0 ; ii < def->nranges ; ii++) {
|
Santize naming of socket address APIs
The socket address APIs in src/util/network.h either take the
form virSocketAddrXXX, virSocketXXX or virSocketXXXAddr.
Sanitize this so everything is virSocketAddrXXXX, and ensure
that the virSocketAddr parameter is always the first one.
* src/util/network.c, src/util/network.h: Santize socket
address API naming
* src/conf/domain_conf.c, src/conf/network_conf.c,
src/conf/nwfilter_conf.c, src/network/bridge_driver.c,
src/nwfilter/nwfilter_ebiptables_driver.c,
src/nwfilter/nwfilter_learnipaddr.c,
src/qemu/qemu_command.c, src/rpc/virnetsocket.c,
src/util/dnsmasq.c, src/util/iptables.c,
src/util/virnetdev.c, src/vbox/vbox_tmpl.c: Update for
API renaming
2011-11-02 14:06:59 +00:00
|
|
|
char *saddr = virSocketAddrFormat(&def->ranges[ii].start);
|
2010-11-17 18:36:19 +00:00
|
|
|
if (!saddr)
|
|
|
|
goto error;
|
Santize naming of socket address APIs
The socket address APIs in src/util/network.h either take the
form virSocketAddrXXX, virSocketXXX or virSocketXXXAddr.
Sanitize this so everything is virSocketAddrXXXX, and ensure
that the virSocketAddr parameter is always the first one.
* src/util/network.c, src/util/network.h: Santize socket
address API naming
* src/conf/domain_conf.c, src/conf/network_conf.c,
src/conf/nwfilter_conf.c, src/network/bridge_driver.c,
src/nwfilter/nwfilter_ebiptables_driver.c,
src/nwfilter/nwfilter_learnipaddr.c,
src/qemu/qemu_command.c, src/rpc/virnetsocket.c,
src/util/dnsmasq.c, src/util/iptables.c,
src/util/virnetdev.c, src/vbox/vbox_tmpl.c: Update for
API renaming
2011-11-02 14:06:59 +00:00
|
|
|
char *eaddr = virSocketAddrFormat(&def->ranges[ii].end);
|
2010-11-17 18:36:19 +00:00
|
|
|
if (!eaddr) {
|
|
|
|
VIR_FREE(saddr);
|
|
|
|
goto error;
|
|
|
|
}
|
2012-08-16 15:41:41 +00:00
|
|
|
virBufferAsprintf(buf, "<range start='%s' end='%s' />\n",
|
2010-11-17 18:36:19 +00:00
|
|
|
saddr, eaddr);
|
|
|
|
VIR_FREE(saddr);
|
|
|
|
VIR_FREE(eaddr);
|
|
|
|
}
|
|
|
|
for (ii = 0 ; ii < def->nhosts ; ii++) {
|
2012-08-16 15:41:41 +00:00
|
|
|
virBufferAddLit(buf, "<host ");
|
2010-11-17 18:36:19 +00:00
|
|
|
if (def->hosts[ii].mac)
|
2011-04-30 16:34:49 +00:00
|
|
|
virBufferAsprintf(buf, "mac='%s' ", def->hosts[ii].mac);
|
2010-11-17 18:36:19 +00:00
|
|
|
if (def->hosts[ii].name)
|
2011-04-30 16:34:49 +00:00
|
|
|
virBufferAsprintf(buf, "name='%s' ", def->hosts[ii].name);
|
Santize naming of socket address APIs
The socket address APIs in src/util/network.h either take the
form virSocketAddrXXX, virSocketXXX or virSocketXXXAddr.
Sanitize this so everything is virSocketAddrXXXX, and ensure
that the virSocketAddr parameter is always the first one.
* src/util/network.c, src/util/network.h: Santize socket
address API naming
* src/conf/domain_conf.c, src/conf/network_conf.c,
src/conf/nwfilter_conf.c, src/network/bridge_driver.c,
src/nwfilter/nwfilter_ebiptables_driver.c,
src/nwfilter/nwfilter_learnipaddr.c,
src/qemu/qemu_command.c, src/rpc/virnetsocket.c,
src/util/dnsmasq.c, src/util/iptables.c,
src/util/virnetdev.c, src/vbox/vbox_tmpl.c: Update for
API renaming
2011-11-02 14:06:59 +00:00
|
|
|
if (VIR_SOCKET_ADDR_VALID(&def->hosts[ii].ip)) {
|
|
|
|
char *ipaddr = virSocketAddrFormat(&def->hosts[ii].ip);
|
2010-11-17 18:36:19 +00:00
|
|
|
if (!ipaddr)
|
|
|
|
goto error;
|
2011-04-30 16:34:49 +00:00
|
|
|
virBufferAsprintf(buf, "ip='%s' ", ipaddr);
|
2010-11-17 18:36:19 +00:00
|
|
|
VIR_FREE(ipaddr);
|
|
|
|
}
|
|
|
|
virBufferAddLit(buf, "/>\n");
|
|
|
|
}
|
|
|
|
if (def->bootfile) {
|
2012-08-16 15:41:41 +00:00
|
|
|
virBufferEscapeString(buf, "<bootp file='%s' ",
|
2010-11-17 18:36:19 +00:00
|
|
|
def->bootfile);
|
Santize naming of socket address APIs
The socket address APIs in src/util/network.h either take the
form virSocketAddrXXX, virSocketXXX or virSocketXXXAddr.
Sanitize this so everything is virSocketAddrXXXX, and ensure
that the virSocketAddr parameter is always the first one.
* src/util/network.c, src/util/network.h: Santize socket
address API naming
* src/conf/domain_conf.c, src/conf/network_conf.c,
src/conf/nwfilter_conf.c, src/network/bridge_driver.c,
src/nwfilter/nwfilter_ebiptables_driver.c,
src/nwfilter/nwfilter_learnipaddr.c,
src/qemu/qemu_command.c, src/rpc/virnetsocket.c,
src/util/dnsmasq.c, src/util/iptables.c,
src/util/virnetdev.c, src/vbox/vbox_tmpl.c: Update for
API renaming
2011-11-02 14:06:59 +00:00
|
|
|
if (VIR_SOCKET_ADDR_VALID(&def->bootserver)) {
|
|
|
|
char *ipaddr = virSocketAddrFormat(&def->bootserver);
|
2010-11-17 18:36:19 +00:00
|
|
|
if (!ipaddr)
|
|
|
|
goto error;
|
|
|
|
virBufferEscapeString(buf, "server='%s' ", ipaddr);
|
|
|
|
VIR_FREE(ipaddr);
|
|
|
|
}
|
|
|
|
virBufferAddLit(buf, "/>\n");
|
2012-08-16 15:41:41 +00:00
|
|
|
|
2010-11-17 18:36:19 +00:00
|
|
|
}
|
|
|
|
|
2012-08-16 15:41:41 +00:00
|
|
|
virBufferAdjustIndent(buf, -2);
|
|
|
|
virBufferAddLit(buf, "</dhcp>\n");
|
2010-11-17 18:36:19 +00:00
|
|
|
}
|
|
|
|
|
2012-08-16 15:41:41 +00:00
|
|
|
virBufferAdjustIndent(buf, -2);
|
|
|
|
virBufferAddLit(buf, "</ip>\n");
|
2010-11-17 18:36:19 +00:00
|
|
|
|
|
|
|
result = 0;
|
|
|
|
error:
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2011-11-02 14:53:35 +00:00
|
|
|
static int
|
conf: support abstracted interface info in network XML
The network XML is updated in the following ways:
1) The <forward> element can now contain a list of forward interfaces:
<forward .... >
<interface dev='eth10'/>
<interface dev='eth11'/>
<interface dev='eth12'/>
<interface dev='eth13'/>
</forward>
The first of these takes the place of the dev attribute that is
normally in <forward> - when defining a network you can specify
either one, and on output both will be present. If you specify
both on input, they must match.
2) In addition to forward modes of 'nat' and 'route', these new modes
are supported:
private, passthrough, vepa - when this network is referenced by a
domain's interface, it will have the same effect as if the
interface had been defined as type='direct', e.g.:
<interface type='direct'>
<source mode='${mode}' dev='${dev}>
...
</interface>
where ${mode} is one of the three new modes, and ${dev} is an interface
selected from the list given in <forward>.
bridge - if a <forward> dev (or multiple devs) is defined, and
forward mode is 'bridge' this is just like the modes 'private',
'passthrough', and 'vepa' above. If there is no forward dev
specified but a bridge name is given (e.g. "<bridge
name='br0'/>"), then guest interfaces using this network will use
libvirt's "host bridge" mode, equivalent to this:
<interface type='bridge'>
<source bridge='${bridge-name}'/>
...
</interface>
3) A network can have multiple <portgroup> elements, which may be
selected by the guest interface definition (by adding
"portgroup='${name}'" in the <source> element along with the
network name). Currently a portgroup can only contain a
virtportprofile, but the intent is that other configuration items
may be put there int the future (e.g. bandwidth config). When
building a guest's interface, if the <interface> XML itself has no
virtportprofile, and if the requested network has a portgroup with
a name matching the name given in the <interface> (or if one of the
network's portgroups is marked with the "default='yes'" attribute),
the virtportprofile from that portgroup will be used by the
interface.
4) A network can have a virtportprofile defined at the top level,
which will be used by a guest interface when connecting in one of
the 'direct' modes if the guest interface XML itself hasn't
specified any virtportprofile, and if there are also no matching
portgroups on the network.
2011-07-20 03:01:09 +00:00
|
|
|
virPortGroupDefFormat(virBufferPtr buf,
|
|
|
|
const virPortGroupDefPtr def)
|
|
|
|
{
|
2012-08-16 15:41:41 +00:00
|
|
|
virBufferAsprintf(buf, "<portgroup name='%s'", def->name);
|
conf: support abstracted interface info in network XML
The network XML is updated in the following ways:
1) The <forward> element can now contain a list of forward interfaces:
<forward .... >
<interface dev='eth10'/>
<interface dev='eth11'/>
<interface dev='eth12'/>
<interface dev='eth13'/>
</forward>
The first of these takes the place of the dev attribute that is
normally in <forward> - when defining a network you can specify
either one, and on output both will be present. If you specify
both on input, they must match.
2) In addition to forward modes of 'nat' and 'route', these new modes
are supported:
private, passthrough, vepa - when this network is referenced by a
domain's interface, it will have the same effect as if the
interface had been defined as type='direct', e.g.:
<interface type='direct'>
<source mode='${mode}' dev='${dev}>
...
</interface>
where ${mode} is one of the three new modes, and ${dev} is an interface
selected from the list given in <forward>.
bridge - if a <forward> dev (or multiple devs) is defined, and
forward mode is 'bridge' this is just like the modes 'private',
'passthrough', and 'vepa' above. If there is no forward dev
specified but a bridge name is given (e.g. "<bridge
name='br0'/>"), then guest interfaces using this network will use
libvirt's "host bridge" mode, equivalent to this:
<interface type='bridge'>
<source bridge='${bridge-name}'/>
...
</interface>
3) A network can have multiple <portgroup> elements, which may be
selected by the guest interface definition (by adding
"portgroup='${name}'" in the <source> element along with the
network name). Currently a portgroup can only contain a
virtportprofile, but the intent is that other configuration items
may be put there int the future (e.g. bandwidth config). When
building a guest's interface, if the <interface> XML itself has no
virtportprofile, and if the requested network has a portgroup with
a name matching the name given in the <interface> (or if one of the
network's portgroups is marked with the "default='yes'" attribute),
the virtportprofile from that portgroup will be used by the
interface.
4) A network can have a virtportprofile defined at the top level,
which will be used by a guest interface when connecting in one of
the 'direct' modes if the guest interface XML itself hasn't
specified any virtportprofile, and if there are also no matching
portgroups on the network.
2011-07-20 03:01:09 +00:00
|
|
|
if (def->isDefault) {
|
|
|
|
virBufferAddLit(buf, " default='yes'");
|
|
|
|
}
|
|
|
|
virBufferAddLit(buf, ">\n");
|
2012-08-16 15:41:41 +00:00
|
|
|
virBufferAdjustIndent(buf, 2);
|
2012-08-12 07:51:30 +00:00
|
|
|
if (virNetDevVlanFormat(&def->vlan, buf) < 0)
|
|
|
|
return -1;
|
2011-11-02 14:53:35 +00:00
|
|
|
if (virNetDevVPortProfileFormat(def->virtPortProfile, buf) < 0)
|
|
|
|
return -1;
|
Adjust naming of network device bandwidth management APIs
Rename virBandwidth to virNetDevBandwidth, and virRate to
virNetDevBandwidthRate.
* src/util/network.c, src/util/network.h: Rename bandwidth
structs and APIs
* src/conf/domain_conf.c, src/conf/domain_conf.h,
src/conf/network_conf.c, src/conf/network_conf.h,
src/lxc/lxc_driver.c, src/network/bridge_driver.c,
src/qemu/qemu_command.c, src/util/macvtap.c,
src/util/macvtap.h, tools/virsh.c: Update for API changes.
2011-11-02 14:29:05 +00:00
|
|
|
virNetDevBandwidthFormat(def->bandwidth, buf);
|
2012-08-16 15:41:41 +00:00
|
|
|
virBufferAdjustIndent(buf, -2);
|
|
|
|
virBufferAddLit(buf, "</portgroup>\n");
|
2011-11-02 14:53:35 +00:00
|
|
|
return 0;
|
conf: support abstracted interface info in network XML
The network XML is updated in the following ways:
1) The <forward> element can now contain a list of forward interfaces:
<forward .... >
<interface dev='eth10'/>
<interface dev='eth11'/>
<interface dev='eth12'/>
<interface dev='eth13'/>
</forward>
The first of these takes the place of the dev attribute that is
normally in <forward> - when defining a network you can specify
either one, and on output both will be present. If you specify
both on input, they must match.
2) In addition to forward modes of 'nat' and 'route', these new modes
are supported:
private, passthrough, vepa - when this network is referenced by a
domain's interface, it will have the same effect as if the
interface had been defined as type='direct', e.g.:
<interface type='direct'>
<source mode='${mode}' dev='${dev}>
...
</interface>
where ${mode} is one of the three new modes, and ${dev} is an interface
selected from the list given in <forward>.
bridge - if a <forward> dev (or multiple devs) is defined, and
forward mode is 'bridge' this is just like the modes 'private',
'passthrough', and 'vepa' above. If there is no forward dev
specified but a bridge name is given (e.g. "<bridge
name='br0'/>"), then guest interfaces using this network will use
libvirt's "host bridge" mode, equivalent to this:
<interface type='bridge'>
<source bridge='${bridge-name}'/>
...
</interface>
3) A network can have multiple <portgroup> elements, which may be
selected by the guest interface definition (by adding
"portgroup='${name}'" in the <source> element along with the
network name). Currently a portgroup can only contain a
virtportprofile, but the intent is that other configuration items
may be put there int the future (e.g. bandwidth config). When
building a guest's interface, if the <interface> XML itself has no
virtportprofile, and if the requested network has a portgroup with
a name matching the name given in the <interface> (or if one of the
network's portgroups is marked with the "default='yes'" attribute),
the virtportprofile from that portgroup will be used by the
interface.
4) A network can have a virtportprofile defined at the top level,
which will be used by a guest interface when connecting in one of
the 'direct' modes if the guest interface XML itself hasn't
specified any virtportprofile, and if there are also no matching
portgroups on the network.
2011-07-20 03:01:09 +00:00
|
|
|
}
|
|
|
|
|
2011-12-14 10:50:40 +00:00
|
|
|
char *virNetworkDefFormat(const virNetworkDefPtr def, unsigned int flags)
|
2008-07-11 10:48:34 +00:00
|
|
|
{
|
|
|
|
virBuffer buf = VIR_BUFFER_INITIALIZER;
|
|
|
|
unsigned char *uuid;
|
|
|
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
2010-11-17 18:36:19 +00:00
|
|
|
int ii;
|
2008-07-11 10:48:34 +00:00
|
|
|
|
2012-08-06 20:17:58 +00:00
|
|
|
virBufferAddLit(&buf, "<network");
|
|
|
|
if (!(flags & VIR_NETWORK_XML_INACTIVE) && (def->connections > 0)) {
|
|
|
|
virBufferAsprintf(&buf, " connections='%d'", def->connections);
|
|
|
|
}
|
|
|
|
virBufferAddLit(&buf, ">\n");
|
2012-08-16 15:41:41 +00:00
|
|
|
virBufferAdjustIndent(&buf, 2);
|
|
|
|
virBufferEscapeString(&buf, "<name>%s</name>\n", def->name);
|
2008-07-11 10:48:34 +00:00
|
|
|
|
|
|
|
uuid = def->uuid;
|
|
|
|
virUUIDFormat(uuid, uuidstr);
|
2012-08-16 15:41:41 +00:00
|
|
|
virBufferAsprintf(&buf, "<uuid>%s</uuid>\n", uuidstr);
|
2008-07-11 10:48:34 +00:00
|
|
|
|
|
|
|
if (def->forwardType != VIR_NETWORK_FORWARD_NONE) {
|
2011-12-14 10:50:23 +00:00
|
|
|
const char *dev = NULL;
|
|
|
|
if (!def->nForwardPfs)
|
|
|
|
dev = virNetworkDefForwardIf(def, 0);
|
2008-07-11 10:48:34 +00:00
|
|
|
const char *mode = virNetworkForwardTypeToString(def->forwardType);
|
conf: support abstracted interface info in network XML
The network XML is updated in the following ways:
1) The <forward> element can now contain a list of forward interfaces:
<forward .... >
<interface dev='eth10'/>
<interface dev='eth11'/>
<interface dev='eth12'/>
<interface dev='eth13'/>
</forward>
The first of these takes the place of the dev attribute that is
normally in <forward> - when defining a network you can specify
either one, and on output both will be present. If you specify
both on input, they must match.
2) In addition to forward modes of 'nat' and 'route', these new modes
are supported:
private, passthrough, vepa - when this network is referenced by a
domain's interface, it will have the same effect as if the
interface had been defined as type='direct', e.g.:
<interface type='direct'>
<source mode='${mode}' dev='${dev}>
...
</interface>
where ${mode} is one of the three new modes, and ${dev} is an interface
selected from the list given in <forward>.
bridge - if a <forward> dev (or multiple devs) is defined, and
forward mode is 'bridge' this is just like the modes 'private',
'passthrough', and 'vepa' above. If there is no forward dev
specified but a bridge name is given (e.g. "<bridge
name='br0'/>"), then guest interfaces using this network will use
libvirt's "host bridge" mode, equivalent to this:
<interface type='bridge'>
<source bridge='${bridge-name}'/>
...
</interface>
3) A network can have multiple <portgroup> elements, which may be
selected by the guest interface definition (by adding
"portgroup='${name}'" in the <source> element along with the
network name). Currently a portgroup can only contain a
virtportprofile, but the intent is that other configuration items
may be put there int the future (e.g. bandwidth config). When
building a guest's interface, if the <interface> XML itself has no
virtportprofile, and if the requested network has a portgroup with
a name matching the name given in the <interface> (or if one of the
network's portgroups is marked with the "default='yes'" attribute),
the virtportprofile from that portgroup will be used by the
interface.
4) A network can have a virtportprofile defined at the top level,
which will be used by a guest interface when connecting in one of
the 'direct' modes if the guest interface XML itself hasn't
specified any virtportprofile, and if there are also no matching
portgroups on the network.
2011-07-20 03:01:09 +00:00
|
|
|
|
|
|
|
if (!mode) {
|
2012-07-18 10:50:44 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Unknown forward type %d in network '%s'"),
|
|
|
|
def->forwardType, def->name);
|
conf: support abstracted interface info in network XML
The network XML is updated in the following ways:
1) The <forward> element can now contain a list of forward interfaces:
<forward .... >
<interface dev='eth10'/>
<interface dev='eth11'/>
<interface dev='eth12'/>
<interface dev='eth13'/>
</forward>
The first of these takes the place of the dev attribute that is
normally in <forward> - when defining a network you can specify
either one, and on output both will be present. If you specify
both on input, they must match.
2) In addition to forward modes of 'nat' and 'route', these new modes
are supported:
private, passthrough, vepa - when this network is referenced by a
domain's interface, it will have the same effect as if the
interface had been defined as type='direct', e.g.:
<interface type='direct'>
<source mode='${mode}' dev='${dev}>
...
</interface>
where ${mode} is one of the three new modes, and ${dev} is an interface
selected from the list given in <forward>.
bridge - if a <forward> dev (or multiple devs) is defined, and
forward mode is 'bridge' this is just like the modes 'private',
'passthrough', and 'vepa' above. If there is no forward dev
specified but a bridge name is given (e.g. "<bridge
name='br0'/>"), then guest interfaces using this network will use
libvirt's "host bridge" mode, equivalent to this:
<interface type='bridge'>
<source bridge='${bridge-name}'/>
...
</interface>
3) A network can have multiple <portgroup> elements, which may be
selected by the guest interface definition (by adding
"portgroup='${name}'" in the <source> element along with the
network name). Currently a portgroup can only contain a
virtportprofile, but the intent is that other configuration items
may be put there int the future (e.g. bandwidth config). When
building a guest's interface, if the <interface> XML itself has no
virtportprofile, and if the requested network has a portgroup with
a name matching the name given in the <interface> (or if one of the
network's portgroups is marked with the "default='yes'" attribute),
the virtportprofile from that portgroup will be used by the
interface.
4) A network can have a virtportprofile defined at the top level,
which will be used by a guest interface when connecting in one of
the 'direct' modes if the guest interface XML itself hasn't
specified any virtportprofile, and if there are also no matching
portgroups on the network.
2011-07-20 03:01:09 +00:00
|
|
|
goto error;
|
|
|
|
}
|
2012-08-16 15:41:41 +00:00
|
|
|
virBufferAddLit(&buf, "<forward");
|
2011-12-14 10:50:23 +00:00
|
|
|
virBufferEscapeString(&buf, " dev='%s'", dev);
|
2012-08-16 15:41:41 +00:00
|
|
|
virBufferAsprintf(&buf, " mode='%s'", mode);
|
|
|
|
if (def->forwardType == VIR_NETWORK_FORWARD_HOSTDEV) {
|
|
|
|
if (def->managed == 1)
|
|
|
|
virBufferAddLit(&buf, " managed='yes'");
|
|
|
|
else
|
|
|
|
virBufferAddLit(&buf, " managed='no'");
|
|
|
|
}
|
|
|
|
virBufferAsprintf(&buf, "%s>\n",
|
2011-12-14 10:50:23 +00:00
|
|
|
(def->nForwardIfs || def->nForwardPfs) ? "" : "/");
|
2012-08-16 15:41:41 +00:00
|
|
|
virBufferAdjustIndent(&buf, 2);
|
2011-12-14 10:50:23 +00:00
|
|
|
|
|
|
|
/* For now, hard-coded to at most 1 forwardPfs */
|
|
|
|
if (def->nForwardPfs)
|
2012-08-16 15:41:41 +00:00
|
|
|
virBufferEscapeString(&buf, "<pf dev='%s'/>\n",
|
2011-12-14 10:50:23 +00:00
|
|
|
def->forwardPfs[0].dev);
|
conf: support abstracted interface info in network XML
The network XML is updated in the following ways:
1) The <forward> element can now contain a list of forward interfaces:
<forward .... >
<interface dev='eth10'/>
<interface dev='eth11'/>
<interface dev='eth12'/>
<interface dev='eth13'/>
</forward>
The first of these takes the place of the dev attribute that is
normally in <forward> - when defining a network you can specify
either one, and on output both will be present. If you specify
both on input, they must match.
2) In addition to forward modes of 'nat' and 'route', these new modes
are supported:
private, passthrough, vepa - when this network is referenced by a
domain's interface, it will have the same effect as if the
interface had been defined as type='direct', e.g.:
<interface type='direct'>
<source mode='${mode}' dev='${dev}>
...
</interface>
where ${mode} is one of the three new modes, and ${dev} is an interface
selected from the list given in <forward>.
bridge - if a <forward> dev (or multiple devs) is defined, and
forward mode is 'bridge' this is just like the modes 'private',
'passthrough', and 'vepa' above. If there is no forward dev
specified but a bridge name is given (e.g. "<bridge
name='br0'/>"), then guest interfaces using this network will use
libvirt's "host bridge" mode, equivalent to this:
<interface type='bridge'>
<source bridge='${bridge-name}'/>
...
</interface>
3) A network can have multiple <portgroup> elements, which may be
selected by the guest interface definition (by adding
"portgroup='${name}'" in the <source> element along with the
network name). Currently a portgroup can only contain a
virtportprofile, but the intent is that other configuration items
may be put there int the future (e.g. bandwidth config). When
building a guest's interface, if the <interface> XML itself has no
virtportprofile, and if the requested network has a portgroup with
a name matching the name given in the <interface> (or if one of the
network's portgroups is marked with the "default='yes'" attribute),
the virtportprofile from that portgroup will be used by the
interface.
4) A network can have a virtportprofile defined at the top level,
which will be used by a guest interface when connecting in one of
the 'direct' modes if the guest interface XML itself hasn't
specified any virtportprofile, and if there are also no matching
portgroups on the network.
2011-07-20 03:01:09 +00:00
|
|
|
|
2011-12-14 10:50:40 +00:00
|
|
|
if (def->nForwardIfs &&
|
|
|
|
(!def->nForwardPfs || !(flags & VIR_NETWORK_XML_INACTIVE))) {
|
conf: support abstracted interface info in network XML
The network XML is updated in the following ways:
1) The <forward> element can now contain a list of forward interfaces:
<forward .... >
<interface dev='eth10'/>
<interface dev='eth11'/>
<interface dev='eth12'/>
<interface dev='eth13'/>
</forward>
The first of these takes the place of the dev attribute that is
normally in <forward> - when defining a network you can specify
either one, and on output both will be present. If you specify
both on input, they must match.
2) In addition to forward modes of 'nat' and 'route', these new modes
are supported:
private, passthrough, vepa - when this network is referenced by a
domain's interface, it will have the same effect as if the
interface had been defined as type='direct', e.g.:
<interface type='direct'>
<source mode='${mode}' dev='${dev}>
...
</interface>
where ${mode} is one of the three new modes, and ${dev} is an interface
selected from the list given in <forward>.
bridge - if a <forward> dev (or multiple devs) is defined, and
forward mode is 'bridge' this is just like the modes 'private',
'passthrough', and 'vepa' above. If there is no forward dev
specified but a bridge name is given (e.g. "<bridge
name='br0'/>"), then guest interfaces using this network will use
libvirt's "host bridge" mode, equivalent to this:
<interface type='bridge'>
<source bridge='${bridge-name}'/>
...
</interface>
3) A network can have multiple <portgroup> elements, which may be
selected by the guest interface definition (by adding
"portgroup='${name}'" in the <source> element along with the
network name). Currently a portgroup can only contain a
virtportprofile, but the intent is that other configuration items
may be put there int the future (e.g. bandwidth config). When
building a guest's interface, if the <interface> XML itself has no
virtportprofile, and if the requested network has a portgroup with
a name matching the name given in the <interface> (or if one of the
network's portgroups is marked with the "default='yes'" attribute),
the virtportprofile from that portgroup will be used by the
interface.
4) A network can have a virtportprofile defined at the top level,
which will be used by a guest interface when connecting in one of
the 'direct' modes if the guest interface XML itself hasn't
specified any virtportprofile, and if there are also no matching
portgroups on the network.
2011-07-20 03:01:09 +00:00
|
|
|
for (ii = 0; ii < def->nForwardIfs; ii++) {
|
2012-08-16 15:41:41 +00:00
|
|
|
if (def->forwardType != VIR_NETWORK_FORWARD_HOSTDEV) {
|
|
|
|
virBufferEscapeString(&buf, "<interface dev='%s'",
|
|
|
|
def->forwardIfs[ii].device.dev);
|
|
|
|
if (!(flags & VIR_NETWORK_XML_INACTIVE) &&
|
|
|
|
(def->forwardIfs[ii].connections > 0)) {
|
|
|
|
virBufferAsprintf(&buf, " connections='%d'",
|
|
|
|
def->forwardIfs[ii].connections);
|
|
|
|
}
|
|
|
|
virBufferAddLit(&buf, "/>\n");
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (def->forwardIfs[ii].type == VIR_NETWORK_FORWARD_HOSTDEV_DEVICE_PCI) {
|
|
|
|
if (virDevicePCIAddressFormat(&buf,
|
|
|
|
def->forwardIfs[ii].device.pci,
|
|
|
|
true) < 0)
|
|
|
|
goto error;
|
|
|
|
}
|
2012-08-05 06:59:55 +00:00
|
|
|
}
|
2008-07-11 10:48:34 +00:00
|
|
|
}
|
|
|
|
}
|
2012-08-16 15:41:41 +00:00
|
|
|
virBufferAdjustIndent(&buf, -2);
|
2011-12-14 10:50:23 +00:00
|
|
|
if (def->nForwardPfs || def->nForwardIfs)
|
2012-08-16 15:41:41 +00:00
|
|
|
virBufferAddLit(&buf, "</forward>\n");
|
2008-07-11 10:48:34 +00:00
|
|
|
}
|
|
|
|
|
conf: support abstracted interface info in network XML
The network XML is updated in the following ways:
1) The <forward> element can now contain a list of forward interfaces:
<forward .... >
<interface dev='eth10'/>
<interface dev='eth11'/>
<interface dev='eth12'/>
<interface dev='eth13'/>
</forward>
The first of these takes the place of the dev attribute that is
normally in <forward> - when defining a network you can specify
either one, and on output both will be present. If you specify
both on input, they must match.
2) In addition to forward modes of 'nat' and 'route', these new modes
are supported:
private, passthrough, vepa - when this network is referenced by a
domain's interface, it will have the same effect as if the
interface had been defined as type='direct', e.g.:
<interface type='direct'>
<source mode='${mode}' dev='${dev}>
...
</interface>
where ${mode} is one of the three new modes, and ${dev} is an interface
selected from the list given in <forward>.
bridge - if a <forward> dev (or multiple devs) is defined, and
forward mode is 'bridge' this is just like the modes 'private',
'passthrough', and 'vepa' above. If there is no forward dev
specified but a bridge name is given (e.g. "<bridge
name='br0'/>"), then guest interfaces using this network will use
libvirt's "host bridge" mode, equivalent to this:
<interface type='bridge'>
<source bridge='${bridge-name}'/>
...
</interface>
3) A network can have multiple <portgroup> elements, which may be
selected by the guest interface definition (by adding
"portgroup='${name}'" in the <source> element along with the
network name). Currently a portgroup can only contain a
virtportprofile, but the intent is that other configuration items
may be put there int the future (e.g. bandwidth config). When
building a guest's interface, if the <interface> XML itself has no
virtportprofile, and if the requested network has a portgroup with
a name matching the name given in the <interface> (or if one of the
network's portgroups is marked with the "default='yes'" attribute),
the virtportprofile from that portgroup will be used by the
interface.
4) A network can have a virtportprofile defined at the top level,
which will be used by a guest interface when connecting in one of
the 'direct' modes if the guest interface XML itself hasn't
specified any virtportprofile, and if there are also no matching
portgroups on the network.
2011-07-20 03:01:09 +00:00
|
|
|
if (def->forwardType == VIR_NETWORK_FORWARD_NONE ||
|
|
|
|
def->forwardType == VIR_NETWORK_FORWARD_NAT ||
|
|
|
|
def->forwardType == VIR_NETWORK_FORWARD_ROUTE) {
|
|
|
|
|
2012-08-16 15:41:41 +00:00
|
|
|
virBufferAddLit(&buf, "<bridge");
|
conf: support abstracted interface info in network XML
The network XML is updated in the following ways:
1) The <forward> element can now contain a list of forward interfaces:
<forward .... >
<interface dev='eth10'/>
<interface dev='eth11'/>
<interface dev='eth12'/>
<interface dev='eth13'/>
</forward>
The first of these takes the place of the dev attribute that is
normally in <forward> - when defining a network you can specify
either one, and on output both will be present. If you specify
both on input, they must match.
2) In addition to forward modes of 'nat' and 'route', these new modes
are supported:
private, passthrough, vepa - when this network is referenced by a
domain's interface, it will have the same effect as if the
interface had been defined as type='direct', e.g.:
<interface type='direct'>
<source mode='${mode}' dev='${dev}>
...
</interface>
where ${mode} is one of the three new modes, and ${dev} is an interface
selected from the list given in <forward>.
bridge - if a <forward> dev (or multiple devs) is defined, and
forward mode is 'bridge' this is just like the modes 'private',
'passthrough', and 'vepa' above. If there is no forward dev
specified but a bridge name is given (e.g. "<bridge
name='br0'/>"), then guest interfaces using this network will use
libvirt's "host bridge" mode, equivalent to this:
<interface type='bridge'>
<source bridge='${bridge-name}'/>
...
</interface>
3) A network can have multiple <portgroup> elements, which may be
selected by the guest interface definition (by adding
"portgroup='${name}'" in the <source> element along with the
network name). Currently a portgroup can only contain a
virtportprofile, but the intent is that other configuration items
may be put there int the future (e.g. bandwidth config). When
building a guest's interface, if the <interface> XML itself has no
virtportprofile, and if the requested network has a portgroup with
a name matching the name given in the <interface> (or if one of the
network's portgroups is marked with the "default='yes'" attribute),
the virtportprofile from that portgroup will be used by the
interface.
4) A network can have a virtportprofile defined at the top level,
which will be used by a guest interface when connecting in one of
the 'direct' modes if the guest interface XML itself hasn't
specified any virtportprofile, and if there are also no matching
portgroups on the network.
2011-07-20 03:01:09 +00:00
|
|
|
if (def->bridge)
|
|
|
|
virBufferEscapeString(&buf, " name='%s'", def->bridge);
|
|
|
|
virBufferAsprintf(&buf, " stp='%s' delay='%ld' />\n",
|
|
|
|
def->stp ? "on" : "off",
|
|
|
|
def->delay);
|
|
|
|
} else if (def->forwardType == VIR_NETWORK_FORWARD_BRIDGE &&
|
|
|
|
def->bridge) {
|
2012-08-16 15:41:41 +00:00
|
|
|
virBufferEscapeString(&buf, "<bridge name='%s' />\n", def->bridge);
|
conf: support abstracted interface info in network XML
The network XML is updated in the following ways:
1) The <forward> element can now contain a list of forward interfaces:
<forward .... >
<interface dev='eth10'/>
<interface dev='eth11'/>
<interface dev='eth12'/>
<interface dev='eth13'/>
</forward>
The first of these takes the place of the dev attribute that is
normally in <forward> - when defining a network you can specify
either one, and on output both will be present. If you specify
both on input, they must match.
2) In addition to forward modes of 'nat' and 'route', these new modes
are supported:
private, passthrough, vepa - when this network is referenced by a
domain's interface, it will have the same effect as if the
interface had been defined as type='direct', e.g.:
<interface type='direct'>
<source mode='${mode}' dev='${dev}>
...
</interface>
where ${mode} is one of the three new modes, and ${dev} is an interface
selected from the list given in <forward>.
bridge - if a <forward> dev (or multiple devs) is defined, and
forward mode is 'bridge' this is just like the modes 'private',
'passthrough', and 'vepa' above. If there is no forward dev
specified but a bridge name is given (e.g. "<bridge
name='br0'/>"), then guest interfaces using this network will use
libvirt's "host bridge" mode, equivalent to this:
<interface type='bridge'>
<source bridge='${bridge-name}'/>
...
</interface>
3) A network can have multiple <portgroup> elements, which may be
selected by the guest interface definition (by adding
"portgroup='${name}'" in the <source> element along with the
network name). Currently a portgroup can only contain a
virtportprofile, but the intent is that other configuration items
may be put there int the future (e.g. bandwidth config). When
building a guest's interface, if the <interface> XML itself has no
virtportprofile, and if the requested network has a portgroup with
a name matching the name given in the <interface> (or if one of the
network's portgroups is marked with the "default='yes'" attribute),
the virtportprofile from that portgroup will be used by the
interface.
4) A network can have a virtportprofile defined at the top level,
which will be used by a guest interface when connecting in one of
the 'direct' modes if the guest interface XML itself hasn't
specified any virtportprofile, and if there are also no matching
portgroups on the network.
2011-07-20 03:01:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
Give each virtual network bridge its own fixed MAC address
This fixes https://bugzilla.redhat.com/show_bug.cgi?id=609463
The problem was that, since a bridge always acquires the MAC address
of the connected interface with the numerically lowest MAC, as guests
are started and stopped, it was possible for the MAC address to change
over time, and this change in the network was being detected by
Windows 7 (it sees the MAC of the default route change), so on each
reboot it would bring up a dialog box asking about this "new network".
The solution is to create a dummy tap interface with a MAC guaranteed
to be lower than any guest interface's MAC, and attach that tap to the
bridge as soon as it's created. Since all guest MAC addresses start
with 0xFE, we can just generate a MAC with the standard "0x52, 0x54,
0" prefix, and it's guaranteed to always win (physical interfaces are
never connected to these bridges, so we don't need to worry about
competing numerically with them).
Note that the dummy tap is never set to IFF_UP state - that's not
necessary in order for the bridge to take its MAC, and not setting it
to UP eliminates the clutter of having an (eg) "virbr0-nic" displayed
in the output of the ifconfig command.
I chose to not auto-generate the MAC address in the network XML
parser, as there are likely to be consumers of that API that don't
need or want to have a MAC address associated with the
bridge.
Instead, in bridge_driver.c when the network is being defined, if
there is no MAC, one is generated. To account for virtual network
configs that already exist when upgrading from an older version of
libvirt, I've added a %post script to the specfile that searches for
all network definitions in both the config directory
(/etc/libvirt/qemu/networks) and the state directory
(/var/lib/libvirt/network) that are missing a mac address, generates a
random address, and adds it to the config (and a matching address to
the state file, if there is one).
docs/formatnetwork.html.in: document <mac address.../>
docs/schemas/network.rng: add nac address to schema
libvirt.spec.in: %post script to update existing networks
src/conf/network_conf.[ch]: parse and format <mac address.../>
src/libvirt_private.syms: export a couple private symbols we need
src/network/bridge_driver.c:
auto-generate mac address when needed,
create dummy interface if mac address is present.
tests/networkxml2xmlin/isolated-network.xml
tests/networkxml2xmlin/routed-network.xml
tests/networkxml2xmlout/isolated-network.xml
tests/networkxml2xmlout/routed-network.xml: add mac address to some tests
2011-02-09 08:28:12 +00:00
|
|
|
if (def->mac_specified) {
|
|
|
|
char macaddr[VIR_MAC_STRING_BUFLEN];
|
2012-07-17 12:07:59 +00:00
|
|
|
virMacAddrFormat(&def->mac, macaddr);
|
2012-08-16 15:41:41 +00:00
|
|
|
virBufferAsprintf(&buf, "<mac address='%s'/>\n", macaddr);
|
Give each virtual network bridge its own fixed MAC address
This fixes https://bugzilla.redhat.com/show_bug.cgi?id=609463
The problem was that, since a bridge always acquires the MAC address
of the connected interface with the numerically lowest MAC, as guests
are started and stopped, it was possible for the MAC address to change
over time, and this change in the network was being detected by
Windows 7 (it sees the MAC of the default route change), so on each
reboot it would bring up a dialog box asking about this "new network".
The solution is to create a dummy tap interface with a MAC guaranteed
to be lower than any guest interface's MAC, and attach that tap to the
bridge as soon as it's created. Since all guest MAC addresses start
with 0xFE, we can just generate a MAC with the standard "0x52, 0x54,
0" prefix, and it's guaranteed to always win (physical interfaces are
never connected to these bridges, so we don't need to worry about
competing numerically with them).
Note that the dummy tap is never set to IFF_UP state - that's not
necessary in order for the bridge to take its MAC, and not setting it
to UP eliminates the clutter of having an (eg) "virbr0-nic" displayed
in the output of the ifconfig command.
I chose to not auto-generate the MAC address in the network XML
parser, as there are likely to be consumers of that API that don't
need or want to have a MAC address associated with the
bridge.
Instead, in bridge_driver.c when the network is being defined, if
there is no MAC, one is generated. To account for virtual network
configs that already exist when upgrading from an older version of
libvirt, I've added a %post script to the specfile that searches for
all network definitions in both the config directory
(/etc/libvirt/qemu/networks) and the state directory
(/var/lib/libvirt/network) that are missing a mac address, generates a
random address, and adds it to the config (and a matching address to
the state file, if there is one).
docs/formatnetwork.html.in: document <mac address.../>
docs/schemas/network.rng: add nac address to schema
libvirt.spec.in: %post script to update existing networks
src/conf/network_conf.[ch]: parse and format <mac address.../>
src/libvirt_private.syms: export a couple private symbols we need
src/network/bridge_driver.c:
auto-generate mac address when needed,
create dummy interface if mac address is present.
tests/networkxml2xmlin/isolated-network.xml
tests/networkxml2xmlin/routed-network.xml
tests/networkxml2xmlout/isolated-network.xml
tests/networkxml2xmlout/routed-network.xml: add mac address to some tests
2011-02-09 08:28:12 +00:00
|
|
|
}
|
2008-07-11 10:48:34 +00:00
|
|
|
|
2009-07-02 14:02:18 +00:00
|
|
|
if (def->domain)
|
2012-08-16 15:41:41 +00:00
|
|
|
virBufferAsprintf(&buf, "<domain name='%s'/>\n", def->domain);
|
2009-07-02 14:02:18 +00:00
|
|
|
|
2011-06-24 10:04:36 +00:00
|
|
|
if (virNetworkDNSDefFormat(&buf, def->dns) < 0)
|
|
|
|
goto error;
|
|
|
|
|
2012-08-12 07:51:30 +00:00
|
|
|
if (virNetDevVlanFormat(&def->vlan, &buf) < 0)
|
|
|
|
goto error;
|
Adjust naming of network device bandwidth management APIs
Rename virBandwidth to virNetDevBandwidth, and virRate to
virNetDevBandwidthRate.
* src/util/network.c, src/util/network.h: Rename bandwidth
structs and APIs
* src/conf/domain_conf.c, src/conf/domain_conf.h,
src/conf/network_conf.c, src/conf/network_conf.h,
src/lxc/lxc_driver.c, src/network/bridge_driver.c,
src/qemu/qemu_command.c, src/util/macvtap.c,
src/util/macvtap.h, tools/virsh.c: Update for API changes.
2011-11-02 14:29:05 +00:00
|
|
|
if (virNetDevBandwidthFormat(def->bandwidth, &buf) < 0)
|
2011-07-22 14:07:26 +00:00
|
|
|
goto error;
|
|
|
|
|
2010-11-17 18:36:19 +00:00
|
|
|
for (ii = 0; ii < def->nips; ii++) {
|
|
|
|
if (virNetworkIpDefFormat(&buf, &def->ips[ii]) < 0)
|
|
|
|
goto error;
|
2008-07-11 10:48:34 +00:00
|
|
|
}
|
|
|
|
|
2011-11-02 14:53:35 +00:00
|
|
|
if (virNetDevVPortProfileFormat(def->virtPortProfile, &buf) < 0)
|
|
|
|
goto error;
|
conf: support abstracted interface info in network XML
The network XML is updated in the following ways:
1) The <forward> element can now contain a list of forward interfaces:
<forward .... >
<interface dev='eth10'/>
<interface dev='eth11'/>
<interface dev='eth12'/>
<interface dev='eth13'/>
</forward>
The first of these takes the place of the dev attribute that is
normally in <forward> - when defining a network you can specify
either one, and on output both will be present. If you specify
both on input, they must match.
2) In addition to forward modes of 'nat' and 'route', these new modes
are supported:
private, passthrough, vepa - when this network is referenced by a
domain's interface, it will have the same effect as if the
interface had been defined as type='direct', e.g.:
<interface type='direct'>
<source mode='${mode}' dev='${dev}>
...
</interface>
where ${mode} is one of the three new modes, and ${dev} is an interface
selected from the list given in <forward>.
bridge - if a <forward> dev (or multiple devs) is defined, and
forward mode is 'bridge' this is just like the modes 'private',
'passthrough', and 'vepa' above. If there is no forward dev
specified but a bridge name is given (e.g. "<bridge
name='br0'/>"), then guest interfaces using this network will use
libvirt's "host bridge" mode, equivalent to this:
<interface type='bridge'>
<source bridge='${bridge-name}'/>
...
</interface>
3) A network can have multiple <portgroup> elements, which may be
selected by the guest interface definition (by adding
"portgroup='${name}'" in the <source> element along with the
network name). Currently a portgroup can only contain a
virtportprofile, but the intent is that other configuration items
may be put there int the future (e.g. bandwidth config). When
building a guest's interface, if the <interface> XML itself has no
virtportprofile, and if the requested network has a portgroup with
a name matching the name given in the <interface> (or if one of the
network's portgroups is marked with the "default='yes'" attribute),
the virtportprofile from that portgroup will be used by the
interface.
4) A network can have a virtportprofile defined at the top level,
which will be used by a guest interface when connecting in one of
the 'direct' modes if the guest interface XML itself hasn't
specified any virtportprofile, and if there are also no matching
portgroups on the network.
2011-07-20 03:01:09 +00:00
|
|
|
|
|
|
|
for (ii = 0; ii < def->nPortGroups; ii++)
|
2011-11-02 14:53:35 +00:00
|
|
|
if (virPortGroupDefFormat(&buf, &def->portGroups[ii]) < 0)
|
|
|
|
goto error;
|
conf: support abstracted interface info in network XML
The network XML is updated in the following ways:
1) The <forward> element can now contain a list of forward interfaces:
<forward .... >
<interface dev='eth10'/>
<interface dev='eth11'/>
<interface dev='eth12'/>
<interface dev='eth13'/>
</forward>
The first of these takes the place of the dev attribute that is
normally in <forward> - when defining a network you can specify
either one, and on output both will be present. If you specify
both on input, they must match.
2) In addition to forward modes of 'nat' and 'route', these new modes
are supported:
private, passthrough, vepa - when this network is referenced by a
domain's interface, it will have the same effect as if the
interface had been defined as type='direct', e.g.:
<interface type='direct'>
<source mode='${mode}' dev='${dev}>
...
</interface>
where ${mode} is one of the three new modes, and ${dev} is an interface
selected from the list given in <forward>.
bridge - if a <forward> dev (or multiple devs) is defined, and
forward mode is 'bridge' this is just like the modes 'private',
'passthrough', and 'vepa' above. If there is no forward dev
specified but a bridge name is given (e.g. "<bridge
name='br0'/>"), then guest interfaces using this network will use
libvirt's "host bridge" mode, equivalent to this:
<interface type='bridge'>
<source bridge='${bridge-name}'/>
...
</interface>
3) A network can have multiple <portgroup> elements, which may be
selected by the guest interface definition (by adding
"portgroup='${name}'" in the <source> element along with the
network name). Currently a portgroup can only contain a
virtportprofile, but the intent is that other configuration items
may be put there int the future (e.g. bandwidth config). When
building a guest's interface, if the <interface> XML itself has no
virtportprofile, and if the requested network has a portgroup with
a name matching the name given in the <interface> (or if one of the
network's portgroups is marked with the "default='yes'" attribute),
the virtportprofile from that portgroup will be used by the
interface.
4) A network can have a virtportprofile defined at the top level,
which will be used by a guest interface when connecting in one of
the 'direct' modes if the guest interface XML itself hasn't
specified any virtportprofile, and if there are also no matching
portgroups on the network.
2011-07-20 03:01:09 +00:00
|
|
|
|
2012-08-16 15:41:41 +00:00
|
|
|
virBufferAdjustIndent(&buf, -2);
|
2008-07-11 10:48:34 +00:00
|
|
|
virBufferAddLit(&buf, "</network>\n");
|
|
|
|
|
|
|
|
if (virBufferError(&buf))
|
|
|
|
goto no_memory;
|
|
|
|
|
|
|
|
return virBufferContentAndReset(&buf);
|
|
|
|
|
|
|
|
no_memory:
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
Convert virNetwork to use virSocketAddr everywhere
Instead of storing the IP address string in virNetwork related
structs, store the parsed virSocketAddr. This will make it
easier to add IPv6 support in the future, by letting driver
code directly check what address family is present
* src/conf/network_conf.c, src/conf/network_conf.h,
src/network/bridge_driver.c: Convert to use virSocketAddr
in virNetwork, instead of char *.
* src/util/bridge.c, src/util/bridge.h,
src/util/dnsmasq.c, src/util/dnsmasq.h,
src/util/iptables.c, src/util/iptables.h: Convert to
take a virSocketAddr instead of char * for any IP
address parameters
* src/util/network.h: Add macros to determine if an address
is set, and what address family is set.
2010-10-21 12:14:33 +00:00
|
|
|
error:
|
2009-12-09 23:00:50 +00:00
|
|
|
virBufferFreeAndReset(&buf);
|
2008-07-11 10:48:34 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
conf: support abstracted interface info in network XML
The network XML is updated in the following ways:
1) The <forward> element can now contain a list of forward interfaces:
<forward .... >
<interface dev='eth10'/>
<interface dev='eth11'/>
<interface dev='eth12'/>
<interface dev='eth13'/>
</forward>
The first of these takes the place of the dev attribute that is
normally in <forward> - when defining a network you can specify
either one, and on output both will be present. If you specify
both on input, they must match.
2) In addition to forward modes of 'nat' and 'route', these new modes
are supported:
private, passthrough, vepa - when this network is referenced by a
domain's interface, it will have the same effect as if the
interface had been defined as type='direct', e.g.:
<interface type='direct'>
<source mode='${mode}' dev='${dev}>
...
</interface>
where ${mode} is one of the three new modes, and ${dev} is an interface
selected from the list given in <forward>.
bridge - if a <forward> dev (or multiple devs) is defined, and
forward mode is 'bridge' this is just like the modes 'private',
'passthrough', and 'vepa' above. If there is no forward dev
specified but a bridge name is given (e.g. "<bridge
name='br0'/>"), then guest interfaces using this network will use
libvirt's "host bridge" mode, equivalent to this:
<interface type='bridge'>
<source bridge='${bridge-name}'/>
...
</interface>
3) A network can have multiple <portgroup> elements, which may be
selected by the guest interface definition (by adding
"portgroup='${name}'" in the <source> element along with the
network name). Currently a portgroup can only contain a
virtportprofile, but the intent is that other configuration items
may be put there int the future (e.g. bandwidth config). When
building a guest's interface, if the <interface> XML itself has no
virtportprofile, and if the requested network has a portgroup with
a name matching the name given in the <interface> (or if one of the
network's portgroups is marked with the "default='yes'" attribute),
the virtportprofile from that portgroup will be used by the
interface.
4) A network can have a virtportprofile defined at the top level,
which will be used by a guest interface when connecting in one of
the 'direct' modes if the guest interface XML itself hasn't
specified any virtportprofile, and if there are also no matching
portgroups on the network.
2011-07-20 03:01:09 +00:00
|
|
|
virPortGroupDefPtr virPortGroupFindByName(virNetworkDefPtr net,
|
|
|
|
const char *portgroup)
|
|
|
|
{
|
|
|
|
int ii;
|
|
|
|
for (ii = 0; ii < net->nPortGroups; ii++) {
|
|
|
|
if (portgroup) {
|
|
|
|
if (STREQ(portgroup, net->portGroups[ii].name))
|
|
|
|
return &net->portGroups[ii];
|
|
|
|
} else {
|
|
|
|
if (net->portGroups[ii].isDefault)
|
|
|
|
return &net->portGroups[ii];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2010-02-10 10:22:52 +00:00
|
|
|
int virNetworkSaveXML(const char *configDir,
|
2009-01-20 22:36:10 +00:00
|
|
|
virNetworkDefPtr def,
|
|
|
|
const char *xml)
|
2008-07-11 10:48:34 +00:00
|
|
|
{
|
2009-01-20 22:36:10 +00:00
|
|
|
char *configFile = NULL;
|
2011-10-27 16:55:47 +00:00
|
|
|
int ret = -1;
|
2008-07-11 10:48:34 +00:00
|
|
|
|
2010-02-10 10:22:52 +00:00
|
|
|
if ((configFile = virNetworkConfigFile(configDir, def->name)) == NULL)
|
2008-07-11 10:48:34 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2011-07-05 21:02:53 +00:00
|
|
|
if (virFileMakePath(configDir) < 0) {
|
|
|
|
virReportSystemError(errno,
|
2009-01-20 17:13:33 +00:00
|
|
|
_("cannot create config directory '%s'"),
|
|
|
|
configDir);
|
2008-07-11 10:48:34 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2011-10-27 16:55:47 +00:00
|
|
|
ret = virXMLSaveFile(configFile, def->name, "net-edit", xml);
|
2008-07-11 10:48:34 +00:00
|
|
|
|
|
|
|
cleanup:
|
2009-01-20 22:36:10 +00:00
|
|
|
VIR_FREE(configFile);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2010-02-10 10:22:52 +00:00
|
|
|
int virNetworkSaveConfig(const char *configDir,
|
2009-01-20 22:36:10 +00:00
|
|
|
virNetworkDefPtr def)
|
|
|
|
{
|
|
|
|
int ret = -1;
|
|
|
|
char *xml;
|
|
|
|
|
2012-09-14 15:35:35 +00:00
|
|
|
if (!(xml = virNetworkDefFormat(def, VIR_NETWORK_XML_INACTIVE)))
|
2009-01-20 22:36:10 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2010-02-10 10:22:52 +00:00
|
|
|
if (virNetworkSaveXML(configDir, def, xml))
|
2009-01-20 22:36:10 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
cleanup:
|
|
|
|
VIR_FREE(xml);
|
2008-07-11 10:48:34 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2009-01-20 22:36:10 +00:00
|
|
|
|
2012-09-14 15:35:35 +00:00
|
|
|
int virNetworkSaveStatus(const char *statusDir,
|
|
|
|
virNetworkObjPtr network)
|
|
|
|
{
|
|
|
|
int ret = -1;
|
|
|
|
char *xml;
|
|
|
|
|
|
|
|
if (!(xml = virNetworkDefFormat(network->def, 0)))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (virNetworkSaveXML(statusDir, network->def, xml))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
cleanup:
|
|
|
|
VIR_FREE(xml);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2010-02-10 10:22:52 +00:00
|
|
|
virNetworkObjPtr virNetworkLoadConfig(virNetworkObjListPtr nets,
|
2008-07-11 10:48:34 +00:00
|
|
|
const char *configDir,
|
|
|
|
const char *autostartDir,
|
2009-01-20 22:36:10 +00:00
|
|
|
const char *name)
|
2008-07-11 10:48:34 +00:00
|
|
|
{
|
|
|
|
char *configFile = NULL, *autostartLink = NULL;
|
|
|
|
virNetworkDefPtr def = NULL;
|
|
|
|
virNetworkObjPtr net;
|
|
|
|
int autostart;
|
|
|
|
|
2010-02-10 10:22:52 +00:00
|
|
|
if ((configFile = virNetworkConfigFile(configDir, name)) == NULL)
|
2008-07-11 10:48:34 +00:00
|
|
|
goto error;
|
2010-02-10 10:22:52 +00:00
|
|
|
if ((autostartLink = virNetworkConfigFile(autostartDir, name)) == NULL)
|
2008-07-11 10:48:34 +00:00
|
|
|
goto error;
|
|
|
|
|
|
|
|
if ((autostart = virFileLinkPointsTo(autostartLink, configFile)) < 0)
|
|
|
|
goto error;
|
|
|
|
|
2010-02-10 10:22:52 +00:00
|
|
|
if (!(def = virNetworkDefParseFile(configFile)))
|
2008-07-11 10:48:34 +00:00
|
|
|
goto error;
|
|
|
|
|
2009-01-20 22:36:10 +00:00
|
|
|
if (!STREQ(name, def->name)) {
|
2012-07-18 10:50:44 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Network config filename '%s'"
|
|
|
|
" does not match network name '%s'"),
|
|
|
|
configFile, def->name);
|
2008-07-11 10:48:34 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
conf: support abstracted interface info in network XML
The network XML is updated in the following ways:
1) The <forward> element can now contain a list of forward interfaces:
<forward .... >
<interface dev='eth10'/>
<interface dev='eth11'/>
<interface dev='eth12'/>
<interface dev='eth13'/>
</forward>
The first of these takes the place of the dev attribute that is
normally in <forward> - when defining a network you can specify
either one, and on output both will be present. If you specify
both on input, they must match.
2) In addition to forward modes of 'nat' and 'route', these new modes
are supported:
private, passthrough, vepa - when this network is referenced by a
domain's interface, it will have the same effect as if the
interface had been defined as type='direct', e.g.:
<interface type='direct'>
<source mode='${mode}' dev='${dev}>
...
</interface>
where ${mode} is one of the three new modes, and ${dev} is an interface
selected from the list given in <forward>.
bridge - if a <forward> dev (or multiple devs) is defined, and
forward mode is 'bridge' this is just like the modes 'private',
'passthrough', and 'vepa' above. If there is no forward dev
specified but a bridge name is given (e.g. "<bridge
name='br0'/>"), then guest interfaces using this network will use
libvirt's "host bridge" mode, equivalent to this:
<interface type='bridge'>
<source bridge='${bridge-name}'/>
...
</interface>
3) A network can have multiple <portgroup> elements, which may be
selected by the guest interface definition (by adding
"portgroup='${name}'" in the <source> element along with the
network name). Currently a portgroup can only contain a
virtportprofile, but the intent is that other configuration items
may be put there int the future (e.g. bandwidth config). When
building a guest's interface, if the <interface> XML itself has no
virtportprofile, and if the requested network has a portgroup with
a name matching the name given in the <interface> (or if one of the
network's portgroups is marked with the "default='yes'" attribute),
the virtportprofile from that portgroup will be used by the
interface.
4) A network can have a virtportprofile defined at the top level,
which will be used by a guest interface when connecting in one of
the 'direct' modes if the guest interface XML itself hasn't
specified any virtportprofile, and if there are also no matching
portgroups on the network.
2011-07-20 03:01:09 +00:00
|
|
|
if (def->forwardType == VIR_NETWORK_FORWARD_NONE ||
|
|
|
|
def->forwardType == VIR_NETWORK_FORWARD_NAT ||
|
|
|
|
def->forwardType == VIR_NETWORK_FORWARD_ROUTE) {
|
|
|
|
|
|
|
|
/* Generate a bridge if none is specified, but don't check for collisions
|
|
|
|
* if a bridge is hardcoded, so the network is at least defined.
|
|
|
|
*/
|
|
|
|
if (virNetworkSetBridgeName(nets, def, 0))
|
|
|
|
goto error;
|
|
|
|
}
|
2009-03-02 17:37:03 +00:00
|
|
|
|
2012-09-14 15:35:35 +00:00
|
|
|
if (!(net = virNetworkAssignDef(nets, def, false)))
|
2008-07-11 10:48:34 +00:00
|
|
|
goto error;
|
|
|
|
|
|
|
|
net->autostart = autostart;
|
2009-03-02 17:29:44 +00:00
|
|
|
net->persistent = 1;
|
2008-07-11 10:48:34 +00:00
|
|
|
|
2009-01-20 22:36:10 +00:00
|
|
|
VIR_FREE(configFile);
|
|
|
|
VIR_FREE(autostartLink);
|
|
|
|
|
2008-07-11 10:48:34 +00:00
|
|
|
return net;
|
|
|
|
|
|
|
|
error:
|
|
|
|
VIR_FREE(configFile);
|
|
|
|
VIR_FREE(autostartLink);
|
|
|
|
virNetworkDefFree(def);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2010-02-10 10:22:52 +00:00
|
|
|
int virNetworkLoadAllConfigs(virNetworkObjListPtr nets,
|
2008-07-11 10:48:34 +00:00
|
|
|
const char *configDir,
|
|
|
|
const char *autostartDir)
|
|
|
|
{
|
|
|
|
DIR *dir;
|
|
|
|
struct dirent *entry;
|
|
|
|
|
|
|
|
if (!(dir = opendir(configDir))) {
|
|
|
|
if (errno == ENOENT)
|
|
|
|
return 0;
|
2010-02-04 20:02:58 +00:00
|
|
|
virReportSystemError(errno,
|
2009-01-20 17:13:33 +00:00
|
|
|
_("Failed to open dir '%s'"),
|
|
|
|
configDir);
|
2008-07-11 10:48:34 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
while ((entry = readdir(dir))) {
|
2008-12-04 22:00:14 +00:00
|
|
|
virNetworkObjPtr net;
|
|
|
|
|
2008-07-11 10:48:34 +00:00
|
|
|
if (entry->d_name[0] == '.')
|
|
|
|
continue;
|
|
|
|
|
2009-01-20 22:36:10 +00:00
|
|
|
if (!virFileStripSuffix(entry->d_name, ".xml"))
|
2008-07-11 10:48:34 +00:00
|
|
|
continue;
|
|
|
|
|
|
|
|
/* NB: ignoring errors, so one malformed config doesn't
|
|
|
|
kill the whole process */
|
2010-02-10 10:22:52 +00:00
|
|
|
net = virNetworkLoadConfig(nets,
|
2008-12-04 22:00:14 +00:00
|
|
|
configDir,
|
|
|
|
autostartDir,
|
|
|
|
entry->d_name);
|
|
|
|
if (net)
|
|
|
|
virNetworkObjUnlock(net);
|
2008-07-11 10:48:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
closedir(dir);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2010-02-10 10:22:52 +00:00
|
|
|
int virNetworkDeleteConfig(const char *configDir,
|
2009-01-20 22:36:10 +00:00
|
|
|
const char *autostartDir,
|
2008-07-11 10:48:34 +00:00
|
|
|
virNetworkObjPtr net)
|
|
|
|
{
|
2009-01-20 22:36:10 +00:00
|
|
|
char *configFile = NULL;
|
|
|
|
char *autostartLink = NULL;
|
2009-09-04 13:56:32 +00:00
|
|
|
int ret = -1;
|
2009-01-20 22:36:10 +00:00
|
|
|
|
2010-02-10 10:22:52 +00:00
|
|
|
if ((configFile = virNetworkConfigFile(configDir, net->def->name)) == NULL)
|
2009-01-20 22:36:10 +00:00
|
|
|
goto error;
|
2010-02-10 10:22:52 +00:00
|
|
|
if ((autostartLink = virNetworkConfigFile(autostartDir, net->def->name)) == NULL)
|
2009-01-20 22:36:10 +00:00
|
|
|
goto error;
|
2008-07-11 10:48:34 +00:00
|
|
|
|
|
|
|
/* Not fatal if this doesn't work */
|
2009-01-20 22:36:10 +00:00
|
|
|
unlink(autostartLink);
|
2008-07-11 10:48:34 +00:00
|
|
|
|
2009-01-20 22:36:10 +00:00
|
|
|
if (unlink(configFile) < 0) {
|
2010-02-04 20:02:58 +00:00
|
|
|
virReportSystemError(errno,
|
2009-01-20 17:13:33 +00:00
|
|
|
_("cannot remove config file '%s'"),
|
2009-01-20 22:36:10 +00:00
|
|
|
configFile);
|
|
|
|
goto error;
|
2008-07-11 10:48:34 +00:00
|
|
|
}
|
|
|
|
|
2009-09-04 13:56:32 +00:00
|
|
|
ret = 0;
|
2009-01-20 22:36:10 +00:00
|
|
|
|
|
|
|
error:
|
|
|
|
VIR_FREE(configFile);
|
|
|
|
VIR_FREE(autostartLink);
|
2009-09-04 13:56:32 +00:00
|
|
|
return ret;
|
2009-01-20 22:36:10 +00:00
|
|
|
}
|
|
|
|
|
2010-02-10 10:22:52 +00:00
|
|
|
char *virNetworkConfigFile(const char *dir,
|
2009-01-20 22:36:10 +00:00
|
|
|
const char *name)
|
|
|
|
{
|
|
|
|
char *ret = NULL;
|
|
|
|
|
|
|
|
if (virAsprintf(&ret, "%s/%s.xml", dir, name) < 0) {
|
2010-02-04 18:19:08 +00:00
|
|
|
virReportOOMError();
|
2009-01-20 22:36:10 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
2008-07-11 10:48:34 +00:00
|
|
|
}
|
2008-12-04 20:53:20 +00:00
|
|
|
|
2009-03-02 17:37:03 +00:00
|
|
|
int virNetworkBridgeInUse(const virNetworkObjListPtr nets,
|
|
|
|
const char *bridge,
|
|
|
|
const char *skipname)
|
|
|
|
{
|
|
|
|
unsigned int i;
|
|
|
|
unsigned int ret = 0;
|
|
|
|
|
|
|
|
for (i = 0 ; i < nets->count ; i++) {
|
|
|
|
virNetworkObjLock(nets->objs[i]);
|
|
|
|
if (nets->objs[i]->def->bridge &&
|
|
|
|
STREQ(nets->objs[i]->def->bridge, bridge) &&
|
|
|
|
!(skipname && STREQ(nets->objs[i]->def->name, skipname)))
|
|
|
|
ret = 1;
|
|
|
|
virNetworkObjUnlock(nets->objs[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2010-02-10 10:22:52 +00:00
|
|
|
char *virNetworkAllocateBridge(const virNetworkObjListPtr nets,
|
2009-04-21 19:00:06 +00:00
|
|
|
const char *template)
|
2009-03-02 17:37:03 +00:00
|
|
|
{
|
|
|
|
|
|
|
|
int id = 0;
|
|
|
|
char *newname;
|
|
|
|
|
2009-04-21 19:00:06 +00:00
|
|
|
if (!template)
|
|
|
|
template = "virbr%d";
|
|
|
|
|
2009-03-02 17:37:03 +00:00
|
|
|
do {
|
2010-08-31 20:25:49 +00:00
|
|
|
if (virAsprintf(&newname, template, id) < 0) {
|
|
|
|
virReportOOMError();
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
if (!virNetworkBridgeInUse(nets, newname, NULL)) {
|
2009-03-02 17:37:03 +00:00
|
|
|
return newname;
|
|
|
|
}
|
2010-08-31 20:25:49 +00:00
|
|
|
VIR_FREE(newname);
|
2009-03-02 17:37:03 +00:00
|
|
|
|
|
|
|
id++;
|
2009-03-02 17:56:50 +00:00
|
|
|
} while (id <= MAX_BRIDGE_ID);
|
2009-03-02 17:37:03 +00:00
|
|
|
|
2012-07-18 10:50:44 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Bridge generation exceeded max id %d"),
|
|
|
|
MAX_BRIDGE_ID);
|
2009-03-02 17:37:03 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2010-02-10 10:22:52 +00:00
|
|
|
int virNetworkSetBridgeName(const virNetworkObjListPtr nets,
|
2009-05-29 14:18:57 +00:00
|
|
|
virNetworkDefPtr def,
|
|
|
|
int check_collision) {
|
2009-03-02 17:37:03 +00:00
|
|
|
|
|
|
|
int ret = -1;
|
|
|
|
|
2009-04-21 19:00:06 +00:00
|
|
|
if (def->bridge && !strstr(def->bridge, "%d")) {
|
2009-05-29 14:18:57 +00:00
|
|
|
/* We may want to skip collision detection in this case (ex. when
|
|
|
|
* loading configs at daemon startup, so the network is at least
|
|
|
|
* defined. */
|
|
|
|
if (check_collision &&
|
|
|
|
virNetworkBridgeInUse(nets, def->bridge, def->name)) {
|
2012-07-18 10:50:44 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("bridge name '%s' already in use."),
|
|
|
|
def->bridge);
|
2009-03-02 17:37:03 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/* Allocate a bridge name */
|
2010-02-10 10:22:52 +00:00
|
|
|
if (!(def->bridge = virNetworkAllocateBridge(nets, def->bridge)))
|
2009-03-02 17:37:03 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
error:
|
|
|
|
return ret;
|
|
|
|
}
|
2009-01-20 22:36:10 +00:00
|
|
|
|
2010-05-27 15:44:31 +00:00
|
|
|
|
Give each virtual network bridge its own fixed MAC address
This fixes https://bugzilla.redhat.com/show_bug.cgi?id=609463
The problem was that, since a bridge always acquires the MAC address
of the connected interface with the numerically lowest MAC, as guests
are started and stopped, it was possible for the MAC address to change
over time, and this change in the network was being detected by
Windows 7 (it sees the MAC of the default route change), so on each
reboot it would bring up a dialog box asking about this "new network".
The solution is to create a dummy tap interface with a MAC guaranteed
to be lower than any guest interface's MAC, and attach that tap to the
bridge as soon as it's created. Since all guest MAC addresses start
with 0xFE, we can just generate a MAC with the standard "0x52, 0x54,
0" prefix, and it's guaranteed to always win (physical interfaces are
never connected to these bridges, so we don't need to worry about
competing numerically with them).
Note that the dummy tap is never set to IFF_UP state - that's not
necessary in order for the bridge to take its MAC, and not setting it
to UP eliminates the clutter of having an (eg) "virbr0-nic" displayed
in the output of the ifconfig command.
I chose to not auto-generate the MAC address in the network XML
parser, as there are likely to be consumers of that API that don't
need or want to have a MAC address associated with the
bridge.
Instead, in bridge_driver.c when the network is being defined, if
there is no MAC, one is generated. To account for virtual network
configs that already exist when upgrading from an older version of
libvirt, I've added a %post script to the specfile that searches for
all network definitions in both the config directory
(/etc/libvirt/qemu/networks) and the state directory
(/var/lib/libvirt/network) that are missing a mac address, generates a
random address, and adds it to the config (and a matching address to
the state file, if there is one).
docs/formatnetwork.html.in: document <mac address.../>
docs/schemas/network.rng: add nac address to schema
libvirt.spec.in: %post script to update existing networks
src/conf/network_conf.[ch]: parse and format <mac address.../>
src/libvirt_private.syms: export a couple private symbols we need
src/network/bridge_driver.c:
auto-generate mac address when needed,
create dummy interface if mac address is present.
tests/networkxml2xmlin/isolated-network.xml
tests/networkxml2xmlin/routed-network.xml
tests/networkxml2xmlout/isolated-network.xml
tests/networkxml2xmlout/routed-network.xml: add mac address to some tests
2011-02-09 08:28:12 +00:00
|
|
|
void virNetworkSetBridgeMacAddr(virNetworkDefPtr def)
|
|
|
|
{
|
|
|
|
if (!def->mac_specified) {
|
|
|
|
/* if the bridge doesn't have a mac address explicitly defined,
|
|
|
|
* autogenerate a random one.
|
|
|
|
*/
|
2012-01-27 16:48:38 +00:00
|
|
|
virMacAddrGenerate((unsigned char[]){ 0x52, 0x54, 0 },
|
2012-07-17 12:07:59 +00:00
|
|
|
&def->mac);
|
Give each virtual network bridge its own fixed MAC address
This fixes https://bugzilla.redhat.com/show_bug.cgi?id=609463
The problem was that, since a bridge always acquires the MAC address
of the connected interface with the numerically lowest MAC, as guests
are started and stopped, it was possible for the MAC address to change
over time, and this change in the network was being detected by
Windows 7 (it sees the MAC of the default route change), so on each
reboot it would bring up a dialog box asking about this "new network".
The solution is to create a dummy tap interface with a MAC guaranteed
to be lower than any guest interface's MAC, and attach that tap to the
bridge as soon as it's created. Since all guest MAC addresses start
with 0xFE, we can just generate a MAC with the standard "0x52, 0x54,
0" prefix, and it's guaranteed to always win (physical interfaces are
never connected to these bridges, so we don't need to worry about
competing numerically with them).
Note that the dummy tap is never set to IFF_UP state - that's not
necessary in order for the bridge to take its MAC, and not setting it
to UP eliminates the clutter of having an (eg) "virbr0-nic" displayed
in the output of the ifconfig command.
I chose to not auto-generate the MAC address in the network XML
parser, as there are likely to be consumers of that API that don't
need or want to have a MAC address associated with the
bridge.
Instead, in bridge_driver.c when the network is being defined, if
there is no MAC, one is generated. To account for virtual network
configs that already exist when upgrading from an older version of
libvirt, I've added a %post script to the specfile that searches for
all network definitions in both the config directory
(/etc/libvirt/qemu/networks) and the state directory
(/var/lib/libvirt/network) that are missing a mac address, generates a
random address, and adds it to the config (and a matching address to
the state file, if there is one).
docs/formatnetwork.html.in: document <mac address.../>
docs/schemas/network.rng: add nac address to schema
libvirt.spec.in: %post script to update existing networks
src/conf/network_conf.[ch]: parse and format <mac address.../>
src/libvirt_private.syms: export a couple private symbols we need
src/network/bridge_driver.c:
auto-generate mac address when needed,
create dummy interface if mac address is present.
tests/networkxml2xmlin/isolated-network.xml
tests/networkxml2xmlin/routed-network.xml
tests/networkxml2xmlout/isolated-network.xml
tests/networkxml2xmlout/routed-network.xml: add mac address to some tests
2011-02-09 08:28:12 +00:00
|
|
|
def->mac_specified = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-09-14 19:14:57 +00:00
|
|
|
/* NetworkObj backend of the virNetworkUpdate API */
|
|
|
|
|
|
|
|
static void
|
|
|
|
virNetworkDefUpdateNoSupport(virNetworkDefPtr def, const char *section)
|
|
|
|
{
|
|
|
|
virReportError(VIR_ERR_NO_SUPPORT,
|
|
|
|
_("can't update '%s' section of network '%s'"),
|
|
|
|
section, def->name);
|
|
|
|
}
|
2012-09-21 16:11:51 +00:00
|
|
|
static void
|
|
|
|
virNetworkDefUpdateUnknownCommand(unsigned int command)
|
|
|
|
{
|
|
|
|
virReportError(VIR_ERR_NO_SUPPORT,
|
|
|
|
_("unrecognized network update command code %d"), command);
|
|
|
|
}
|
2012-09-14 19:14:57 +00:00
|
|
|
|
|
|
|
static int
|
|
|
|
virNetworkDefUpdateCheckElementName(virNetworkDefPtr def,
|
|
|
|
xmlNodePtr node,
|
|
|
|
const char *section)
|
|
|
|
{
|
|
|
|
if (!xmlStrEqual(node->name, BAD_CAST section)) {
|
|
|
|
virReportError(VIR_ERR_XML_ERROR,
|
|
|
|
_("unexpected element <%s>, expecting <%s>, "
|
|
|
|
"while updating network '%s'"),
|
|
|
|
node->name, section, def->name);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
virNetworkDefUpdateBridge(virNetworkDefPtr def,
|
|
|
|
unsigned int command ATTRIBUTE_UNUSED,
|
|
|
|
int parentIndex ATTRIBUTE_UNUSED,
|
|
|
|
xmlXPathContextPtr ctxt ATTRIBUTE_UNUSED,
|
|
|
|
/* virNetworkUpdateFlags */
|
|
|
|
unsigned int fflags ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
virNetworkDefUpdateNoSupport(def, "bridge");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
virNetworkDefUpdateDomain(virNetworkDefPtr def,
|
|
|
|
unsigned int command ATTRIBUTE_UNUSED,
|
|
|
|
int parentIndex ATTRIBUTE_UNUSED,
|
|
|
|
xmlXPathContextPtr ctxt ATTRIBUTE_UNUSED,
|
|
|
|
/* virNetworkUpdateFlags */
|
|
|
|
unsigned int fflags ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
virNetworkDefUpdateNoSupport(def, "domain");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
virNetworkDefUpdateIP(virNetworkDefPtr def,
|
|
|
|
unsigned int command ATTRIBUTE_UNUSED,
|
|
|
|
int parentIndex ATTRIBUTE_UNUSED,
|
|
|
|
xmlXPathContextPtr ctxt ATTRIBUTE_UNUSED,
|
|
|
|
/* virNetworkUpdateFlags */
|
|
|
|
unsigned int fflags ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
virNetworkDefUpdateNoSupport(def, "ip");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
network: implement backend of virNetworkUpdate(IP_DHCP_HOST)
This patch fills in the first implementation for one of the
virNetworkUpdate sections. With this code, you can now add/delete/edit
<host> entries in a network's <ip> address <dhcp> element (by
specifying a section of VIR_NETWORK_SECTION_IP_DHCP_HOST).
If you pass in a parentIndex of -1, the code will automatically find
the one ip element that has a <dhcp> section and make the updates
there. Otherwise, you can specify an index >= 0, and libvirt will look
for that particular instance of <ip> in the network, and modify its
<dhcp> element. (This currently isn't very useful, because libvirt
only supports having dhcp information on a single IP address, but that
could change in the future).
When adding a new host entry
(VIR_NETWORK_UPDATE_COMMAND_ADD_(FIRST|LAST)), the existing entries
will be compared to the new entry, and if any non-empty attribute
matches, the add will fail. When updating an existing entry
(VIR_NETWORK_UPDATE_COMMAND_MODIFY), the mac address or name will be
used to find the existing entry, and other fields will only be updated
(note there is some potential for ambiguity here if you specify the
mac address from one entry and the name from another). When deleting
an existing entry (VIR_NETWORK_UPDATE_COMMAND_DELETE), all non-empty
attributes in the supplied xml arg will be compared - all of them must
match before libvirt will delete the host.
The xml should be a fully formed <host> element as it would appear in
a network definition, e.g. "<host mac=00:11:22:33:44:55 ip=10.1.23.22
name='testbox'/>" (when adding/updating, ip and one of mac|name is
required; when deleting, you can specify any one, two, or all
attributes, but they all must match the target element).
As with the update of any other section, you can choose to affect the
live config (with flag VIR_NETWORK_UPDATE_AFFECT_LIVE), the persistent
config (VIR_NETWORK_UPDATE_AFFECT_CONFIG), or both. If you've chosen
to affect the live config, those changes will take effect immediately,
with no need to destroy/restart the network.
An example of adding a host entry:
virNetworkUpdate(net, VIR_NETWORK_UPDATE_COMMAND_ADD_LAST,
VIR_NETWORK_SECTION_IP_DHCP_HOST, -1,
"<host mac='00:11:22:33:44:55' ip='192.168.122.5'/>",
VIR_NETWORK_UPDATE_AFFECT_LIVE
| VIR_NETWORK_UPDATE_AFFECT_CONFIG);
To delete that same entry:
virNetworkUpdate(net, VIR_NETWORK_UPDATE_COMMAND_DELETE,
VIR_NETWORK_SECTION_IP_DHCP_HOST, -1,
"<host mac='00:11:22:33:44:55'/>",
VIR_NETWORK_UPDATE_AFFECT_LIVE
| VIR_NETWORK_UPDATE_AFFECT_CONFIG);
(you could also delete it by replacing "mac='00:11:22:33:44:55'" with
"ip='192.168.122.5'".)
2012-09-17 21:03:11 +00:00
|
|
|
static virNetworkIpDefPtr
|
|
|
|
virNetworkIpDefByIndex(virNetworkDefPtr def, int parentIndex)
|
|
|
|
{
|
|
|
|
virNetworkIpDefPtr ipdef = NULL;
|
|
|
|
int ii;
|
|
|
|
|
|
|
|
/* first find which ip element's dhcp host list to work on */
|
|
|
|
if (parentIndex >= 0) {
|
|
|
|
ipdef = virNetworkDefGetIpByIndex(def, AF_UNSPEC, parentIndex);
|
|
|
|
if (!(ipdef &&
|
|
|
|
VIR_SOCKET_ADDR_IS_FAMILY(&ipdef->address, AF_INET))) {
|
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
_("couldn't update dhcp host entry - "
|
|
|
|
"no <ip family='ipv4'> "
|
|
|
|
"element found at index %d in network '%s'"),
|
|
|
|
parentIndex, def->name);
|
|
|
|
}
|
|
|
|
return ipdef;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* -1 means "find the most appropriate", which in this case
|
|
|
|
* means the one and only <ip> that has <dhcp> element
|
|
|
|
*/
|
|
|
|
for (ii = 0;
|
|
|
|
(ipdef = virNetworkDefGetIpByIndex(def, AF_UNSPEC, ii));
|
|
|
|
ii++) {
|
|
|
|
if (VIR_SOCKET_ADDR_IS_FAMILY(&ipdef->address, AF_INET) &&
|
|
|
|
(ipdef->nranges || ipdef->nhosts)) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!ipdef)
|
|
|
|
ipdef = virNetworkDefGetIpByIndex(def, AF_INET, 0);
|
|
|
|
if (!ipdef) {
|
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
_("couldn't update dhcp host entry - "
|
|
|
|
"no <ip family='ipv4'> "
|
|
|
|
"element found in network '%s'"), def->name);
|
|
|
|
}
|
|
|
|
return ipdef;
|
|
|
|
}
|
|
|
|
|
2012-09-14 19:14:57 +00:00
|
|
|
static int
|
|
|
|
virNetworkDefUpdateIPDHCPHost(virNetworkDefPtr def,
|
network: implement backend of virNetworkUpdate(IP_DHCP_HOST)
This patch fills in the first implementation for one of the
virNetworkUpdate sections. With this code, you can now add/delete/edit
<host> entries in a network's <ip> address <dhcp> element (by
specifying a section of VIR_NETWORK_SECTION_IP_DHCP_HOST).
If you pass in a parentIndex of -1, the code will automatically find
the one ip element that has a <dhcp> section and make the updates
there. Otherwise, you can specify an index >= 0, and libvirt will look
for that particular instance of <ip> in the network, and modify its
<dhcp> element. (This currently isn't very useful, because libvirt
only supports having dhcp information on a single IP address, but that
could change in the future).
When adding a new host entry
(VIR_NETWORK_UPDATE_COMMAND_ADD_(FIRST|LAST)), the existing entries
will be compared to the new entry, and if any non-empty attribute
matches, the add will fail. When updating an existing entry
(VIR_NETWORK_UPDATE_COMMAND_MODIFY), the mac address or name will be
used to find the existing entry, and other fields will only be updated
(note there is some potential for ambiguity here if you specify the
mac address from one entry and the name from another). When deleting
an existing entry (VIR_NETWORK_UPDATE_COMMAND_DELETE), all non-empty
attributes in the supplied xml arg will be compared - all of them must
match before libvirt will delete the host.
The xml should be a fully formed <host> element as it would appear in
a network definition, e.g. "<host mac=00:11:22:33:44:55 ip=10.1.23.22
name='testbox'/>" (when adding/updating, ip and one of mac|name is
required; when deleting, you can specify any one, two, or all
attributes, but they all must match the target element).
As with the update of any other section, you can choose to affect the
live config (with flag VIR_NETWORK_UPDATE_AFFECT_LIVE), the persistent
config (VIR_NETWORK_UPDATE_AFFECT_CONFIG), or both. If you've chosen
to affect the live config, those changes will take effect immediately,
with no need to destroy/restart the network.
An example of adding a host entry:
virNetworkUpdate(net, VIR_NETWORK_UPDATE_COMMAND_ADD_LAST,
VIR_NETWORK_SECTION_IP_DHCP_HOST, -1,
"<host mac='00:11:22:33:44:55' ip='192.168.122.5'/>",
VIR_NETWORK_UPDATE_AFFECT_LIVE
| VIR_NETWORK_UPDATE_AFFECT_CONFIG);
To delete that same entry:
virNetworkUpdate(net, VIR_NETWORK_UPDATE_COMMAND_DELETE,
VIR_NETWORK_SECTION_IP_DHCP_HOST, -1,
"<host mac='00:11:22:33:44:55'/>",
VIR_NETWORK_UPDATE_AFFECT_LIVE
| VIR_NETWORK_UPDATE_AFFECT_CONFIG);
(you could also delete it by replacing "mac='00:11:22:33:44:55'" with
"ip='192.168.122.5'".)
2012-09-17 21:03:11 +00:00
|
|
|
unsigned int command,
|
|
|
|
int parentIndex,
|
|
|
|
xmlXPathContextPtr ctxt,
|
2012-09-14 19:14:57 +00:00
|
|
|
/* virNetworkUpdateFlags */
|
|
|
|
unsigned int fflags ATTRIBUTE_UNUSED)
|
|
|
|
{
|
network: implement backend of virNetworkUpdate(IP_DHCP_HOST)
This patch fills in the first implementation for one of the
virNetworkUpdate sections. With this code, you can now add/delete/edit
<host> entries in a network's <ip> address <dhcp> element (by
specifying a section of VIR_NETWORK_SECTION_IP_DHCP_HOST).
If you pass in a parentIndex of -1, the code will automatically find
the one ip element that has a <dhcp> section and make the updates
there. Otherwise, you can specify an index >= 0, and libvirt will look
for that particular instance of <ip> in the network, and modify its
<dhcp> element. (This currently isn't very useful, because libvirt
only supports having dhcp information on a single IP address, but that
could change in the future).
When adding a new host entry
(VIR_NETWORK_UPDATE_COMMAND_ADD_(FIRST|LAST)), the existing entries
will be compared to the new entry, and if any non-empty attribute
matches, the add will fail. When updating an existing entry
(VIR_NETWORK_UPDATE_COMMAND_MODIFY), the mac address or name will be
used to find the existing entry, and other fields will only be updated
(note there is some potential for ambiguity here if you specify the
mac address from one entry and the name from another). When deleting
an existing entry (VIR_NETWORK_UPDATE_COMMAND_DELETE), all non-empty
attributes in the supplied xml arg will be compared - all of them must
match before libvirt will delete the host.
The xml should be a fully formed <host> element as it would appear in
a network definition, e.g. "<host mac=00:11:22:33:44:55 ip=10.1.23.22
name='testbox'/>" (when adding/updating, ip and one of mac|name is
required; when deleting, you can specify any one, two, or all
attributes, but they all must match the target element).
As with the update of any other section, you can choose to affect the
live config (with flag VIR_NETWORK_UPDATE_AFFECT_LIVE), the persistent
config (VIR_NETWORK_UPDATE_AFFECT_CONFIG), or both. If you've chosen
to affect the live config, those changes will take effect immediately,
with no need to destroy/restart the network.
An example of adding a host entry:
virNetworkUpdate(net, VIR_NETWORK_UPDATE_COMMAND_ADD_LAST,
VIR_NETWORK_SECTION_IP_DHCP_HOST, -1,
"<host mac='00:11:22:33:44:55' ip='192.168.122.5'/>",
VIR_NETWORK_UPDATE_AFFECT_LIVE
| VIR_NETWORK_UPDATE_AFFECT_CONFIG);
To delete that same entry:
virNetworkUpdate(net, VIR_NETWORK_UPDATE_COMMAND_DELETE,
VIR_NETWORK_SECTION_IP_DHCP_HOST, -1,
"<host mac='00:11:22:33:44:55'/>",
VIR_NETWORK_UPDATE_AFFECT_LIVE
| VIR_NETWORK_UPDATE_AFFECT_CONFIG);
(you could also delete it by replacing "mac='00:11:22:33:44:55'" with
"ip='192.168.122.5'".)
2012-09-17 21:03:11 +00:00
|
|
|
int ii, ret = -1;
|
|
|
|
virNetworkIpDefPtr ipdef = virNetworkIpDefByIndex(def, parentIndex);
|
|
|
|
virNetworkDHCPHostDef host;
|
|
|
|
|
|
|
|
memset(&host, 0, sizeof(host));
|
|
|
|
|
|
|
|
if (virNetworkDefUpdateCheckElementName(def, ctxt->node, "host") < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
/* ipdef is the ip element that needs its host array updated */
|
|
|
|
if (!ipdef)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
/* parse the xml into a virNetworkDHCPHostDef */
|
|
|
|
if (command == VIR_NETWORK_UPDATE_COMMAND_MODIFY) {
|
|
|
|
|
|
|
|
if (virNetworkDHCPHostDefParse(def->name, ctxt->node, &host, false) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
/* search for the entry with this (mac|name),
|
|
|
|
* and update the IP+(mac|name) */
|
|
|
|
for (ii = 0; ii < ipdef->nhosts; ii++) {
|
|
|
|
if ((host.mac &&
|
|
|
|
!virMacAddrCompare(host.mac, ipdef->hosts[ii].mac)) ||
|
|
|
|
(host.name &&
|
|
|
|
STREQ_NULLABLE(host.name, ipdef->hosts[ii].name))) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ii == ipdef->nhosts) {
|
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
_("couldn't locate an existing dhcp host entry with "
|
|
|
|
"\"mac='%s'\" in network '%s'"),
|
|
|
|
host.mac, def->name);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* clear the existing hosts entry, move the new one in its place,
|
|
|
|
* then clear out the extra copy to get rid of the duplicate pointers
|
|
|
|
* to its data (mac and name strings).
|
|
|
|
*/
|
|
|
|
virNetworkDHCPHostDefClear(&ipdef->hosts[ii]);
|
|
|
|
ipdef->hosts[ii] = host;
|
|
|
|
memset(&host, 0, sizeof(host));
|
|
|
|
|
|
|
|
} else if ((command == VIR_NETWORK_UPDATE_COMMAND_ADD_FIRST) ||
|
|
|
|
(command == VIR_NETWORK_UPDATE_COMMAND_ADD_LAST)) {
|
|
|
|
|
|
|
|
if (virNetworkDHCPHostDefParse(def->name, ctxt->node, &host, true) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
/* log error if an entry with same name/address/ip already exists */
|
|
|
|
for (ii = 0; ii < ipdef->nhosts; ii++) {
|
|
|
|
if ((host.mac &&
|
|
|
|
!virMacAddrCompare(host.mac, ipdef->hosts[ii].mac)) ||
|
|
|
|
(host.name &&
|
|
|
|
STREQ_NULLABLE(host.name, ipdef->hosts[ii].name)) ||
|
|
|
|
(VIR_SOCKET_ADDR_VALID(&host.ip) &&
|
|
|
|
virSocketAddrEqual(&host.ip, &ipdef->hosts[ii].ip))) {
|
|
|
|
char *ip = virSocketAddrFormat(&host.ip);
|
|
|
|
|
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
_("there is an existing dhcp host entry in "
|
|
|
|
"network '%s' that matches "
|
|
|
|
"\"<host mac='%s' name='%s' ip='%s'/>\""),
|
|
|
|
def->name, host.mac, host.name,
|
|
|
|
ip ? ip : "unknown");
|
|
|
|
VIR_FREE(ip);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* add to beginning/end of list */
|
|
|
|
if (VIR_REALLOC_N(ipdef->hosts, ipdef->nhosts +1) < 0) {
|
|
|
|
virReportOOMError();
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (command == VIR_NETWORK_UPDATE_COMMAND_ADD_LAST) {
|
|
|
|
|
|
|
|
ipdef->hosts[ipdef->nhosts] = host;
|
|
|
|
ipdef->nhosts++;
|
|
|
|
memset(&host, 0, sizeof(host));
|
|
|
|
|
|
|
|
} else { /* implied (command == VIR_NETWORK_UPDATE_COMMAND_ADD_FIRST) */
|
|
|
|
|
|
|
|
memmove(ipdef->hosts + 1, ipdef->hosts,
|
2012-09-19 22:45:58 +00:00
|
|
|
sizeof(*ipdef->hosts) * ipdef->nhosts);
|
network: implement backend of virNetworkUpdate(IP_DHCP_HOST)
This patch fills in the first implementation for one of the
virNetworkUpdate sections. With this code, you can now add/delete/edit
<host> entries in a network's <ip> address <dhcp> element (by
specifying a section of VIR_NETWORK_SECTION_IP_DHCP_HOST).
If you pass in a parentIndex of -1, the code will automatically find
the one ip element that has a <dhcp> section and make the updates
there. Otherwise, you can specify an index >= 0, and libvirt will look
for that particular instance of <ip> in the network, and modify its
<dhcp> element. (This currently isn't very useful, because libvirt
only supports having dhcp information on a single IP address, but that
could change in the future).
When adding a new host entry
(VIR_NETWORK_UPDATE_COMMAND_ADD_(FIRST|LAST)), the existing entries
will be compared to the new entry, and if any non-empty attribute
matches, the add will fail. When updating an existing entry
(VIR_NETWORK_UPDATE_COMMAND_MODIFY), the mac address or name will be
used to find the existing entry, and other fields will only be updated
(note there is some potential for ambiguity here if you specify the
mac address from one entry and the name from another). When deleting
an existing entry (VIR_NETWORK_UPDATE_COMMAND_DELETE), all non-empty
attributes in the supplied xml arg will be compared - all of them must
match before libvirt will delete the host.
The xml should be a fully formed <host> element as it would appear in
a network definition, e.g. "<host mac=00:11:22:33:44:55 ip=10.1.23.22
name='testbox'/>" (when adding/updating, ip and one of mac|name is
required; when deleting, you can specify any one, two, or all
attributes, but they all must match the target element).
As with the update of any other section, you can choose to affect the
live config (with flag VIR_NETWORK_UPDATE_AFFECT_LIVE), the persistent
config (VIR_NETWORK_UPDATE_AFFECT_CONFIG), or both. If you've chosen
to affect the live config, those changes will take effect immediately,
with no need to destroy/restart the network.
An example of adding a host entry:
virNetworkUpdate(net, VIR_NETWORK_UPDATE_COMMAND_ADD_LAST,
VIR_NETWORK_SECTION_IP_DHCP_HOST, -1,
"<host mac='00:11:22:33:44:55' ip='192.168.122.5'/>",
VIR_NETWORK_UPDATE_AFFECT_LIVE
| VIR_NETWORK_UPDATE_AFFECT_CONFIG);
To delete that same entry:
virNetworkUpdate(net, VIR_NETWORK_UPDATE_COMMAND_DELETE,
VIR_NETWORK_SECTION_IP_DHCP_HOST, -1,
"<host mac='00:11:22:33:44:55'/>",
VIR_NETWORK_UPDATE_AFFECT_LIVE
| VIR_NETWORK_UPDATE_AFFECT_CONFIG);
(you could also delete it by replacing "mac='00:11:22:33:44:55'" with
"ip='192.168.122.5'".)
2012-09-17 21:03:11 +00:00
|
|
|
ipdef->hosts[0] = host;
|
|
|
|
ipdef->nhosts++;
|
|
|
|
memset(&host, 0, sizeof(host));
|
|
|
|
}
|
|
|
|
|
|
|
|
} else if (command == VIR_NETWORK_UPDATE_COMMAND_DELETE) {
|
|
|
|
|
|
|
|
if (virNetworkDHCPHostDefParse(def->name, ctxt->node, &host, false) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
/* find matching entry - all specified attributes must match */
|
|
|
|
for (ii = 0; ii < ipdef->nhosts; ii++) {
|
|
|
|
if ((!host.mac ||
|
|
|
|
!virMacAddrCompare(host.mac, ipdef->hosts[ii].mac)) &&
|
|
|
|
(!host.name ||
|
|
|
|
STREQ_NULLABLE(host.name, ipdef->hosts[ii].name)) &&
|
|
|
|
(!VIR_SOCKET_ADDR_VALID(&host.ip) ||
|
|
|
|
virSocketAddrEqual(&host.ip, &ipdef->hosts[ii].ip))) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (ii == ipdef->nhosts) {
|
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
_("couldn't locate a matching dhcp host entry "
|
|
|
|
"in network '%s'"), def->name);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* remove it */
|
|
|
|
virNetworkDHCPHostDefClear(&ipdef->hosts[ii]);
|
|
|
|
memmove(ipdef->hosts + ii, ipdef->hosts + ii + 1,
|
2012-09-19 22:45:58 +00:00
|
|
|
sizeof(*ipdef->hosts) * (ipdef->nhosts - ii - 1));
|
network: implement backend of virNetworkUpdate(IP_DHCP_HOST)
This patch fills in the first implementation for one of the
virNetworkUpdate sections. With this code, you can now add/delete/edit
<host> entries in a network's <ip> address <dhcp> element (by
specifying a section of VIR_NETWORK_SECTION_IP_DHCP_HOST).
If you pass in a parentIndex of -1, the code will automatically find
the one ip element that has a <dhcp> section and make the updates
there. Otherwise, you can specify an index >= 0, and libvirt will look
for that particular instance of <ip> in the network, and modify its
<dhcp> element. (This currently isn't very useful, because libvirt
only supports having dhcp information on a single IP address, but that
could change in the future).
When adding a new host entry
(VIR_NETWORK_UPDATE_COMMAND_ADD_(FIRST|LAST)), the existing entries
will be compared to the new entry, and if any non-empty attribute
matches, the add will fail. When updating an existing entry
(VIR_NETWORK_UPDATE_COMMAND_MODIFY), the mac address or name will be
used to find the existing entry, and other fields will only be updated
(note there is some potential for ambiguity here if you specify the
mac address from one entry and the name from another). When deleting
an existing entry (VIR_NETWORK_UPDATE_COMMAND_DELETE), all non-empty
attributes in the supplied xml arg will be compared - all of them must
match before libvirt will delete the host.
The xml should be a fully formed <host> element as it would appear in
a network definition, e.g. "<host mac=00:11:22:33:44:55 ip=10.1.23.22
name='testbox'/>" (when adding/updating, ip and one of mac|name is
required; when deleting, you can specify any one, two, or all
attributes, but they all must match the target element).
As with the update of any other section, you can choose to affect the
live config (with flag VIR_NETWORK_UPDATE_AFFECT_LIVE), the persistent
config (VIR_NETWORK_UPDATE_AFFECT_CONFIG), or both. If you've chosen
to affect the live config, those changes will take effect immediately,
with no need to destroy/restart the network.
An example of adding a host entry:
virNetworkUpdate(net, VIR_NETWORK_UPDATE_COMMAND_ADD_LAST,
VIR_NETWORK_SECTION_IP_DHCP_HOST, -1,
"<host mac='00:11:22:33:44:55' ip='192.168.122.5'/>",
VIR_NETWORK_UPDATE_AFFECT_LIVE
| VIR_NETWORK_UPDATE_AFFECT_CONFIG);
To delete that same entry:
virNetworkUpdate(net, VIR_NETWORK_UPDATE_COMMAND_DELETE,
VIR_NETWORK_SECTION_IP_DHCP_HOST, -1,
"<host mac='00:11:22:33:44:55'/>",
VIR_NETWORK_UPDATE_AFFECT_LIVE
| VIR_NETWORK_UPDATE_AFFECT_CONFIG);
(you could also delete it by replacing "mac='00:11:22:33:44:55'" with
"ip='192.168.122.5'".)
2012-09-17 21:03:11 +00:00
|
|
|
ipdef->nhosts--;
|
|
|
|
ignore_value(VIR_REALLOC_N(ipdef->hosts, ipdef->nhosts));
|
2012-09-21 16:11:51 +00:00
|
|
|
} else {
|
|
|
|
virNetworkDefUpdateUnknownCommand(command);
|
|
|
|
goto cleanup;
|
network: implement backend of virNetworkUpdate(IP_DHCP_HOST)
This patch fills in the first implementation for one of the
virNetworkUpdate sections. With this code, you can now add/delete/edit
<host> entries in a network's <ip> address <dhcp> element (by
specifying a section of VIR_NETWORK_SECTION_IP_DHCP_HOST).
If you pass in a parentIndex of -1, the code will automatically find
the one ip element that has a <dhcp> section and make the updates
there. Otherwise, you can specify an index >= 0, and libvirt will look
for that particular instance of <ip> in the network, and modify its
<dhcp> element. (This currently isn't very useful, because libvirt
only supports having dhcp information on a single IP address, but that
could change in the future).
When adding a new host entry
(VIR_NETWORK_UPDATE_COMMAND_ADD_(FIRST|LAST)), the existing entries
will be compared to the new entry, and if any non-empty attribute
matches, the add will fail. When updating an existing entry
(VIR_NETWORK_UPDATE_COMMAND_MODIFY), the mac address or name will be
used to find the existing entry, and other fields will only be updated
(note there is some potential for ambiguity here if you specify the
mac address from one entry and the name from another). When deleting
an existing entry (VIR_NETWORK_UPDATE_COMMAND_DELETE), all non-empty
attributes in the supplied xml arg will be compared - all of them must
match before libvirt will delete the host.
The xml should be a fully formed <host> element as it would appear in
a network definition, e.g. "<host mac=00:11:22:33:44:55 ip=10.1.23.22
name='testbox'/>" (when adding/updating, ip and one of mac|name is
required; when deleting, you can specify any one, two, or all
attributes, but they all must match the target element).
As with the update of any other section, you can choose to affect the
live config (with flag VIR_NETWORK_UPDATE_AFFECT_LIVE), the persistent
config (VIR_NETWORK_UPDATE_AFFECT_CONFIG), or both. If you've chosen
to affect the live config, those changes will take effect immediately,
with no need to destroy/restart the network.
An example of adding a host entry:
virNetworkUpdate(net, VIR_NETWORK_UPDATE_COMMAND_ADD_LAST,
VIR_NETWORK_SECTION_IP_DHCP_HOST, -1,
"<host mac='00:11:22:33:44:55' ip='192.168.122.5'/>",
VIR_NETWORK_UPDATE_AFFECT_LIVE
| VIR_NETWORK_UPDATE_AFFECT_CONFIG);
To delete that same entry:
virNetworkUpdate(net, VIR_NETWORK_UPDATE_COMMAND_DELETE,
VIR_NETWORK_SECTION_IP_DHCP_HOST, -1,
"<host mac='00:11:22:33:44:55'/>",
VIR_NETWORK_UPDATE_AFFECT_LIVE
| VIR_NETWORK_UPDATE_AFFECT_CONFIG);
(you could also delete it by replacing "mac='00:11:22:33:44:55'" with
"ip='192.168.122.5'".)
2012-09-17 21:03:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
cleanup:
|
|
|
|
virNetworkDHCPHostDefClear(&host);
|
|
|
|
return ret;
|
2012-09-14 19:14:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
virNetworkDefUpdateIPDHCPRange(virNetworkDefPtr def,
|
network: backend for virNetworkUpdate of dhcp range
The dhcp range element is contained in the <dhcp> element of one of a
network's <ip> elements. There can be multiple <range>
elements. Because there are only two attributes (start and end), and
those are exactly what you would use to identify a particular range,
it doesn't really make sense to modify an existing element, so
VIR_NETWORK_UPDATE_COMMAND_MODIFY isn't supported for this section,
only ADD_FIRST, ADD_LAST, and DELETE.
Since virsh already has support for understanding all the defined
sections, this new backend is automatically supported by virsh. You
would use it like this:
virsh net-update mynet add ip-dhcp-range \
"<range start='1.2.3.4' end='1.2.3.20'/>" --live --config
The bridge driver also already supports all sections, so it's doing
the correct thing in this case as well - since the dhcp range is
placed on the dnsmasq commandline, the bridge driver recreates the
dnsmasq commandline, and re-runs dnsmasq whenever a range is
added/deleted (and AFFECT_LIVE is specified in the flags).
2012-09-21 02:25:40 +00:00
|
|
|
unsigned int command,
|
2012-09-14 19:14:57 +00:00
|
|
|
int parentIndex ATTRIBUTE_UNUSED,
|
network: backend for virNetworkUpdate of dhcp range
The dhcp range element is contained in the <dhcp> element of one of a
network's <ip> elements. There can be multiple <range>
elements. Because there are only two attributes (start and end), and
those are exactly what you would use to identify a particular range,
it doesn't really make sense to modify an existing element, so
VIR_NETWORK_UPDATE_COMMAND_MODIFY isn't supported for this section,
only ADD_FIRST, ADD_LAST, and DELETE.
Since virsh already has support for understanding all the defined
sections, this new backend is automatically supported by virsh. You
would use it like this:
virsh net-update mynet add ip-dhcp-range \
"<range start='1.2.3.4' end='1.2.3.20'/>" --live --config
The bridge driver also already supports all sections, so it's doing
the correct thing in this case as well - since the dhcp range is
placed on the dnsmasq commandline, the bridge driver recreates the
dnsmasq commandline, and re-runs dnsmasq whenever a range is
added/deleted (and AFFECT_LIVE is specified in the flags).
2012-09-21 02:25:40 +00:00
|
|
|
xmlXPathContextPtr ctxt,
|
2012-09-14 19:14:57 +00:00
|
|
|
/* virNetworkUpdateFlags */
|
|
|
|
unsigned int fflags ATTRIBUTE_UNUSED)
|
|
|
|
{
|
network: backend for virNetworkUpdate of dhcp range
The dhcp range element is contained in the <dhcp> element of one of a
network's <ip> elements. There can be multiple <range>
elements. Because there are only two attributes (start and end), and
those are exactly what you would use to identify a particular range,
it doesn't really make sense to modify an existing element, so
VIR_NETWORK_UPDATE_COMMAND_MODIFY isn't supported for this section,
only ADD_FIRST, ADD_LAST, and DELETE.
Since virsh already has support for understanding all the defined
sections, this new backend is automatically supported by virsh. You
would use it like this:
virsh net-update mynet add ip-dhcp-range \
"<range start='1.2.3.4' end='1.2.3.20'/>" --live --config
The bridge driver also already supports all sections, so it's doing
the correct thing in this case as well - since the dhcp range is
placed on the dnsmasq commandline, the bridge driver recreates the
dnsmasq commandline, and re-runs dnsmasq whenever a range is
added/deleted (and AFFECT_LIVE is specified in the flags).
2012-09-21 02:25:40 +00:00
|
|
|
int ii, ret = -1;
|
|
|
|
virNetworkIpDefPtr ipdef = virNetworkIpDefByIndex(def, parentIndex);
|
|
|
|
virNetworkDHCPRangeDef range;
|
|
|
|
|
|
|
|
memset(&range, 0, sizeof(range));
|
|
|
|
|
|
|
|
if (virNetworkDefUpdateCheckElementName(def, ctxt->node, "range") < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
/* ipdef is the ip element that needs its range array updated */
|
|
|
|
if (!ipdef)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
/* parse the xml into a virNetworkDHCPRangeDef */
|
|
|
|
if (command == VIR_NETWORK_UPDATE_COMMAND_MODIFY) {
|
|
|
|
|
|
|
|
virReportError(VIR_ERR_NO_SUPPORT, "%s",
|
|
|
|
_("dhcp ranges cannot be modified, "
|
|
|
|
"only added or deleted"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (virNetworkDHCPRangeDefParse(def->name, ctxt->node, &range) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
/* check if an entry with same name/address/ip already exists */
|
|
|
|
for (ii = 0; ii < ipdef->nranges; ii++) {
|
|
|
|
if (virSocketAddrEqual(&range.start, &ipdef->ranges[ii].start) &&
|
|
|
|
virSocketAddrEqual(&range.end, &ipdef->ranges[ii].end)) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((command == VIR_NETWORK_UPDATE_COMMAND_ADD_FIRST) ||
|
|
|
|
(command == VIR_NETWORK_UPDATE_COMMAND_ADD_LAST)) {
|
|
|
|
|
|
|
|
if (ii < ipdef->nranges) {
|
|
|
|
char *startip = virSocketAddrFormat(&range.start);
|
|
|
|
char *endip = virSocketAddrFormat(&range.end);
|
|
|
|
|
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
_("there is an existing dhcp range entry in "
|
|
|
|
"network '%s' that matches "
|
|
|
|
"\"<range start='%s' end='%s'/>\""),
|
|
|
|
def->name,
|
|
|
|
startip ? startip : "unknown",
|
|
|
|
endip ? endip : "unknown");
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* add to beginning/end of list */
|
|
|
|
if (VIR_REALLOC_N(ipdef->ranges, ipdef->nranges +1) < 0) {
|
|
|
|
virReportOOMError();
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (command == VIR_NETWORK_UPDATE_COMMAND_ADD_LAST) {
|
|
|
|
ipdef->ranges[ipdef->nranges] = range;
|
|
|
|
} else { /* implied (command == VIR_NETWORK_UPDATE_COMMAND_ADD_FIRST) */
|
|
|
|
memmove(ipdef->ranges + 1, ipdef->ranges,
|
|
|
|
sizeof(*ipdef->ranges) * ipdef->nranges);
|
|
|
|
ipdef->ranges[0] = range;
|
|
|
|
}
|
|
|
|
ipdef->nranges++;
|
|
|
|
memset(&range, 0, sizeof(range));
|
|
|
|
|
|
|
|
} else if (command == VIR_NETWORK_UPDATE_COMMAND_DELETE) {
|
|
|
|
|
|
|
|
if (ii == ipdef->nranges) {
|
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
_("couldn't locate a matching dhcp range entry "
|
|
|
|
"in network '%s'"), def->name);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* remove it */
|
|
|
|
/* NB: nothing to clear from a RangeDef that's being freed */
|
|
|
|
memmove(ipdef->ranges + ii, ipdef->ranges + ii + 1,
|
|
|
|
sizeof(*ipdef->ranges) * (ipdef->nranges - ii - 1));
|
|
|
|
ipdef->nranges--;
|
|
|
|
ignore_value(VIR_REALLOC_N(ipdef->ranges, ipdef->nranges));
|
2012-09-21 16:11:51 +00:00
|
|
|
} else {
|
|
|
|
virNetworkDefUpdateUnknownCommand(command);
|
|
|
|
goto cleanup;
|
network: backend for virNetworkUpdate of dhcp range
The dhcp range element is contained in the <dhcp> element of one of a
network's <ip> elements. There can be multiple <range>
elements. Because there are only two attributes (start and end), and
those are exactly what you would use to identify a particular range,
it doesn't really make sense to modify an existing element, so
VIR_NETWORK_UPDATE_COMMAND_MODIFY isn't supported for this section,
only ADD_FIRST, ADD_LAST, and DELETE.
Since virsh already has support for understanding all the defined
sections, this new backend is automatically supported by virsh. You
would use it like this:
virsh net-update mynet add ip-dhcp-range \
"<range start='1.2.3.4' end='1.2.3.20'/>" --live --config
The bridge driver also already supports all sections, so it's doing
the correct thing in this case as well - since the dhcp range is
placed on the dnsmasq commandline, the bridge driver recreates the
dnsmasq commandline, and re-runs dnsmasq whenever a range is
added/deleted (and AFFECT_LIVE is specified in the flags).
2012-09-21 02:25:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
cleanup:
|
|
|
|
return ret;
|
2012-09-14 19:14:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
virNetworkDefUpdateForward(virNetworkDefPtr def,
|
|
|
|
unsigned int command ATTRIBUTE_UNUSED,
|
|
|
|
int parentIndex ATTRIBUTE_UNUSED,
|
|
|
|
xmlXPathContextPtr ctxt ATTRIBUTE_UNUSED,
|
|
|
|
/* virNetworkUpdateFlags */
|
|
|
|
unsigned int fflags ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
virNetworkDefUpdateNoSupport(def, "forward");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
virNetworkDefUpdateForwardInterface(virNetworkDefPtr def,
|
|
|
|
unsigned int command ATTRIBUTE_UNUSED,
|
|
|
|
int parentIndex ATTRIBUTE_UNUSED,
|
|
|
|
xmlXPathContextPtr ctxt ATTRIBUTE_UNUSED,
|
|
|
|
/* virNetworkUpdateFlags */
|
|
|
|
unsigned int fflags ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
virNetworkDefUpdateNoSupport(def, "forward interface");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
virNetworkDefUpdateForwardPF(virNetworkDefPtr def,
|
|
|
|
unsigned int command ATTRIBUTE_UNUSED,
|
|
|
|
int parentIndex ATTRIBUTE_UNUSED,
|
|
|
|
xmlXPathContextPtr ctxt ATTRIBUTE_UNUSED,
|
|
|
|
/* virNetworkUpdateFlags */
|
|
|
|
unsigned int fflags ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
virNetworkDefUpdateNoSupport(def, "forward pf");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
network: backend for virNetworkUpdate of portgroups
portgroup elements are located in the toplevel of <network>
objects. There can be multiple <portgroup> elements, and they each
have a unique name attribute.
Add, delete, and modify are all supported for portgroup. When deleting
a portgroup, only the name must be specified in the provided xml - all
other attributes and subelements are ignored for the purposes of
matching and existing portgroup.
The bridge driver and virsh already know about the portgroup element,
so providing this backend should cause the entire stack to work. Note
that in the case of portgroup, there is no external daemon based on
the portgroup config, so nothing must be restarted.
It is important to note that guests make a copy of the appropriate
network's portgroup data when they are started, so although an updated
portgroup's configuration will have an affect on new guests started
after the cahange, existing guests won't magically have their
bandwidth changed, for example. If something like that is desired, it
will take a lot of redesign work in the way network devices are setup
(there is currently no link from the network back to the individual
interfaces using it, much less from a portgroup within a network back
to the individual interfaces).
2012-09-21 02:25:41 +00:00
|
|
|
virNetworkDefUpdatePortGroup(virNetworkDefPtr def,
|
|
|
|
unsigned int command,
|
2012-09-14 19:14:57 +00:00
|
|
|
int parentIndex ATTRIBUTE_UNUSED,
|
network: backend for virNetworkUpdate of portgroups
portgroup elements are located in the toplevel of <network>
objects. There can be multiple <portgroup> elements, and they each
have a unique name attribute.
Add, delete, and modify are all supported for portgroup. When deleting
a portgroup, only the name must be specified in the provided xml - all
other attributes and subelements are ignored for the purposes of
matching and existing portgroup.
The bridge driver and virsh already know about the portgroup element,
so providing this backend should cause the entire stack to work. Note
that in the case of portgroup, there is no external daemon based on
the portgroup config, so nothing must be restarted.
It is important to note that guests make a copy of the appropriate
network's portgroup data when they are started, so although an updated
portgroup's configuration will have an affect on new guests started
after the cahange, existing guests won't magically have their
bandwidth changed, for example. If something like that is desired, it
will take a lot of redesign work in the way network devices are setup
(there is currently no link from the network back to the individual
interfaces using it, much less from a portgroup within a network back
to the individual interfaces).
2012-09-21 02:25:41 +00:00
|
|
|
xmlXPathContextPtr ctxt,
|
2012-09-14 19:14:57 +00:00
|
|
|
/* virNetworkUpdateFlags */
|
|
|
|
unsigned int fflags ATTRIBUTE_UNUSED)
|
|
|
|
{
|
2012-10-20 08:39:18 +00:00
|
|
|
int ii, foundName = -1, foundDefault = -1;
|
|
|
|
int ret = -1;
|
network: backend for virNetworkUpdate of portgroups
portgroup elements are located in the toplevel of <network>
objects. There can be multiple <portgroup> elements, and they each
have a unique name attribute.
Add, delete, and modify are all supported for portgroup. When deleting
a portgroup, only the name must be specified in the provided xml - all
other attributes and subelements are ignored for the purposes of
matching and existing portgroup.
The bridge driver and virsh already know about the portgroup element,
so providing this backend should cause the entire stack to work. Note
that in the case of portgroup, there is no external daemon based on
the portgroup config, so nothing must be restarted.
It is important to note that guests make a copy of the appropriate
network's portgroup data when they are started, so although an updated
portgroup's configuration will have an affect on new guests started
after the cahange, existing guests won't magically have their
bandwidth changed, for example. If something like that is desired, it
will take a lot of redesign work in the way network devices are setup
(there is currently no link from the network back to the individual
interfaces using it, much less from a portgroup within a network back
to the individual interfaces).
2012-09-21 02:25:41 +00:00
|
|
|
virPortGroupDef portgroup;
|
|
|
|
|
|
|
|
memset(&portgroup, 0, sizeof(portgroup));
|
|
|
|
|
|
|
|
if (virNetworkDefUpdateCheckElementName(def, ctxt->node, "portgroup") < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (virNetworkPortGroupParseXML(&portgroup, ctxt->node, ctxt) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
/* check if a portgroup with same name already exists */
|
|
|
|
for (ii = 0; ii < def->nPortGroups; ii++) {
|
|
|
|
if (STREQ(portgroup.name, def->portGroups[ii].name))
|
2012-10-20 08:39:18 +00:00
|
|
|
foundName = ii;
|
|
|
|
if (def->portGroups[ii].isDefault)
|
|
|
|
foundDefault = ii;
|
network: backend for virNetworkUpdate of portgroups
portgroup elements are located in the toplevel of <network>
objects. There can be multiple <portgroup> elements, and they each
have a unique name attribute.
Add, delete, and modify are all supported for portgroup. When deleting
a portgroup, only the name must be specified in the provided xml - all
other attributes and subelements are ignored for the purposes of
matching and existing portgroup.
The bridge driver and virsh already know about the portgroup element,
so providing this backend should cause the entire stack to work. Note
that in the case of portgroup, there is no external daemon based on
the portgroup config, so nothing must be restarted.
It is important to note that guests make a copy of the appropriate
network's portgroup data when they are started, so although an updated
portgroup's configuration will have an affect on new guests started
after the cahange, existing guests won't magically have their
bandwidth changed, for example. If something like that is desired, it
will take a lot of redesign work in the way network devices are setup
(there is currently no link from the network back to the individual
interfaces using it, much less from a portgroup within a network back
to the individual interfaces).
2012-09-21 02:25:41 +00:00
|
|
|
}
|
2012-10-20 08:39:18 +00:00
|
|
|
if (foundName == -1 &&
|
network: backend for virNetworkUpdate of portgroups
portgroup elements are located in the toplevel of <network>
objects. There can be multiple <portgroup> elements, and they each
have a unique name attribute.
Add, delete, and modify are all supported for portgroup. When deleting
a portgroup, only the name must be specified in the provided xml - all
other attributes and subelements are ignored for the purposes of
matching and existing portgroup.
The bridge driver and virsh already know about the portgroup element,
so providing this backend should cause the entire stack to work. Note
that in the case of portgroup, there is no external daemon based on
the portgroup config, so nothing must be restarted.
It is important to note that guests make a copy of the appropriate
network's portgroup data when they are started, so although an updated
portgroup's configuration will have an affect on new guests started
after the cahange, existing guests won't magically have their
bandwidth changed, for example. If something like that is desired, it
will take a lot of redesign work in the way network devices are setup
(there is currently no link from the network back to the individual
interfaces using it, much less from a portgroup within a network back
to the individual interfaces).
2012-09-21 02:25:41 +00:00
|
|
|
((command == VIR_NETWORK_UPDATE_COMMAND_MODIFY) ||
|
|
|
|
(command == VIR_NETWORK_UPDATE_COMMAND_DELETE))) {
|
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
_("couldn't find a portgroup entry "
|
|
|
|
"in network '%s' matching <portgroup name='%s'>"),
|
|
|
|
def->name, portgroup.name);
|
|
|
|
goto cleanup;
|
2012-10-20 08:39:18 +00:00
|
|
|
} else if (foundName >= 0 &&
|
network: backend for virNetworkUpdate of portgroups
portgroup elements are located in the toplevel of <network>
objects. There can be multiple <portgroup> elements, and they each
have a unique name attribute.
Add, delete, and modify are all supported for portgroup. When deleting
a portgroup, only the name must be specified in the provided xml - all
other attributes and subelements are ignored for the purposes of
matching and existing portgroup.
The bridge driver and virsh already know about the portgroup element,
so providing this backend should cause the entire stack to work. Note
that in the case of portgroup, there is no external daemon based on
the portgroup config, so nothing must be restarted.
It is important to note that guests make a copy of the appropriate
network's portgroup data when they are started, so although an updated
portgroup's configuration will have an affect on new guests started
after the cahange, existing guests won't magically have their
bandwidth changed, for example. If something like that is desired, it
will take a lot of redesign work in the way network devices are setup
(there is currently no link from the network back to the individual
interfaces using it, much less from a portgroup within a network back
to the individual interfaces).
2012-09-21 02:25:41 +00:00
|
|
|
((command == VIR_NETWORK_UPDATE_COMMAND_ADD_FIRST) ||
|
|
|
|
(command == VIR_NETWORK_UPDATE_COMMAND_ADD_LAST))) {
|
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
_("there is an existing portgroup entry in "
|
|
|
|
"network '%s' that matches "
|
|
|
|
"\"<portgroup name='%s'>\""),
|
|
|
|
def->name, portgroup.name);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2012-10-20 08:39:18 +00:00
|
|
|
/* if there is already a different default, we can't make this
|
|
|
|
* one the default.
|
|
|
|
*/
|
|
|
|
if (command != VIR_NETWORK_UPDATE_COMMAND_DELETE &&
|
|
|
|
portgroup.isDefault &&
|
|
|
|
foundDefault >= 0 && foundDefault != foundName) {
|
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
_("a different portgroup entry in "
|
|
|
|
"network '%s' is already set as the default. "
|
|
|
|
"Only one default is allowed."),
|
|
|
|
def->name);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
network: backend for virNetworkUpdate of portgroups
portgroup elements are located in the toplevel of <network>
objects. There can be multiple <portgroup> elements, and they each
have a unique name attribute.
Add, delete, and modify are all supported for portgroup. When deleting
a portgroup, only the name must be specified in the provided xml - all
other attributes and subelements are ignored for the purposes of
matching and existing portgroup.
The bridge driver and virsh already know about the portgroup element,
so providing this backend should cause the entire stack to work. Note
that in the case of portgroup, there is no external daemon based on
the portgroup config, so nothing must be restarted.
It is important to note that guests make a copy of the appropriate
network's portgroup data when they are started, so although an updated
portgroup's configuration will have an affect on new guests started
after the cahange, existing guests won't magically have their
bandwidth changed, for example. If something like that is desired, it
will take a lot of redesign work in the way network devices are setup
(there is currently no link from the network back to the individual
interfaces using it, much less from a portgroup within a network back
to the individual interfaces).
2012-09-21 02:25:41 +00:00
|
|
|
if (command == VIR_NETWORK_UPDATE_COMMAND_MODIFY) {
|
|
|
|
|
|
|
|
/* replace existing entry */
|
2012-10-20 08:39:18 +00:00
|
|
|
virPortGroupDefClear(&def->portGroups[foundName]);
|
|
|
|
def->portGroups[foundName] = portgroup;
|
network: backend for virNetworkUpdate of portgroups
portgroup elements are located in the toplevel of <network>
objects. There can be multiple <portgroup> elements, and they each
have a unique name attribute.
Add, delete, and modify are all supported for portgroup. When deleting
a portgroup, only the name must be specified in the provided xml - all
other attributes and subelements are ignored for the purposes of
matching and existing portgroup.
The bridge driver and virsh already know about the portgroup element,
so providing this backend should cause the entire stack to work. Note
that in the case of portgroup, there is no external daemon based on
the portgroup config, so nothing must be restarted.
It is important to note that guests make a copy of the appropriate
network's portgroup data when they are started, so although an updated
portgroup's configuration will have an affect on new guests started
after the cahange, existing guests won't magically have their
bandwidth changed, for example. If something like that is desired, it
will take a lot of redesign work in the way network devices are setup
(there is currently no link from the network back to the individual
interfaces using it, much less from a portgroup within a network back
to the individual interfaces).
2012-09-21 02:25:41 +00:00
|
|
|
memset(&portgroup, 0, sizeof(portgroup));
|
|
|
|
|
|
|
|
} else if ((command == VIR_NETWORK_UPDATE_COMMAND_ADD_FIRST) ||
|
|
|
|
(command == VIR_NETWORK_UPDATE_COMMAND_ADD_LAST)) {
|
|
|
|
|
|
|
|
/* add to beginning/end of list */
|
|
|
|
if (VIR_REALLOC_N(def->portGroups, def->nPortGroups +1) < 0) {
|
|
|
|
virReportOOMError();
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (command == VIR_NETWORK_UPDATE_COMMAND_ADD_LAST) {
|
|
|
|
def->portGroups[def->nPortGroups] = portgroup;
|
|
|
|
} else { /* implied (command == VIR_NETWORK_UPDATE_COMMAND_ADD_FIRST) */
|
|
|
|
memmove(def->portGroups + 1, def->portGroups,
|
|
|
|
sizeof(*def->portGroups) * def->nPortGroups);
|
|
|
|
def->portGroups[0] = portgroup;
|
|
|
|
}
|
|
|
|
def->nPortGroups++;
|
|
|
|
memset(&portgroup, 0, sizeof(portgroup));
|
|
|
|
|
|
|
|
} else if (command == VIR_NETWORK_UPDATE_COMMAND_DELETE) {
|
|
|
|
|
|
|
|
/* remove it */
|
2012-10-20 08:39:18 +00:00
|
|
|
virPortGroupDefClear(&def->portGroups[foundName]);
|
|
|
|
memmove(def->portGroups + foundName, def->portGroups + foundName + 1,
|
|
|
|
sizeof(*def->portGroups) * (def->nPortGroups - foundName - 1));
|
network: backend for virNetworkUpdate of portgroups
portgroup elements are located in the toplevel of <network>
objects. There can be multiple <portgroup> elements, and they each
have a unique name attribute.
Add, delete, and modify are all supported for portgroup. When deleting
a portgroup, only the name must be specified in the provided xml - all
other attributes and subelements are ignored for the purposes of
matching and existing portgroup.
The bridge driver and virsh already know about the portgroup element,
so providing this backend should cause the entire stack to work. Note
that in the case of portgroup, there is no external daemon based on
the portgroup config, so nothing must be restarted.
It is important to note that guests make a copy of the appropriate
network's portgroup data when they are started, so although an updated
portgroup's configuration will have an affect on new guests started
after the cahange, existing guests won't magically have their
bandwidth changed, for example. If something like that is desired, it
will take a lot of redesign work in the way network devices are setup
(there is currently no link from the network back to the individual
interfaces using it, much less from a portgroup within a network back
to the individual interfaces).
2012-09-21 02:25:41 +00:00
|
|
|
def->nPortGroups--;
|
|
|
|
ignore_value(VIR_REALLOC_N(def->portGroups, def->nPortGroups));
|
2012-09-21 16:11:51 +00:00
|
|
|
} else {
|
|
|
|
virNetworkDefUpdateUnknownCommand(command);
|
|
|
|
goto cleanup;
|
network: backend for virNetworkUpdate of portgroups
portgroup elements are located in the toplevel of <network>
objects. There can be multiple <portgroup> elements, and they each
have a unique name attribute.
Add, delete, and modify are all supported for portgroup. When deleting
a portgroup, only the name must be specified in the provided xml - all
other attributes and subelements are ignored for the purposes of
matching and existing portgroup.
The bridge driver and virsh already know about the portgroup element,
so providing this backend should cause the entire stack to work. Note
that in the case of portgroup, there is no external daemon based on
the portgroup config, so nothing must be restarted.
It is important to note that guests make a copy of the appropriate
network's portgroup data when they are started, so although an updated
portgroup's configuration will have an affect on new guests started
after the cahange, existing guests won't magically have their
bandwidth changed, for example. If something like that is desired, it
will take a lot of redesign work in the way network devices are setup
(there is currently no link from the network back to the individual
interfaces using it, much less from a portgroup within a network back
to the individual interfaces).
2012-09-21 02:25:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
cleanup:
|
|
|
|
virPortGroupDefClear(&portgroup);
|
|
|
|
return ret;
|
2012-09-14 19:14:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
virNetworkDefUpdateDNSHost(virNetworkDefPtr def,
|
|
|
|
unsigned int command ATTRIBUTE_UNUSED,
|
|
|
|
int parentIndex ATTRIBUTE_UNUSED,
|
|
|
|
xmlXPathContextPtr ctxt ATTRIBUTE_UNUSED,
|
|
|
|
/* virNetworkUpdateFlags */
|
|
|
|
unsigned int fflags ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
virNetworkDefUpdateNoSupport(def, "dns host");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
virNetworkDefUpdateDNSTxt(virNetworkDefPtr def,
|
|
|
|
unsigned int command ATTRIBUTE_UNUSED,
|
|
|
|
int parentIndex ATTRIBUTE_UNUSED,
|
|
|
|
xmlXPathContextPtr ctxt ATTRIBUTE_UNUSED,
|
|
|
|
/* virNetworkUpdateFlags */
|
|
|
|
unsigned int fflags ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
virNetworkDefUpdateNoSupport(def, "dns txt");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
virNetworkDefUpdateDNSSrv(virNetworkDefPtr def,
|
|
|
|
unsigned int command ATTRIBUTE_UNUSED,
|
|
|
|
int parentIndex ATTRIBUTE_UNUSED,
|
|
|
|
xmlXPathContextPtr ctxt ATTRIBUTE_UNUSED,
|
|
|
|
/* virNetworkUpdateFlags */
|
|
|
|
unsigned int fflags ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
virNetworkDefUpdateNoSupport(def, "dns txt");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
virNetworkDefUpdateSection(virNetworkDefPtr def,
|
|
|
|
unsigned int command, /* virNetworkUpdateCommand */
|
|
|
|
unsigned int section, /* virNetworkUpdateSection */
|
|
|
|
int parentIndex,
|
|
|
|
const char *xml,
|
|
|
|
unsigned int flags) /* virNetworkUpdateFlags */
|
|
|
|
{
|
|
|
|
int ret = -1;
|
|
|
|
xmlDocPtr doc;
|
|
|
|
xmlXPathContextPtr ctxt = NULL;
|
|
|
|
|
|
|
|
if (!(doc = virXMLParseStringCtxt(xml, _("network_update_xml"), &ctxt)))
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
switch (section) {
|
|
|
|
case VIR_NETWORK_SECTION_BRIDGE:
|
|
|
|
ret = virNetworkDefUpdateBridge(def, command, parentIndex, ctxt, flags);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_NETWORK_SECTION_DOMAIN:
|
|
|
|
ret = virNetworkDefUpdateDomain(def, command, parentIndex, ctxt, flags);
|
|
|
|
break;
|
|
|
|
case VIR_NETWORK_SECTION_IP:
|
|
|
|
ret = virNetworkDefUpdateIP(def, command, parentIndex, ctxt, flags);
|
|
|
|
break;
|
|
|
|
case VIR_NETWORK_SECTION_IP_DHCP_HOST:
|
|
|
|
ret = virNetworkDefUpdateIPDHCPHost(def, command,
|
|
|
|
parentIndex, ctxt, flags);
|
|
|
|
break;
|
|
|
|
case VIR_NETWORK_SECTION_IP_DHCP_RANGE:
|
|
|
|
ret = virNetworkDefUpdateIPDHCPRange(def, command,
|
|
|
|
parentIndex, ctxt, flags);
|
|
|
|
break;
|
|
|
|
case VIR_NETWORK_SECTION_FORWARD:
|
|
|
|
ret = virNetworkDefUpdateForward(def, command,
|
|
|
|
parentIndex, ctxt, flags);
|
|
|
|
break;
|
|
|
|
case VIR_NETWORK_SECTION_FORWARD_INTERFACE:
|
|
|
|
ret = virNetworkDefUpdateForwardInterface(def, command,
|
|
|
|
parentIndex, ctxt, flags);
|
|
|
|
break;
|
|
|
|
case VIR_NETWORK_SECTION_FORWARD_PF:
|
|
|
|
ret = virNetworkDefUpdateForwardPF(def, command,
|
|
|
|
parentIndex, ctxt, flags);
|
|
|
|
break;
|
|
|
|
case VIR_NETWORK_SECTION_PORTGROUP:
|
network: backend for virNetworkUpdate of portgroups
portgroup elements are located in the toplevel of <network>
objects. There can be multiple <portgroup> elements, and they each
have a unique name attribute.
Add, delete, and modify are all supported for portgroup. When deleting
a portgroup, only the name must be specified in the provided xml - all
other attributes and subelements are ignored for the purposes of
matching and existing portgroup.
The bridge driver and virsh already know about the portgroup element,
so providing this backend should cause the entire stack to work. Note
that in the case of portgroup, there is no external daemon based on
the portgroup config, so nothing must be restarted.
It is important to note that guests make a copy of the appropriate
network's portgroup data when they are started, so although an updated
portgroup's configuration will have an affect on new guests started
after the cahange, existing guests won't magically have their
bandwidth changed, for example. If something like that is desired, it
will take a lot of redesign work in the way network devices are setup
(there is currently no link from the network back to the individual
interfaces using it, much less from a portgroup within a network back
to the individual interfaces).
2012-09-21 02:25:41 +00:00
|
|
|
ret = virNetworkDefUpdatePortGroup(def, command,
|
2012-09-14 19:14:57 +00:00
|
|
|
parentIndex, ctxt, flags);
|
|
|
|
break;
|
|
|
|
case VIR_NETWORK_SECTION_DNS_HOST:
|
|
|
|
ret = virNetworkDefUpdateDNSHost(def, command,
|
|
|
|
parentIndex, ctxt, flags);
|
|
|
|
break;
|
|
|
|
case VIR_NETWORK_SECTION_DNS_TXT:
|
|
|
|
ret = virNetworkDefUpdateDNSTxt(def, command, parentIndex, ctxt, flags);
|
|
|
|
break;
|
|
|
|
case VIR_NETWORK_SECTION_DNS_SRV:
|
|
|
|
ret = virNetworkDefUpdateDNSSrv(def, command, parentIndex, ctxt, flags);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
virReportError(VIR_ERR_NO_SUPPORT, "%s",
|
|
|
|
_("can't update unrecognized section of network"));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
xmlFreeDoc(doc);
|
|
|
|
xmlXPathFreeContext(ctxt);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* virNetworkObjUpdate:
|
|
|
|
*
|
|
|
|
* Apply the supplied update to the given virNetworkObj. Except for
|
|
|
|
* @network pointing to an actual network object rather than the
|
|
|
|
* opaque virNetworkPtr, parameters are identical to the public API
|
|
|
|
* virNetworkUpdate.
|
|
|
|
*
|
|
|
|
* The original virNetworkDefs are copied, and all modifications made
|
|
|
|
* to these copies. The originals are replaced with the copies only
|
|
|
|
* after success has been guaranteed.
|
|
|
|
*
|
|
|
|
* Returns: -1 on error, 0 on success.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
virNetworkObjUpdate(virNetworkObjPtr network,
|
|
|
|
unsigned int command, /* virNetworkUpdateCommand */
|
|
|
|
unsigned int section, /* virNetworkUpdateSection */
|
|
|
|
int parentIndex,
|
|
|
|
const char *xml,
|
|
|
|
unsigned int flags) /* virNetworkUpdateFlags */
|
|
|
|
{
|
|
|
|
int ret = -1;
|
2012-09-21 18:48:17 +00:00
|
|
|
virNetworkDefPtr livedef = NULL, configdef = NULL;
|
2012-09-14 19:14:57 +00:00
|
|
|
|
|
|
|
/* normalize config data, and check for common invalid requests. */
|
|
|
|
if (virNetworkConfigChangeSetup(network, flags) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (flags & VIR_NETWORK_UPDATE_AFFECT_LIVE) {
|
2012-09-21 18:48:17 +00:00
|
|
|
virNetworkDefPtr checkdef;
|
|
|
|
|
2012-09-14 19:14:57 +00:00
|
|
|
/* work on a copy of the def */
|
2012-09-21 18:48:17 +00:00
|
|
|
if (!(livedef = virNetworkDefCopy(network->def, 0)))
|
2012-09-14 19:14:57 +00:00
|
|
|
goto cleanup;
|
2012-09-21 18:48:17 +00:00
|
|
|
if (virNetworkDefUpdateSection(livedef, command, section,
|
2012-09-14 19:14:57 +00:00
|
|
|
parentIndex, xml, flags) < 0) {
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2012-09-21 18:48:17 +00:00
|
|
|
/* run a final format/parse cycle to make sure we didn't
|
|
|
|
* add anything illegal to the def
|
|
|
|
*/
|
|
|
|
if (!(checkdef = virNetworkDefCopy(livedef, 0)))
|
|
|
|
goto cleanup;
|
|
|
|
virNetworkDefFree(checkdef);
|
2012-09-14 19:14:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (flags & VIR_NETWORK_UPDATE_AFFECT_CONFIG) {
|
2012-09-21 18:48:17 +00:00
|
|
|
virNetworkDefPtr checkdef;
|
|
|
|
|
2012-09-14 19:14:57 +00:00
|
|
|
/* work on a copy of the def */
|
2012-09-21 18:48:17 +00:00
|
|
|
if (!(configdef = virNetworkDefCopy(virNetworkObjGetPersistentDef(network),
|
|
|
|
VIR_NETWORK_XML_INACTIVE))) {
|
2012-09-14 19:14:57 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
2012-09-21 18:48:17 +00:00
|
|
|
if (virNetworkDefUpdateSection(configdef, command, section,
|
2012-09-14 19:14:57 +00:00
|
|
|
parentIndex, xml, flags) < 0) {
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2012-09-21 18:48:17 +00:00
|
|
|
if (!(checkdef = virNetworkDefCopy(configdef,
|
|
|
|
VIR_NETWORK_XML_INACTIVE))) {
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
virNetworkDefFree(checkdef);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (configdef) {
|
2012-09-14 19:14:57 +00:00
|
|
|
/* successfully modified copy, now replace original */
|
2012-09-21 18:48:17 +00:00
|
|
|
if (virNetworkObjReplacePersistentDef(network, configdef) < 0)
|
2012-09-14 19:14:57 +00:00
|
|
|
goto cleanup;
|
2012-09-21 18:48:17 +00:00
|
|
|
configdef = NULL;
|
|
|
|
}
|
|
|
|
if (livedef) {
|
|
|
|
/* successfully modified copy, now replace original */
|
|
|
|
virNetworkDefFree(network->def);
|
|
|
|
network->def = livedef;
|
|
|
|
livedef = NULL;
|
2012-09-14 19:14:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
cleanup:
|
2012-09-21 18:48:17 +00:00
|
|
|
virNetworkDefFree(livedef);
|
|
|
|
virNetworkDefFree(configdef);
|
2012-09-14 19:14:57 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2010-05-27 15:44:31 +00:00
|
|
|
/*
|
|
|
|
* virNetworkObjIsDuplicate:
|
|
|
|
* @doms : virNetworkObjListPtr to search
|
|
|
|
* @def : virNetworkDefPtr definition of network to lookup
|
|
|
|
* @check_active: If true, ensure that network is not active
|
|
|
|
*
|
|
|
|
* Returns: -1 on error
|
|
|
|
* 0 if network is new
|
|
|
|
* 1 if network is a duplicate
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
virNetworkObjIsDuplicate(virNetworkObjListPtr doms,
|
|
|
|
virNetworkDefPtr def,
|
|
|
|
unsigned int check_active)
|
|
|
|
{
|
|
|
|
int ret = -1;
|
|
|
|
int dupVM = 0;
|
|
|
|
virNetworkObjPtr vm = NULL;
|
|
|
|
|
|
|
|
/* See if a VM with matching UUID already exists */
|
|
|
|
vm = virNetworkFindByUUID(doms, def->uuid);
|
|
|
|
if (vm) {
|
|
|
|
/* UUID matches, but if names don't match, refuse it */
|
|
|
|
if (STRNEQ(vm->def->name, def->name)) {
|
|
|
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
|
|
|
virUUIDFormat(vm->def->uuid, uuidstr);
|
2012-07-18 10:50:44 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_FAILED,
|
|
|
|
_("network '%s' is already defined with uuid %s"),
|
|
|
|
vm->def->name, uuidstr);
|
2010-05-27 15:44:31 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (check_active) {
|
|
|
|
/* UUID & name match, but if VM is already active, refuse it */
|
|
|
|
if (virNetworkObjIsActive(vm)) {
|
2012-07-18 10:50:44 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
_("network is already active as '%s'"),
|
|
|
|
vm->def->name);
|
2010-05-27 15:44:31 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
dupVM = 1;
|
|
|
|
} else {
|
|
|
|
/* UUID does not match, but if a name matches, refuse it */
|
|
|
|
vm = virNetworkFindByName(doms, def->name);
|
|
|
|
if (vm) {
|
|
|
|
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
|
|
|
virUUIDFormat(vm->def->uuid, uuidstr);
|
2012-07-18 10:50:44 +00:00
|
|
|
virReportError(VIR_ERR_OPERATION_FAILED,
|
|
|
|
_("network '%s' already exists with uuid %s"),
|
|
|
|
def->name, uuidstr);
|
2010-05-27 15:44:31 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = dupVM;
|
|
|
|
cleanup:
|
|
|
|
if (vm)
|
|
|
|
virNetworkObjUnlock(vm);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-12-04 22:00:14 +00:00
|
|
|
void virNetworkObjLock(virNetworkObjPtr obj)
|
|
|
|
{
|
2009-01-15 19:56:05 +00:00
|
|
|
virMutexLock(&obj->lock);
|
2008-12-04 22:00:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void virNetworkObjUnlock(virNetworkObjPtr obj)
|
|
|
|
{
|
2009-01-15 19:56:05 +00:00
|
|
|
virMutexUnlock(&obj->lock);
|
2008-12-04 20:53:20 +00:00
|
|
|
}
|
2012-09-04 15:55:17 +00:00
|
|
|
|
|
|
|
#define MATCH(FLAG) (flags & (FLAG))
|
|
|
|
static bool
|
|
|
|
virNetworkMatch (virNetworkObjPtr netobj,
|
|
|
|
unsigned int flags)
|
|
|
|
{
|
|
|
|
/* filter by active state */
|
|
|
|
if (MATCH(VIR_CONNECT_LIST_NETWORKS_FILTERS_ACTIVE) &&
|
|
|
|
!((MATCH(VIR_CONNECT_LIST_NETWORKS_ACTIVE) &&
|
|
|
|
virNetworkObjIsActive(netobj)) ||
|
|
|
|
(MATCH(VIR_CONNECT_LIST_NETWORKS_INACTIVE) &&
|
|
|
|
!virNetworkObjIsActive(netobj))))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
/* filter by persistence */
|
|
|
|
if (MATCH(VIR_CONNECT_LIST_NETWORKS_FILTERS_PERSISTENT) &&
|
|
|
|
!((MATCH(VIR_CONNECT_LIST_NETWORKS_PERSISTENT) &&
|
|
|
|
netobj->persistent) ||
|
|
|
|
(MATCH(VIR_CONNECT_LIST_NETWORKS_TRANSIENT) &&
|
|
|
|
!netobj->persistent)))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
/* filter by autostart option */
|
|
|
|
if (MATCH(VIR_CONNECT_LIST_NETWORKS_FILTERS_AUTOSTART) &&
|
|
|
|
!((MATCH(VIR_CONNECT_LIST_NETWORKS_AUTOSTART) &&
|
|
|
|
netobj->autostart) ||
|
|
|
|
(MATCH(VIR_CONNECT_LIST_NETWORKS_NO_AUTOSTART) &&
|
|
|
|
!netobj->autostart)))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
#undef MATCH
|
|
|
|
|
|
|
|
int
|
|
|
|
virNetworkList(virConnectPtr conn,
|
|
|
|
virNetworkObjList netobjs,
|
|
|
|
virNetworkPtr **nets,
|
|
|
|
unsigned int flags)
|
|
|
|
{
|
|
|
|
virNetworkPtr *tmp_nets = NULL;
|
|
|
|
virNetworkPtr net = NULL;
|
|
|
|
int nnets = 0;
|
|
|
|
int ret = -1;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (nets) {
|
|
|
|
if (VIR_ALLOC_N(tmp_nets, netobjs.count + 1) < 0) {
|
|
|
|
virReportOOMError();
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < netobjs.count; i++) {
|
|
|
|
virNetworkObjPtr netobj = netobjs.objs[i];
|
|
|
|
virNetworkObjLock(netobj);
|
|
|
|
if (virNetworkMatch(netobj, flags)) {
|
|
|
|
if (nets) {
|
|
|
|
if (!(net = virGetNetwork(conn,
|
|
|
|
netobj->def->name,
|
|
|
|
netobj->def->uuid))) {
|
|
|
|
virNetworkObjUnlock(netobj);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
tmp_nets[nnets] = net;
|
|
|
|
}
|
|
|
|
nnets++;
|
|
|
|
}
|
|
|
|
virNetworkObjUnlock(netobj);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (tmp_nets) {
|
|
|
|
/* trim the array to the final size */
|
|
|
|
ignore_value(VIR_REALLOC_N(tmp_nets, nnets + 1));
|
|
|
|
*nets = tmp_nets;
|
|
|
|
tmp_nets = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = nnets;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (tmp_nets) {
|
|
|
|
for (i = 0; i < nnets; i++) {
|
|
|
|
if (tmp_nets[i])
|
|
|
|
virNetworkFree(tmp_nets[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
VIR_FREE(tmp_nets);
|
|
|
|
return ret;
|
|
|
|
}
|