mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-10-30 01:43:23 +00:00
Add bridged network to openvz driver & add some openvz docs
This commit is contained in:
parent
48f32d8033
commit
bfdac58c36
@ -1,3 +1,10 @@
|
|||||||
|
Wed Nov 12 16:33:42 GMT 2008 Daniel P. Berrange <berrange@redhat.com>
|
||||||
|
|
||||||
|
* docs/drvopenvz.html, docs/drvopenvz.html.in: Introductory
|
||||||
|
docs for openvz driver
|
||||||
|
* src/openvz_conf.c, src/openvz_conf.h, src/openvz_driver.c:
|
||||||
|
Support bridged network configuration for containers
|
||||||
|
|
||||||
Wed Nov 12 16:13:42 GMT 2008 Daniel P. Berrange <berrange@redhat.com>
|
Wed Nov 12 16:13:42 GMT 2008 Daniel P. Berrange <berrange@redhat.com>
|
||||||
|
|
||||||
* src/storage_backend.c, src/storage_backend.h, src/storage_driver.c:
|
* src/storage_backend.c, src/storage_backend.h, src/storage_driver.c:
|
||||||
|
@ -122,6 +122,93 @@
|
|||||||
</div>
|
</div>
|
||||||
<div id="content">
|
<div id="content">
|
||||||
<h1>OpenVZ container driver</h1>
|
<h1>OpenVZ container driver</h1>
|
||||||
|
<p>
|
||||||
|
The OpenVZ driver for libvirt allows use and management of container
|
||||||
|
based virtualization on a Linux host OS. Prior to using the OpenVZ
|
||||||
|
driver, the OpenVZ enabled kernel must be installed & booted, and the
|
||||||
|
OpenVZ userspace tools installed. The libvirt driver has been tested
|
||||||
|
with OpenVZ 3.0.22, but other 3.0.x versions should also work without
|
||||||
|
undue trouble.
|
||||||
|
</p>
|
||||||
|
<h2>Connections to OpenVZ driver</h2>
|
||||||
|
<p>
|
||||||
|
The libvirt OpenVZ driver is a single-instance privileged driver,
|
||||||
|
with a driver name of 'openvz'. Some example conection URIs for
|
||||||
|
the libvirt driver are:
|
||||||
|
</p>
|
||||||
|
<pre>
|
||||||
|
openvz:///system (local access)
|
||||||
|
openvz://example.com/system (remote access, TLS/x509)
|
||||||
|
openvz+tcp://example.com/system (remote access, SASl/Kerberos)
|
||||||
|
openvz+ssh://root@example.com/system (remote access, SSH tunnelled)
|
||||||
|
</pre>
|
||||||
|
<h2>Notes on bridged networking</h2>
|
||||||
|
<p>
|
||||||
|
Bridged networking enables a guest domain (ie container) to have its
|
||||||
|
network interface connected directly to the host's physical LAN. Before
|
||||||
|
this can be used there are a couple of configuration pre-requisites for
|
||||||
|
the host OS.
|
||||||
|
</p>
|
||||||
|
<h3>Host network devices</h3>
|
||||||
|
<p>
|
||||||
|
One or more of the physical devices must be attached to a bridge. The
|
||||||
|
process for this varies according to the operating system in use, so
|
||||||
|
for up to date notes consult the <a href="http://wiki.libvirt.org">Wiki</a>
|
||||||
|
or your operating system's networking documentation. The basic idea is
|
||||||
|
that the host OS should end up with a bridge device "br0" containing a
|
||||||
|
physical device "eth0", or a bonding device "bond0".
|
||||||
|
</p>
|
||||||
|
<h3>OpenVZ tools configuration</h3>
|
||||||
|
<p>
|
||||||
|
OpenVZ releases later than 3.0.23 ship with a standard network device
|
||||||
|
setup script that is able to setup bridging, named
|
||||||
|
<code>/usr/sbin/vznetaddbr</code>. For releases prior to 3.0.23, this
|
||||||
|
script must be created manually by the host OS adminstrator. The
|
||||||
|
simplest way is to just download the latest version of this script
|
||||||
|
from a newer OpenVZ release, or upstream source repository. Then
|
||||||
|
a generic configuration file <code>/etc/vz/vznetctl.conf</code>
|
||||||
|
must be created containing
|
||||||
|
</p>
|
||||||
|
<pre>
|
||||||
|
#!/bin/bash
|
||||||
|
EXTERNAL_SCRIPT="/usr/sbin/vznetaddbr"
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
The host OS is now ready to allow bridging of guest containers, which
|
||||||
|
will work whether the container is started with libvirt, or OpenVZ
|
||||||
|
tools.
|
||||||
|
</p>
|
||||||
|
<h2>Example guest domain XML configuration</h2>
|
||||||
|
<p>
|
||||||
|
The current libvirt OpenVZ driver has a restriction that the
|
||||||
|
domain names must match the OpenVZ container VEID, which by
|
||||||
|
convention start at 100, and are incremented from there. The
|
||||||
|
choice of OS template to use inside the container is determined
|
||||||
|
by the <code>filesystem</code> tag, and the template source name
|
||||||
|
matches the templates known to OpenVZ tools.
|
||||||
|
</p>
|
||||||
|
<pre>
|
||||||
|
<domain type='openvz' id='104'>
|
||||||
|
<name>104</name>
|
||||||
|
<uuid>86c12009-e591-a159-6e9f-91d18b85ef78</uuid>
|
||||||
|
<vcpu>3</vcpu>
|
||||||
|
<os>
|
||||||
|
<type>exe</type>
|
||||||
|
<init>/sbin/init</init>
|
||||||
|
</os>
|
||||||
|
<devices>
|
||||||
|
<filesystem type='template'>
|
||||||
|
<source name='fedora-9-i386-minimal'/>
|
||||||
|
<target dir='/'/>
|
||||||
|
</filesystem>
|
||||||
|
<interface type='bridge'>
|
||||||
|
<mac address='00:18:51:5b:ea:bf'/>
|
||||||
|
<source bridge='br0'/>
|
||||||
|
<target dev='veth101.0'/>
|
||||||
|
</interface>
|
||||||
|
</devices>
|
||||||
|
</domain>
|
||||||
|
</pre>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="footer">
|
<div id="footer">
|
||||||
|
@ -1,5 +1,109 @@
|
|||||||
<html>
|
<html> <!-- -*- html -*- -->
|
||||||
<body>
|
<body>
|
||||||
<h1>OpenVZ container driver</h1>
|
<h1>OpenVZ container driver</h1>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The OpenVZ driver for libvirt allows use and management of container
|
||||||
|
based virtualization on a Linux host OS. Prior to using the OpenVZ
|
||||||
|
driver, the OpenVZ enabled kernel must be installed & booted, and the
|
||||||
|
OpenVZ userspace tools installed. The libvirt driver has been tested
|
||||||
|
with OpenVZ 3.0.22, but other 3.0.x versions should also work without
|
||||||
|
undue trouble.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2>Connections to OpenVZ driver</h2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The libvirt OpenVZ driver is a single-instance privileged driver,
|
||||||
|
with a driver name of 'openvz'. Some example conection URIs for
|
||||||
|
the libvirt driver are:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
openvz:///system (local access)
|
||||||
|
openvz://example.com/system (remote access, TLS/x509)
|
||||||
|
openvz+tcp://example.com/system (remote access, SASl/Kerberos)
|
||||||
|
openvz+ssh://root@example.com/system (remote access, SSH tunnelled)
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<h2>Notes on bridged networking</h2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Bridged networking enables a guest domain (ie container) to have its
|
||||||
|
network interface connected directly to the host's physical LAN. Before
|
||||||
|
this can be used there are a couple of configuration pre-requisites for
|
||||||
|
the host OS.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3>Host network devices</h3>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
One or more of the physical devices must be attached to a bridge. The
|
||||||
|
process for this varies according to the operating system in use, so
|
||||||
|
for up to date notes consult the <a href="http://wiki.libvirt.org">Wiki</a>
|
||||||
|
or your operating system's networking documentation. The basic idea is
|
||||||
|
that the host OS should end up with a bridge device "br0" containing a
|
||||||
|
physical device "eth0", or a bonding device "bond0".
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3>OpenVZ tools configuration</h3>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
OpenVZ releases later than 3.0.23 ship with a standard network device
|
||||||
|
setup script that is able to setup bridging, named
|
||||||
|
<code>/usr/sbin/vznetaddbr</code>. For releases prior to 3.0.23, this
|
||||||
|
script must be created manually by the host OS adminstrator. The
|
||||||
|
simplest way is to just download the latest version of this script
|
||||||
|
from a newer OpenVZ release, or upstream source repository. Then
|
||||||
|
a generic configuration file <code>/etc/vz/vznetctl.conf</code>
|
||||||
|
must be created containing
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
#!/bin/bash
|
||||||
|
EXTERNAL_SCRIPT="/usr/sbin/vznetaddbr"
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The host OS is now ready to allow bridging of guest containers, which
|
||||||
|
will work whether the container is started with libvirt, or OpenVZ
|
||||||
|
tools.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
<h2>Example guest domain XML configuration</h2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The current libvirt OpenVZ driver has a restriction that the
|
||||||
|
domain names must match the OpenVZ container VEID, which by
|
||||||
|
convention start at 100, and are incremented from there. The
|
||||||
|
choice of OS template to use inside the container is determined
|
||||||
|
by the <code>filesystem</code> tag, and the template source name
|
||||||
|
matches the templates known to OpenVZ tools.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
<domain type='openvz' id='104'>
|
||||||
|
<name>104</name>
|
||||||
|
<uuid>86c12009-e591-a159-6e9f-91d18b85ef78</uuid>
|
||||||
|
<vcpu>3</vcpu>
|
||||||
|
<os>
|
||||||
|
<type>exe</type>
|
||||||
|
<init>/sbin/init</init>
|
||||||
|
</os>
|
||||||
|
<devices>
|
||||||
|
<filesystem type='template'>
|
||||||
|
<source name='fedora-9-i386-minimal'/>
|
||||||
|
<target dir='/'/>
|
||||||
|
</filesystem>
|
||||||
|
<interface type='bridge'>
|
||||||
|
<mac address='00:18:51:5b:ea:bf'/>
|
||||||
|
<source bridge='br0'/>
|
||||||
|
<target dev='veth101.0'/>
|
||||||
|
</interface>
|
||||||
|
</devices>
|
||||||
|
</domain>
|
||||||
|
</pre>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@ -52,7 +52,7 @@
|
|||||||
|
|
||||||
static char *openvzLocateConfDir(void);
|
static char *openvzLocateConfDir(void);
|
||||||
static int openvzGetVPSUUID(int vpsid, char *uuidstr);
|
static int openvzGetVPSUUID(int vpsid, char *uuidstr);
|
||||||
static int openvzLocateConfFile(int vpsid, char *conffile, int maxlen);
|
static int openvzLocateConfFile(int vpsid, char *conffile, int maxlen, const char *ext);
|
||||||
static int openvzAssignUUIDs(void);
|
static int openvzAssignUUIDs(void);
|
||||||
|
|
||||||
int
|
int
|
||||||
@ -145,6 +145,8 @@ virCapsPtr openvzCapsInit(void)
|
|||||||
0, 0)) == NULL)
|
0, 0)) == NULL)
|
||||||
goto no_memory;
|
goto no_memory;
|
||||||
|
|
||||||
|
virCapabilitiesSetMacPrefix(caps, (unsigned char[]){ 0x52, 0x54, 0x00 });
|
||||||
|
|
||||||
if ((guest = virCapabilitiesAddGuest(caps,
|
if ((guest = virCapabilitiesAddGuest(caps,
|
||||||
"exe",
|
"exe",
|
||||||
utsname.machine,
|
utsname.machine,
|
||||||
@ -170,54 +172,6 @@ no_memory:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* function checks MAC address is empty
|
|
||||||
return 0 - empty
|
|
||||||
1 - not
|
|
||||||
*/
|
|
||||||
int openvzCheckEmptyMac(const unsigned char *mac)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
for (i = 0; i < VIR_MAC_BUFLEN; i++)
|
|
||||||
if (mac[i] != 0x00)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* convert mac address to string
|
|
||||||
return pointer to string or NULL
|
|
||||||
*/
|
|
||||||
char *openvzMacToString(const unsigned char *mac)
|
|
||||||
{
|
|
||||||
char str[20];
|
|
||||||
if (snprintf(str, 18, "%02X:%02X:%02X:%02X:%02X:%02X",
|
|
||||||
mac[0], mac[1], mac[2],
|
|
||||||
mac[3], mac[4], mac[5]) >= 18)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
return strdup(str);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*parse MAC from view: 00:18:51:8F:D9:F3
|
|
||||||
return -1 - error
|
|
||||||
0 - OK
|
|
||||||
*/
|
|
||||||
static int openvzParseMac(const char *macaddr, unsigned char *mac)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
ret = sscanf((const char *)macaddr, "%02X:%02X:%02X:%02X:%02X:%02X",
|
|
||||||
(unsigned int*)&mac[0],
|
|
||||||
(unsigned int*)&mac[1],
|
|
||||||
(unsigned int*)&mac[2],
|
|
||||||
(unsigned int*)&mac[3],
|
|
||||||
(unsigned int*)&mac[4],
|
|
||||||
(unsigned int*)&mac[5]) ;
|
|
||||||
if (ret == 6)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
openvzReadNetworkConf(virConnectPtr conn,
|
openvzReadNetworkConf(virConnectPtr conn,
|
||||||
virDomainDefPtr def,
|
virDomainDefPtr def,
|
||||||
@ -288,6 +242,9 @@ openvzReadNetworkConf(virConnectPtr conn,
|
|||||||
while (*next != '\0' && *next != ',') next++;
|
while (*next != '\0' && *next != ',') next++;
|
||||||
if (STRPREFIX(p, "ifname=")) {
|
if (STRPREFIX(p, "ifname=")) {
|
||||||
p += 7;
|
p += 7;
|
||||||
|
/* skip in libvirt */
|
||||||
|
} else if (STRPREFIX(p, "host_ifname=")) {
|
||||||
|
p += 12;
|
||||||
len = next - p;
|
len = next - p;
|
||||||
if (len > 16) {
|
if (len > 16) {
|
||||||
openvzError(conn, VIR_ERR_INTERNAL_ERROR,
|
openvzError(conn, VIR_ERR_INTERNAL_ERROR,
|
||||||
@ -295,14 +252,25 @@ openvzReadNetworkConf(virConnectPtr conn,
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (VIR_ALLOC_N(net->ifname, len+1) < 0)
|
||||||
|
goto no_memory;
|
||||||
|
|
||||||
|
strncpy(net->ifname, p, len);
|
||||||
|
net->ifname[len] = '\0';
|
||||||
|
} else if (STRPREFIX(p, "bridge=")) {
|
||||||
|
p += 7;
|
||||||
|
len = next - p;
|
||||||
|
if (len > 16) {
|
||||||
|
openvzError(conn, VIR_ERR_INTERNAL_ERROR,
|
||||||
|
"%s", _("Too long bridge device name"));
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
if (VIR_ALLOC_N(net->data.bridge.brname, len+1) < 0)
|
if (VIR_ALLOC_N(net->data.bridge.brname, len+1) < 0)
|
||||||
goto no_memory;
|
goto no_memory;
|
||||||
|
|
||||||
strncpy(net->data.bridge.brname, p, len);
|
strncpy(net->data.bridge.brname, p, len);
|
||||||
net->data.bridge.brname[len] = '\0';
|
net->data.bridge.brname[len] = '\0';
|
||||||
} else if (STRPREFIX(p, "host_ifname=")) {
|
|
||||||
p += 12;
|
|
||||||
//skip in libvirt
|
|
||||||
} else if (STRPREFIX(p, "mac=")) {
|
} else if (STRPREFIX(p, "mac=")) {
|
||||||
p += 4;
|
p += 4;
|
||||||
len = next - p;
|
len = next - p;
|
||||||
@ -313,14 +281,11 @@ openvzReadNetworkConf(virConnectPtr conn,
|
|||||||
}
|
}
|
||||||
strncpy(cpy_temp, p, len);
|
strncpy(cpy_temp, p, len);
|
||||||
cpy_temp[len] = '\0';
|
cpy_temp[len] = '\0';
|
||||||
if (openvzParseMac(cpy_temp, net->mac)<0) {
|
if (virParseMacAddr(cpy_temp, net->mac) < 0) {
|
||||||
openvzError(conn, VIR_ERR_INTERNAL_ERROR,
|
openvzError(conn, VIR_ERR_INTERNAL_ERROR,
|
||||||
"%s", _("Wrong MAC address"));
|
"%s", _("Wrong MAC address"));
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
} else if (STRPREFIX(p, "host_mac=")) {
|
|
||||||
p += 9;
|
|
||||||
//skip in libvirt
|
|
||||||
}
|
}
|
||||||
p = ++next;
|
p = ++next;
|
||||||
} while (p < token + strlen(token));
|
} while (p < token + strlen(token));
|
||||||
@ -492,6 +457,68 @@ int openvzLoadDomains(struct openvz_driver *driver) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
openvzWriteConfigParam(int vpsid, const char *param, const char *value)
|
||||||
|
{
|
||||||
|
char conf_file[PATH_MAX];
|
||||||
|
char temp_file[PATH_MAX];
|
||||||
|
char line[PATH_MAX] ;
|
||||||
|
int fd, temp_fd;
|
||||||
|
|
||||||
|
if (openvzLocateConfFile(vpsid, conf_file, PATH_MAX, "conf")<0)
|
||||||
|
return -1;
|
||||||
|
if (openvzLocateConfFile(vpsid, temp_file, PATH_MAX, "tmp")<0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
fd = open(conf_file, O_RDONLY);
|
||||||
|
if (fd == -1)
|
||||||
|
return -1;
|
||||||
|
temp_fd = open(temp_file, O_WRONLY | O_CREAT | O_TRUNC, 0644);
|
||||||
|
if (temp_fd == -1) {
|
||||||
|
close(fd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
while(1) {
|
||||||
|
if (openvz_readline(fd, line, sizeof(line)) <= 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (!STRPREFIX(line, param) &&
|
||||||
|
line[strlen(param)] == '=') {
|
||||||
|
if (safewrite(temp_fd, line, strlen(line)) !=
|
||||||
|
strlen(line))
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (safewrite(temp_fd, param, strlen(param)) < 0 ||
|
||||||
|
safewrite(temp_fd, "=\"", 2) < 0 ||
|
||||||
|
safewrite(temp_fd, value, strlen(value)) < 0 ||
|
||||||
|
safewrite(temp_fd, "\"\n", 2) < 0)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
if (close(fd) < 0)
|
||||||
|
goto error;
|
||||||
|
fd = -1;
|
||||||
|
if (close(temp_fd) < 0)
|
||||||
|
goto error;
|
||||||
|
temp_fd = -1;
|
||||||
|
|
||||||
|
if (rename(temp_file, conf_file) < 0)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
error:
|
||||||
|
if (fd != -1)
|
||||||
|
close(fd);
|
||||||
|
if (temp_fd != -1)
|
||||||
|
close(temp_fd);
|
||||||
|
unlink(temp_file);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Read parameter from container config
|
* Read parameter from container config
|
||||||
* sample: 133, "OSTEMPLATE", value, 1024
|
* sample: 133, "OSTEMPLATE", value, 1024
|
||||||
@ -509,7 +536,7 @@ openvzReadConfigParam(int vpsid ,const char * param, char *value, int maxlen)
|
|||||||
char * sf, * token;
|
char * sf, * token;
|
||||||
char *saveptr = NULL;
|
char *saveptr = NULL;
|
||||||
|
|
||||||
if (openvzLocateConfFile(vpsid, conf_file, PATH_MAX)<0)
|
if (openvzLocateConfFile(vpsid, conf_file, PATH_MAX, "conf")<0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
value[0] = 0;
|
value[0] = 0;
|
||||||
@ -549,7 +576,7 @@ openvzReadConfigParam(int vpsid ,const char * param, char *value, int maxlen)
|
|||||||
* 0 - OK
|
* 0 - OK
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
openvzLocateConfFile(int vpsid, char *conffile, int maxlen)
|
openvzLocateConfFile(int vpsid, char *conffile, int maxlen, const char *ext)
|
||||||
{
|
{
|
||||||
char * confdir;
|
char * confdir;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
@ -558,7 +585,8 @@ openvzLocateConfFile(int vpsid, char *conffile, int maxlen)
|
|||||||
if (confdir == NULL)
|
if (confdir == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (snprintf(conffile, maxlen, "%s/%d.conf", confdir, vpsid) >= maxlen)
|
if (snprintf(conffile, maxlen, "%s/%d.%s",
|
||||||
|
confdir, vpsid, ext ? ext : "conf") >= maxlen)
|
||||||
ret = -1;
|
ret = -1;
|
||||||
|
|
||||||
VIR_FREE(confdir);
|
VIR_FREE(confdir);
|
||||||
@ -615,7 +643,7 @@ openvzGetVPSUUID(int vpsid, char *uuidstr)
|
|||||||
char iden[1024];
|
char iden[1024];
|
||||||
int fd, ret;
|
int fd, ret;
|
||||||
|
|
||||||
if (openvzLocateConfFile(vpsid, conf_file, PATH_MAX)<0)
|
if (openvzLocateConfFile(vpsid, conf_file, PATH_MAX, "conf")<0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
fd = open(conf_file, O_RDONLY);
|
fd = open(conf_file, O_RDONLY);
|
||||||
@ -655,7 +683,7 @@ openvzSetDefinedUUID(int vpsid, unsigned char *uuid)
|
|||||||
if (uuid == NULL)
|
if (uuid == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (openvzLocateConfFile(vpsid, conf_file, PATH_MAX)<0)
|
if (openvzLocateConfFile(vpsid, conf_file, PATH_MAX, "conf")<0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (openvzGetVPSUUID(vpsid, uuidstr))
|
if (openvzGetVPSUUID(vpsid, uuidstr))
|
||||||
@ -723,4 +751,3 @@ static int openvzAssignUUIDs(void)
|
|||||||
VIR_FREE(conf_dir);
|
VIR_FREE(conf_dir);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,6 +50,8 @@ enum { OPENVZ_WARN, OPENVZ_ERR };
|
|||||||
#define VZLIST "/usr/sbin/vzlist"
|
#define VZLIST "/usr/sbin/vzlist"
|
||||||
#define VZCTL "/usr/sbin/vzctl"
|
#define VZCTL "/usr/sbin/vzctl"
|
||||||
|
|
||||||
|
#define VZCTL_BRIDGE_MIN_VERSION ((3 * 1000 * 1000) + (0 * 1000) + 22 + 1)
|
||||||
|
|
||||||
struct openvz_driver {
|
struct openvz_driver {
|
||||||
virCapsPtr caps;
|
virCapsPtr caps;
|
||||||
virDomainObjList domains;
|
virDomainObjList domains;
|
||||||
@ -60,12 +62,11 @@ int openvz_readline(int fd, char *ptr, int maxlen);
|
|||||||
int openvzExtractVersion(virConnectPtr conn,
|
int openvzExtractVersion(virConnectPtr conn,
|
||||||
struct openvz_driver *driver);
|
struct openvz_driver *driver);
|
||||||
int openvzReadConfigParam(int vpsid ,const char * param, char *value, int maxlen);
|
int openvzReadConfigParam(int vpsid ,const char * param, char *value, int maxlen);
|
||||||
|
int openvzWriteConfigParam(int vpsid, const char *param, const char *value);
|
||||||
virCapsPtr openvzCapsInit(void);
|
virCapsPtr openvzCapsInit(void);
|
||||||
int openvzLoadDomains(struct openvz_driver *driver);
|
int openvzLoadDomains(struct openvz_driver *driver);
|
||||||
void openvzFreeDriver(struct openvz_driver *driver);
|
void openvzFreeDriver(struct openvz_driver *driver);
|
||||||
int strtoI(const char *str);
|
int strtoI(const char *str);
|
||||||
int openvzCheckEmptyMac(const unsigned char *mac);
|
|
||||||
char *openvzMacToString(const unsigned char *mac);
|
|
||||||
int openvzSetDefinedUUID(int vpsid, unsigned char *uuid);
|
int openvzSetDefinedUUID(int vpsid, unsigned char *uuid);
|
||||||
|
|
||||||
#endif /* OPENVZ_CONF_H */
|
#endif /* OPENVZ_CONF_H */
|
||||||
|
@ -56,6 +56,7 @@
|
|||||||
#include "openvz_conf.h"
|
#include "openvz_conf.h"
|
||||||
#include "nodeinfo.h"
|
#include "nodeinfo.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
|
#include "bridge.h"
|
||||||
|
|
||||||
#define OPENVZ_MAX_ARG 28
|
#define OPENVZ_MAX_ARG 28
|
||||||
#define CMDBUF_LEN 1488
|
#define CMDBUF_LEN 1488
|
||||||
@ -330,13 +331,56 @@ static int openvzDomainReboot(virDomainPtr dom,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char *
|
||||||
|
openvzGenerateVethName(int veid, char *dev_name_ve)
|
||||||
|
{
|
||||||
|
char dev_name[32];
|
||||||
|
int ifNo = 0;
|
||||||
|
|
||||||
|
if (sscanf(dev_name_ve, "%*[^0-9]%d", &ifNo) != 1)
|
||||||
|
return NULL;
|
||||||
|
if (snprintf(dev_name, sizeof(dev_name), "veth%d.%d", veid, ifNo) < 7)
|
||||||
|
return NULL;
|
||||||
|
return strdup(dev_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *
|
||||||
|
openvzGenerateContainerVethName(int veid)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
char temp[1024];
|
||||||
|
|
||||||
|
/* try to get line "^NETIF=..." from config */
|
||||||
|
if ( (ret = openvzReadConfigParam(veid, "NETIF", temp, sizeof(temp))) <= 0) {
|
||||||
|
snprintf(temp, sizeof(temp), "eth0");
|
||||||
|
} else {
|
||||||
|
char *s;
|
||||||
|
int max = 0;
|
||||||
|
|
||||||
|
/* get maximum interface number (actually, it is the last one) */
|
||||||
|
for (s=strtok(temp, ";"); s; s=strtok(NULL, ";")) {
|
||||||
|
int x;
|
||||||
|
|
||||||
|
if (sscanf(s, "ifname=eth%d", &x) != 1) return NULL;
|
||||||
|
if (x > max) max = x;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set new name */
|
||||||
|
snprintf(temp, sizeof(temp), "eth%d", max+1);
|
||||||
|
}
|
||||||
|
return strdup(temp);
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
openvzDomainSetNetwork(virConnectPtr conn, const char *vpsid,
|
openvzDomainSetNetwork(virConnectPtr conn, const char *vpsid,
|
||||||
virDomainNetDefPtr net)
|
virDomainNetDefPtr net,
|
||||||
|
virBufferPtr configBuf)
|
||||||
{
|
{
|
||||||
int rc = 0, narg;
|
int rc = 0, narg;
|
||||||
const char *prog[OPENVZ_MAX_ARG];
|
const char *prog[OPENVZ_MAX_ARG];
|
||||||
char *mac = NULL;
|
char macaddr[VIR_MAC_STRING_BUFLEN];
|
||||||
|
struct openvz_driver *driver = (struct openvz_driver *) conn->privateData;
|
||||||
|
char *opt = NULL;
|
||||||
|
|
||||||
#define ADD_ARG_LIT(thisarg) \
|
#define ADD_ARG_LIT(thisarg) \
|
||||||
do { \
|
do { \
|
||||||
@ -368,21 +412,61 @@ openvzDomainSetNetwork(virConnectPtr conn, const char *vpsid,
|
|||||||
ADD_ARG_LIT(vpsid);
|
ADD_ARG_LIT(vpsid);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (openvzCheckEmptyMac(net->mac) > 0)
|
virFormatMacAddr(net->mac, macaddr);
|
||||||
mac = openvzMacToString(net->mac);
|
|
||||||
|
if (net->type == VIR_DOMAIN_NET_TYPE_BRIDGE) {
|
||||||
|
virBuffer buf = VIR_BUFFER_INITIALIZER;
|
||||||
|
char *dev_name_ve;
|
||||||
|
int veid = strtoI(vpsid);
|
||||||
|
|
||||||
if (net->type == VIR_DOMAIN_NET_TYPE_BRIDGE &&
|
|
||||||
net->data.bridge.brname != NULL) {
|
|
||||||
char opt[1024];
|
|
||||||
//--netif_add ifname[,mac,host_ifname,host_mac]
|
//--netif_add ifname[,mac,host_ifname,host_mac]
|
||||||
ADD_ARG_LIT("--netif_add") ;
|
ADD_ARG_LIT("--netif_add") ;
|
||||||
strncpy(opt, net->data.bridge.brname, 256);
|
|
||||||
if (mac != NULL) {
|
/* generate interface name in ve and copy it to options */
|
||||||
strcat(opt, ",");
|
dev_name_ve = openvzGenerateContainerVethName(veid);
|
||||||
strcat(opt, mac);
|
if (dev_name_ve == NULL) {
|
||||||
|
openvzError(conn, VIR_ERR_INTERNAL_ERROR,
|
||||||
|
_("Could not generate eth name for container"));
|
||||||
|
rc = -1;
|
||||||
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* if user doesn't specified host interface name,
|
||||||
|
* than we need to generate it */
|
||||||
|
if (net->ifname == NULL) {
|
||||||
|
net->ifname = openvzGenerateVethName(veid, dev_name_ve);
|
||||||
|
if (net->ifname == NULL) {
|
||||||
|
openvzError(conn, VIR_ERR_INTERNAL_ERROR,
|
||||||
|
_("Could not generate veth name"));
|
||||||
|
rc = -1;
|
||||||
|
VIR_FREE(dev_name_ve);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virBufferAdd(&buf, dev_name_ve, -1); /* Guest dev */
|
||||||
|
virBufferVSprintf(&buf, ",%s", macaddr); /* Guest dev mac */
|
||||||
|
virBufferVSprintf(&buf, ",%s", net->ifname); /* Host dev */
|
||||||
|
virBufferVSprintf(&buf, ",%s", macaddr); /* Host dev mac */
|
||||||
|
|
||||||
|
if (driver->version >= VZCTL_BRIDGE_MIN_VERSION) {
|
||||||
|
virBufferVSprintf(&buf, ",%s", net->data.bridge.brname); /* Host bridge */
|
||||||
|
} else {
|
||||||
|
virBufferVSprintf(configBuf, "ifname=%s", dev_name_ve);
|
||||||
|
virBufferVSprintf(configBuf, ",mac=%s", macaddr); /* Guest dev mac */
|
||||||
|
virBufferVSprintf(configBuf, ",host_ifname=%s", net->ifname); /* Host dev */
|
||||||
|
virBufferVSprintf(configBuf, ",host_mac=%s", macaddr); /* Host dev mac */
|
||||||
|
virBufferVSprintf(configBuf, ",bridge=%s", net->data.bridge.brname); /* Host bridge */
|
||||||
|
}
|
||||||
|
|
||||||
|
VIR_FREE(dev_name_ve);
|
||||||
|
|
||||||
|
if (!(opt = virBufferContentAndReset(&buf)))
|
||||||
|
goto no_memory;
|
||||||
|
|
||||||
ADD_ARG_LIT(opt) ;
|
ADD_ARG_LIT(opt) ;
|
||||||
}else if (net->type == VIR_DOMAIN_NET_TYPE_ETHERNET &&
|
VIR_FREE(opt);
|
||||||
|
} else if (net->type == VIR_DOMAIN_NET_TYPE_ETHERNET &&
|
||||||
net->data.ethernet.ipaddr != NULL) {
|
net->data.ethernet.ipaddr != NULL) {
|
||||||
//--ipadd ip
|
//--ipadd ip
|
||||||
ADD_ARG_LIT("--ipadd") ;
|
ADD_ARG_LIT("--ipadd") ;
|
||||||
@ -403,19 +487,67 @@ openvzDomainSetNetwork(virConnectPtr conn, const char *vpsid,
|
|||||||
|
|
||||||
exit:
|
exit:
|
||||||
cmdExecFree(prog);
|
cmdExecFree(prog);
|
||||||
VIR_FREE(mac);
|
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
no_memory:
|
no_memory:
|
||||||
|
VIR_FREE(opt);
|
||||||
openvzError(conn, VIR_ERR_INTERNAL_ERROR,
|
openvzError(conn, VIR_ERR_INTERNAL_ERROR,
|
||||||
_("Could not put argument to %s"), VZCTL);
|
_("Could not put argument to %s"), VZCTL);
|
||||||
cmdExecFree(prog);
|
cmdExecFree(prog);
|
||||||
VIR_FREE(mac);
|
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
#undef ADD_ARG_LIT
|
#undef ADD_ARG_LIT
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
openvzDomainSetNetworkConfig(virConnectPtr conn,
|
||||||
|
virDomainDefPtr def)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
virBuffer buf = VIR_BUFFER_INITIALIZER;
|
||||||
|
char *param;
|
||||||
|
int first = 1;
|
||||||
|
struct openvz_driver *driver = (struct openvz_driver *) conn->privateData;
|
||||||
|
|
||||||
|
for (i = 0 ; i < def->nnets ; i++) {
|
||||||
|
if (driver->version < VZCTL_BRIDGE_MIN_VERSION &&
|
||||||
|
def->nets[i]->type == VIR_DOMAIN_NET_TYPE_BRIDGE) {
|
||||||
|
if (first)
|
||||||
|
first = 0;
|
||||||
|
else
|
||||||
|
virBufferAddLit(&buf, ";");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (openvzDomainSetNetwork(conn, def->name, def->nets[i], &buf) < 0) {
|
||||||
|
openvzError(conn, VIR_ERR_INTERNAL_ERROR,
|
||||||
|
"%s", _("Could not configure network"));
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (driver->version < VZCTL_BRIDGE_MIN_VERSION && def->nnets) {
|
||||||
|
param = virBufferContentAndReset(&buf);
|
||||||
|
if (param) {
|
||||||
|
if (openvzWriteConfigParam(strtoI(def->name), "NETIF", param) < 0) {
|
||||||
|
VIR_FREE(param);
|
||||||
|
openvzError(conn, VIR_ERR_INTERNAL_ERROR,
|
||||||
|
"%s", _("cannot replace NETIF config"));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
VIR_FREE(param);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
param = virBufferContentAndReset(&buf);
|
||||||
|
VIR_FREE(param);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static virDomainPtr
|
static virDomainPtr
|
||||||
openvzDomainDefineXML(virConnectPtr conn, const char *xml)
|
openvzDomainDefineXML(virConnectPtr conn, const char *xml)
|
||||||
{
|
{
|
||||||
@ -423,7 +555,6 @@ openvzDomainDefineXML(virConnectPtr conn, const char *xml)
|
|||||||
virDomainDefPtr vmdef = NULL;
|
virDomainDefPtr vmdef = NULL;
|
||||||
virDomainObjPtr vm = NULL;
|
virDomainObjPtr vm = NULL;
|
||||||
virDomainPtr dom = NULL;
|
virDomainPtr dom = NULL;
|
||||||
int i;
|
|
||||||
const char *prog[OPENVZ_MAX_ARG];
|
const char *prog[OPENVZ_MAX_ARG];
|
||||||
prog[0] = NULL;
|
prog[0] = NULL;
|
||||||
|
|
||||||
@ -469,18 +600,13 @@ openvzDomainDefineXML(virConnectPtr conn, const char *xml)
|
|||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (openvzDomainSetNetworkConfig(conn, vmdef) < 0)
|
||||||
|
goto exit;
|
||||||
|
|
||||||
dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
|
dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
|
||||||
if (dom)
|
if (dom)
|
||||||
dom->id = -1;
|
dom->id = -1;
|
||||||
|
|
||||||
for (i = 0 ; i < vmdef->nnets ; i++) {
|
|
||||||
if (openvzDomainSetNetwork(conn, vmdef->name, vmdef->nets[i]) < 0) {
|
|
||||||
openvzError(conn, VIR_ERR_INTERNAL_ERROR,
|
|
||||||
"%s", _("Could not configure network"));
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (vmdef->vcpus > 0) {
|
if (vmdef->vcpus > 0) {
|
||||||
if (openvzDomainSetVcpus(dom, vmdef->vcpus) < 0) {
|
if (openvzDomainSetVcpus(dom, vmdef->vcpus) < 0) {
|
||||||
openvzError(conn, VIR_ERR_INTERNAL_ERROR,
|
openvzError(conn, VIR_ERR_INTERNAL_ERROR,
|
||||||
@ -501,7 +627,6 @@ openvzDomainCreateXML(virConnectPtr conn, const char *xml,
|
|||||||
virDomainDefPtr vmdef = NULL;
|
virDomainDefPtr vmdef = NULL;
|
||||||
virDomainObjPtr vm = NULL;
|
virDomainObjPtr vm = NULL;
|
||||||
virDomainPtr dom = NULL;
|
virDomainPtr dom = NULL;
|
||||||
int i;
|
|
||||||
struct openvz_driver *driver = (struct openvz_driver *) conn->privateData;
|
struct openvz_driver *driver = (struct openvz_driver *) conn->privateData;
|
||||||
const char *progstart[] = {VZCTL, "--quiet", "start", NULL, NULL};
|
const char *progstart[] = {VZCTL, "--quiet", "start", NULL, NULL};
|
||||||
const char *progcreate[OPENVZ_MAX_ARG];
|
const char *progcreate[OPENVZ_MAX_ARG];
|
||||||
@ -547,13 +672,8 @@ openvzDomainCreateXML(virConnectPtr conn, const char *xml,
|
|||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0 ; i < vmdef->nnets ; i++) {
|
if (openvzDomainSetNetworkConfig(conn, vmdef) < 0)
|
||||||
if (openvzDomainSetNetwork(conn, vmdef->name, vmdef->nets[i]) < 0) {
|
goto exit;
|
||||||
openvzError(conn, VIR_ERR_INTERNAL_ERROR,
|
|
||||||
"%s", _("Could not configure network"));
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
progstart[3] = vmdef->name;
|
progstart[3] = vmdef->name;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user