2008-11-07 01:40:25 +01:00
|
|
|
Index: libvirt-0.4.6/src/network_conf.c
|
|
|
|
===================================================================
|
|
|
|
--- libvirt-0.4.6.orig/src/network_conf.c
|
|
|
|
+++ libvirt-0.4.6/src/network_conf.c
|
|
|
|
@@ -752,6 +752,131 @@ error:
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
+static int virNetworkIsBridge(const char *name)
|
|
|
|
+{
|
|
|
|
+ char *path = NULL;
|
|
|
|
+ int ret = 0;
|
|
|
|
+ struct stat s;
|
|
|
|
+
|
|
|
|
+ if (asprintf(&path, "/sys/class/net/%s/bridge", name) < 0)
|
|
|
|
+ goto out;
|
|
|
|
+
|
|
|
|
+ if (stat(path, &s) != 0)
|
|
|
|
+ goto out;
|
|
|
|
+
|
|
|
|
+ if (S_ISDIR(s.st_mode))
|
|
|
|
+ ret = 1;
|
|
|
|
+
|
|
|
|
+ out:
|
|
|
|
+ free(path);
|
|
|
|
+ return ret;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static unsigned long virNetworkDefSuseGetValue(char *netName, char *valName)
|
|
|
|
+{
|
|
|
|
+ unsigned long ret = 0;
|
|
|
|
+ char *path = NULL;
|
|
|
|
+ FILE *f;
|
|
|
|
+
|
|
|
|
+ if (asprintf(&path, "/sys/class/net/%s/bridge/%s", netName, valName) < 0)
|
|
|
|
+ return ret;
|
|
|
|
+
|
|
|
|
+ if ((f = fopen(path, "r")) == NULL)
|
|
|
|
+ goto out;
|
|
|
|
+
|
|
|
|
+ if (fscanf(f, "%lu", &ret) != 1) {
|
|
|
|
+ ret = 0;
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ out:
|
|
|
|
+ if (f != NULL)
|
|
|
|
+ fclose(f);
|
|
|
|
+ free(path);
|
|
|
|
+ return ret;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static virNetworkObjPtr virNetworkLoadSuseNet(virConnectPtr conn,
|
|
|
|
+ virNetworkObjPtr *nets,
|
|
|
|
+ char *name)
|
|
|
|
+{
|
|
|
|
+ virNetworkDefPtr def;
|
|
|
|
+ virNetworkObjPtr network;
|
|
|
|
+ int err;
|
|
|
|
+
|
|
|
|
+ if ((network = virNetworkFindByName(*nets, name))) {
|
|
|
|
+ return network;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (VIR_ALLOC(network) < 0) {
|
|
|
|
+ virNetworkReportError(conn, VIR_ERR_NO_MEMORY, NULL);
|
|
|
|
+ return NULL;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ network->autostart = 1;
|
|
|
|
+ network->active = 1;
|
|
|
|
+ network->readonly = 1;
|
|
|
|
+ network->next = *nets;
|
|
|
|
+
|
|
|
|
+ if (VIR_ALLOC(def) < 0) {
|
|
|
|
+ virNetworkReportError(conn, VIR_ERR_NO_MEMORY, NULL);
|
|
|
|
+ goto error;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ network->def = def;
|
|
|
|
+
|
|
|
|
+ /* name */
|
|
|
|
+ def->name = strdup(name);
|
|
|
|
+ if (def->name == NULL) {
|
|
|
|
+ virNetworkReportError(conn, VIR_ERR_NO_MEMORY, NULL);
|
|
|
|
+ goto error;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* uuid */
|
|
|
|
+ if ((err = virUUIDGenerate(def->uuid))) {
|
|
|
|
+ virNetworkReportError(conn, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
+ _("Failed to generate UUID: %s"), strerror(err));
|
|
|
|
+ goto error;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* bridge information */
|
|
|
|
+ def->bridge = strdup(name);
|
|
|
|
+ if (def->bridge == NULL) {
|
|
|
|
+ virNetworkReportError(conn, VIR_ERR_NO_MEMORY, NULL);
|
|
|
|
+ goto error;
|
|
|
|
+ }
|
|
|
|
+ def->stp = (int)virNetworkDefSuseGetValue(name, "stp_state");
|
|
|
|
+ def->delay = virNetworkDefSuseGetValue(name, "forward_delay");
|
|
|
|
+
|
|
|
|
+ /* Add network to the list */
|
|
|
|
+ *nets = network;
|
|
|
|
+ return network;
|
|
|
|
+
|
|
|
|
+ error:
|
|
|
|
+ virNetworkObjFree(network);
|
|
|
|
+ return NULL;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void virNetworkLoadSuseNetworks(virConnectPtr conn,
|
|
|
|
+ virNetworkObjPtr *nets)
|
|
|
|
+{
|
|
|
|
+ DIR *dir = NULL;
|
|
|
|
+ struct dirent *de;
|
|
|
|
+ int count = 0;
|
|
|
|
+
|
|
|
|
+ dir = opendir("/sys/class/net");
|
|
|
|
+ if (dir == NULL)
|
2008-11-21 15:32:50 +01:00
|
|
|
+ return;
|
2008-11-07 01:40:25 +01:00
|
|
|
+
|
|
|
|
+ while ((de = readdir(dir))) {
|
|
|
|
+ if (virNetworkIsBridge(de->d_name)) {
|
|
|
|
+ virNetworkLoadSuseNet(conn, nets, de->d_name);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ closedir(dir);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
int virNetworkLoadAllConfigs(virConnectPtr conn,
|
|
|
|
virNetworkObjPtr *nets,
|
|
|
|
const char *configDir,
|
|
|
|
@@ -787,6 +912,7 @@ int virNetworkLoadAllConfigs(virConnectP
|
|
|
|
|
|
|
|
closedir(dir);
|
|
|
|
|
|
|
|
+ virNetworkLoadSuseNetworks(conn, nets);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
Index: libvirt-0.4.6/src/network_conf.h
|
|
|
|
===================================================================
|
|
|
|
--- libvirt-0.4.6.orig/src/network_conf.h
|
|
|
|
+++ libvirt-0.4.6/src/network_conf.h
|
|
|
|
@@ -82,6 +82,7 @@ struct _virNetworkObj {
|
|
|
|
unsigned int active : 1;
|
|
|
|
unsigned int autostart : 1;
|
|
|
|
unsigned int persistent : 1;
|
|
|
|
+ unsigned int readonly : 1;
|
|
|
|
|
|
|
|
char *configFile; /* Persistent config file path */
|
|
|
|
char *autostartLink; /* Symlink path for autostart */
|
|
|
|
Index: libvirt-0.4.6/src/qemu_driver.c
|
|
|
|
===================================================================
|
|
|
|
--- libvirt-0.4.6.orig/src/qemu_driver.c
|
|
|
|
+++ libvirt-0.4.6/src/qemu_driver.c
|
|
|
|
@@ -1601,6 +1601,12 @@ static int qemudShutdownNetworkDaemon(vi
|
|
|
|
if (!virNetworkIsActive(network))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
+ if (network->readonly) {
|
|
|
|
+ qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
+ ": Network '%s' is readonly", network->def->name);
|
|
|
|
+ return -1;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
if (network->dnsmasqPid > 0)
|
|
|
|
kill(network->dnsmasqPid, SIGTERM);
|
|
|
|
|
|
|
|
@@ -3974,6 +3980,12 @@ static int qemudNetworkSetAutostart(virN
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
+ if (network->readonly) {
|
|
|
|
+ qemudReportError(net->conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
+ ": Network '%s' is readonly", network->def->name);
|
|
|
|
+ return -1;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
autostart = (autostart != 0);
|
|
|
|
|
|
|
|
if (network->autostart == autostart)
|