From: Aline Manera <alinefm(a)br.ibm.com>
Libvirt connection is a base facility for kimchi model, so each
resource model should be able to access it directly.
Signed-off-by: Aline Manera <alinefm(a)br.ibm.com>
---
src/kimchi/model.py | 93 +-----------------------
src/kimchi/model_/libvirtconnection.py | 123 ++++++++++++++++++++++++++++++++
2 files changed, 124 insertions(+), 92 deletions(-)
create mode 100644 src/kimchi/model_/libvirtconnection.py
diff --git a/src/kimchi/model.py b/src/kimchi/model.py
index 2c6d3a1..0577088 100644
--- a/src/kimchi/model.py
+++ b/src/kimchi/model.py
@@ -67,6 +67,7 @@ from kimchi.exception import MissingParameter, NotFoundError,
OperationFailed
from kimchi.featuretests import FeatureTests
from kimchi.iscsi import TargetClient
from kimchi.isoinfo import IsoImage
+from kimchi.model_.libvirtconnection import LibvirtConnection
from kimchi.objectstore import ObjectStore
from kimchi.scan import Scanner
from kimchi.screenshot import VMScreenshot
@@ -1733,95 +1734,3 @@ def _get_volume_xml(**kwargs):
</volume>
""" % kwargs
return xml
-
-
-class LibvirtConnection(object):
- def __init__(self, uri):
- self.uri = uri
- self._connections = {}
- self._connectionLock = threading.Lock()
- self.wrappables = self.get_wrappable_objects()
-
- def get_wrappable_objects(self):
- """
- When a wrapped function returns an instance of another libvirt object,
- we also want to wrap that object so we can catch errors that happen when
- calling its methods.
- """
- objs = []
- for name in ('virDomain', 'virDomainSnapshot',
'virInterface',
- 'virNWFilter', 'virNetwork',
'virNodeDevice', 'virSecret',
- 'virStoragePool', 'virStorageVol',
'virStream'):
- try:
- attr = getattr(libvirt, name)
- except AttributeError:
- pass
- objs.append(attr)
- return tuple(objs)
-
- def get(self, conn_id=0):
- """
- Return current connection to libvirt or open a new one. Wrap all
- callable libvirt methods so we can catch connection errors and handle
- them by restarting the server.
- """
- def wrapMethod(f):
- def wrapper(*args, **kwargs):
- try:
- ret = f(*args, **kwargs)
- return ret
- except libvirt.libvirtError as e:
- edom = e.get_error_domain()
- ecode = e.get_error_code()
- EDOMAINS = (libvirt.VIR_FROM_REMOTE,
- libvirt.VIR_FROM_RPC)
- ECODES = (libvirt.VIR_ERR_SYSTEM_ERROR,
- libvirt.VIR_ERR_INTERNAL_ERROR,
- libvirt.VIR_ERR_NO_CONNECT,
- libvirt.VIR_ERR_INVALID_CONN)
- if edom in EDOMAINS and ecode in ECODES:
- kimchi_log.error('Connection to libvirt broken. '
- 'Recycling. ecode: %d edom: %d' %
- (ecode, edom))
- with self._connectionLock:
- self._connections[conn_id] = None
- raise
- wrapper.__name__ = f.__name__
- wrapper.__doc__ = f.__doc__
- return wrapper
-
- with self._connectionLock:
- conn = self._connections.get(conn_id)
- if not conn:
- retries = 5
- while True:
- retries = retries - 1
- try:
- conn = libvirt.open(self.uri)
- break
- except libvirt.libvirtError:
- kimchi_log.error('Unable to connect to libvirt.')
- if not retries:
- kimchi_log.error('Libvirt is not available,
exiting.')
- cherrypy.engine.stop()
- raise
- time.sleep(2)
-
- for name in dir(libvirt.virConnect):
- method = getattr(conn, name)
- if callable(method) and not name.startswith('_'):
- setattr(conn, name, wrapMethod(method))
-
- for cls in self.wrappables:
- for name in dir(cls):
- method = getattr(cls, name)
- if callable(method) and not name.startswith('_'):
- setattr(cls, name, wrapMethod(method))
-
- self._connections[conn_id] = conn
- # In case we're running into troubles with keeping the connections
- # alive we should place here:
- # conn.setKeepAlive(interval=5, count=3)
- # However the values need to be considered wisely to not affect
- # hosts which are hosting a lot of virtual machines
- return conn
diff --git a/src/kimchi/model_/libvirtconnection.py
b/src/kimchi/model_/libvirtconnection.py
new file mode 100644
index 0000000..9276acc
--- /dev/null
+++ b/src/kimchi/model_/libvirtconnection.py
@@ -0,0 +1,123 @@
+#
+# Project Kimchi
+#
+# Copyright IBM, Corp. 2013
+#
+# Authors:
+# Adam Litke <agl(a)linux.vnet.ibm.com>
+# Aline Manera <alinefm(a)linux.vnet.ibm.com>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+import cherrypy
+import libvirt
+import threading
+import time
+
+
+from kimchi.utils import kimchi_log
+
+
+class LibvirtConnection(object):
+ def __init__(self, uri):
+ self.uri = uri
+ self._connections = {}
+ self._connectionLock = threading.Lock()
+ self.wrappables = self.get_wrappable_objects()
+
+ def get_wrappable_objects(self):
+ """
+ When a wrapped function returns an instance of another libvirt object,
+ we also want to wrap that object so we can catch errors that happen
+ when calling its methods.
+ """
+ objs = []
+ for name in ('virDomain', 'virDomainSnapshot',
'virInterface',
+ 'virNWFilter', 'virNetwork',
'virNodeDevice', 'virSecret',
+ 'virStoragePool', 'virStorageVol',
'virStream'):
+ try:
+ attr = getattr(libvirt, name)
+ except AttributeError:
+ pass
+ objs.append(attr)
+ return tuple(objs)
+
+ def get(self, conn_id=0):
+ """
+ Return current connection to libvirt or open a new one. Wrap all
+ callable libvirt methods so we can catch connection errors and handle
+ them by restarting the server.
+ """
+ def wrapMethod(f):
+ def wrapper(*args, **kwargs):
+ try:
+ ret = f(*args, **kwargs)
+ return ret
+ except libvirt.libvirtError as e:
+ edom = e.get_error_domain()
+ ecode = e.get_error_code()
+ EDOMAINS = (libvirt.VIR_FROM_REMOTE,
+ libvirt.VIR_FROM_RPC)
+ ECODES = (libvirt.VIR_ERR_SYSTEM_ERROR,
+ libvirt.VIR_ERR_INTERNAL_ERROR,
+ libvirt.VIR_ERR_NO_CONNECT,
+ libvirt.VIR_ERR_INVALID_CONN)
+ if edom in EDOMAINS and ecode in ECODES:
+ kimchi_log.error('Connection to libvirt broken. '
+ 'Recycling. ecode: %d edom: %d' %
+ (ecode, edom))
+ with self._connectionLock:
+ self._connections[conn_id] = None
+ raise
+ wrapper.__name__ = f.__name__
+ wrapper.__doc__ = f.__doc__
+ return wrapper
+
+ with self._connectionLock:
+ conn = self._connections.get(conn_id)
+ if not conn:
+ retries = 5
+ while True:
+ retries = retries - 1
+ try:
+ conn = libvirt.open(self.uri)
+ break
+ except libvirt.libvirtError:
+ kimchi_log.error('Unable to connect to libvirt.')
+ if not retries:
+ msg = 'Libvirt is not available, exiting.'
+ kimchi_log.error(msg)
+ cherrypy.engine.stop()
+ raise
+ time.sleep(2)
+
+ for name in dir(libvirt.virConnect):
+ method = getattr(conn, name)
+ if callable(method) and not name.startswith('_'):
+ setattr(conn, name, wrapMethod(method))
+
+ for cls in self.wrappables:
+ for name in dir(cls):
+ method = getattr(cls, name)
+ if callable(method) and not name.startswith('_'):
+ setattr(cls, name, wrapMethod(method))
+
+ self._connections[conn_id] = conn
+ # In case we're running into troubles with keeping the
+ # connections alive we should place here:
+ # conn.setKeepAlive(interval=5, count=3)
+ # However the values need to be considered wisely to not affect
+ # hosts which are hosting a lot of virtual machines
+ return conn
--
1.7.10.4