reguire gnupg1 on f>=31; sense the system to use gpg1 when installed
[nodemanager.git] / sliver_libvirt.py
index a70d18f..cea8a39 100644 (file)
@@ -24,12 +24,33 @@ STATES = {
     libvirt.VIR_DOMAIN_CRASHED:  'crashed',
 }
 
-REASONS = {
-    libvirt.VIR_CONNECT_CLOSE_REASON_ERROR: 'Misc I/O error',
-    libvirt.VIR_CONNECT_CLOSE_REASON_EOF: 'End-of-file from server',
-    libvirt.VIR_CONNECT_CLOSE_REASON_KEEPALIVE: 'Keepalive timer triggered',
-    libvirt.VIR_CONNECT_CLOSE_REASON_CLIENT: 'Client requested it',
-}
+# with fedora24 and (broken) libvirt-python-1.3.3-3,
+# the following symbols are not available
+# kashyap on IRC reported that libvirt-python-1.3.5-1.fc24.x86_64
+# did not have the issue though
+try:
+    REASONS = {
+        # 0
+        libvirt.VIR_CONNECT_CLOSE_REASON_ERROR: 'Misc I/O error',
+        # 1
+        libvirt.VIR_CONNECT_CLOSE_REASON_EOF: 'End-of-file from server',
+        # 2
+        libvirt.VIR_CONNECT_CLOSE_REASON_KEEPALIVE: 'Keepalive timer triggered',
+        # 3
+        libvirt.VIR_CONNECT_CLOSE_REASON_CLIENT: 'Client requested it',
+    }
+except:
+    REASONS = {
+        # libvirt.VIR_CONNECT_CLOSE_REASON_ERROR
+        0 : 'Misc I/O error',
+        # libvirt.VIR_CONNECT_CLOSE_REASON_EOF
+        1 : 'End-of-file from server',
+        # libvirt.VIR_CONNECT_CLOSE_REASON_KEEPALIVE
+        2 : 'Keepalive timer triggered',
+        # libvirt.VIR_CONNECT_CLOSE_REASON_CLIENT
+        3 : 'Client requested it',
+    }
+    logger.log("WARNING : using hard-wired constants instead of symbolic names for CONNECT_CLOSE*")
 
 connections = dict()
 
@@ -41,11 +62,33 @@ class Sliver_Libvirt(Account):
 
     @staticmethod
     def getConnection(sliver_type):
-        # TODO: error checking
-        # vtype is of the form sliver.[LXC/QEMU] we need to lower case to lxc/qemu
+        """
+        returns a connection to the underlying libvirt service
+        a single connection is created and shared among slivers
+        this call ensures the connection is alive
+        and will reconnect if it appears to be necessary
+        """
+        # sliver_type comes from rec['type'] and is of the form sliver.{LXC,QEMU}
+        # so we need to lower case to lxc/qemu
         vtype = sliver_type.split('.')[1].lower()
-        uri = vtype + '://'
-        return connections.setdefault(uri, libvirt.open(uri))
+        uri = vtype + ':///'
+        if uri not in connections:
+            # create connection
+            conn = libvirt.open(uri)
+            connections[uri] = conn
+            return conn
+        else:
+            # connection already available : check for health
+            conn = connections[uri]
+            # see if a reconnection is needed
+            try:
+                numDomains = conn.numOfDomains()
+            except:
+                logger.log("libvirt connection to {} looks broken - reconnecting".format(uri))
+                conn = libvirt.open(uri)
+                # if this fails then an expection is thrown outside of this function
+                numDomains = conn.numOfDomains()
+            return conn
 
     def __init__(self, rec):
         self.name = rec['name']
@@ -127,7 +170,7 @@ class Sliver_Libvirt(Account):
             try:
                 # create actually means start
                 self.dom.create()
-            except Exception, e:
+            except Exception as e:
                 # XXX smbaker: attempt to resolve slivers that are stuck in
                 #   "failed to allocate free veth".
                 if "ailed to allocate free veth" in str(e):
@@ -146,6 +189,7 @@ class Sliver_Libvirt(Account):
         bwlimit.ebtables("-A INPUT -i veth{} -j mark --set-mark {}"
                          .format(self.xid, self.xid))
 
+    ### this is confusing, because it seems it is not used in fact
     def stop(self):
         logger.verbose('sliver_libvirt: {} stop'.format(self.name))
 
@@ -181,7 +225,7 @@ class Sliver_Libvirt(Account):
 
         # Btrfs support quota per volumes
 
-        if rec.has_key("rspec") and rec["rspec"].has_key("tags"):
+        if "rspec" in rec and "tags" in rec["rspec"]:
             if cgroups.get_cgroup_path(self.name) == None:
                 # If configure is called before start, then the cgroups won't exist
                 # yet. NM will eventually re-run configure on the next iteration.
@@ -191,7 +235,7 @@ class Sliver_Libvirt(Account):
             else:
                 tags = rec["rspec"]["tags"]
                 # It will depend on the FS selection
-                if tags.has_key('disk_max'):
+                if 'disk_max' in tags:
                     disk_max = tags['disk_max']
                     if disk_max == 0:
                         # unlimited
@@ -201,17 +245,17 @@ class Sliver_Libvirt(Account):
                         pass
 
                 # Memory allocation
-                if tags.has_key('memlock_hard'):
+                if 'memlock_hard' in tags:
                     mem = str(int(tags['memlock_hard']) * 1024) # hard limit in bytes
                     cgroups.write(self.name, 'memory.limit_in_bytes', mem, subsystem="memory")
-                if tags.has_key('memlock_soft'):
+                if 'memlock_soft' in tags:
                     mem = str(int(tags['memlock_soft']) * 1024) # soft limit in bytes
                     cgroups.write(self.name, 'memory.soft_limit_in_bytes', mem, subsystem="memory")
 
                 # CPU allocation
                 # Only cpu_shares until figure out how to provide limits and guarantees
                 # (RT_SCHED?)
-                if tags.has_key('cpu_share'):
+                if 'cpu_share' in tags:
                     cpu_share = tags['cpu_share']
                     cgroups.write(self.name, 'cpu.shares', cpu_share)