From 25cacebb7644ff7e5f28b0d2756e1277f528ef23 Mon Sep 17 00:00:00 2001
From: David Lehman <dlehman@redhat.com>
Date: Thu, 7 Aug 2014 17:34:03 -0500
Subject: [PATCH 09/26] Make the main class hierarchies thread-safe.

Add a global reentrant lock. Use a metaclass which wraps every method
call in a decorator which grabs that lock before calling a method.
---
 blivet/deviceaction.py      | 4 +++-
 blivet/devices/container.py | 3 ++-
 blivet/devices/device.py    | 3 +++
 blivet/devices/lvm.py       | 3 ++-
 blivet/devices/raid.py      | 5 ++---
 blivet/devicetree.py        | 9 ++++++++-
 blivet/formats/__init__.py  | 3 +++
 7 files changed, 23 insertions(+), 7 deletions(-)

diff --git a/blivet/deviceaction.py b/blivet/deviceaction.py
index dc3508d..5fa31b1 100644
--- a/blivet/deviceaction.py
+++ b/blivet/deviceaction.py
@@ -20,9 +20,9 @@
 # Red Hat Author(s): Dave Lehman <dlehman@redhat.com>
 #
 
+from six import add_metaclass
 
 from . import util
-
 from . import udev
 from .util import get_current_entropy
 from .devices import StorageDevice
@@ -35,6 +35,7 @@ from .callbacks import CreateFormatPreData, CreateFormatPostData
 from .callbacks import ResizeFormatPreData, ResizeFormatPostData
 from .callbacks import WaitForEntropyData
 from .size import Size
+from .threads import SynchronizedMeta
 
 import logging
 log = logging.getLogger("blivet")
@@ -97,6 +98,7 @@ def resize_type_from_string(type_string):
         if v.lower() == type_string.lower():
             return k
 
+@add_metaclass(SynchronizedMeta)
 class DeviceAction(util.ObjectID):
     """ An action that will be carried out in the future on a Device.
 
diff --git a/blivet/devices/container.py b/blivet/devices/container.py
index 612b9fc..8050513 100644
--- a/blivet/devices/container.py
+++ b/blivet/devices/container.py
@@ -26,13 +26,14 @@ from six import add_metaclass
 from .. import errors
 from ..storage_log import log_method_call
 from ..formats import get_device_format_class
+from ..threads import SynchronizedABCMeta
 
 import logging
 log = logging.getLogger("blivet")
 
 from .storage import StorageDevice
 
-@add_metaclass(abc.ABCMeta)
+@add_metaclass(SynchronizedABCMeta)
 class ContainerDevice(StorageDevice):
     """ A device that aggregates a set of member devices.
 
diff --git a/blivet/devices/device.py b/blivet/devices/device.py
index 1109b3d..433bd1d 100644
--- a/blivet/devices/device.py
+++ b/blivet/devices/device.py
@@ -21,15 +21,18 @@
 #
 
 import pprint
+from six import add_metaclass
 
 from .. import util
 from ..storage_log import log_method_call
+from ..threads import SynchronizedMeta
 
 import logging
 log = logging.getLogger("blivet")
 
 from .lib import ParentList
 
+@add_metaclass(SynchronizedMeta)
 class Device(util.ObjectID):
     """ A generic device.
 
diff --git a/blivet/devices/lvm.py b/blivet/devices/lvm.py
index d1817dd..a35a0c4 100644
--- a/blivet/devices/lvm.py
+++ b/blivet/devices/lvm.py
@@ -35,6 +35,7 @@ from ..formats import getFormat
 from ..storage_log import log_method_call
 from .. import udev
 from ..size import Size, KiB, MiB
+from ..threads import SynchronizedABCMeta
 
 import logging
 log = logging.getLogger("blivet")
@@ -785,7 +786,7 @@ class LVMLogicalVolumeDevice(DMDevice):
 
         return True
 
-@add_metaclass(abc.ABCMeta)
+@add_metaclass(SynchronizedABCMeta)
 class LVMSnapShotBase(object):
     """ Abstract base class for lvm snapshots
 
diff --git a/blivet/devices/raid.py b/blivet/devices/raid.py
index 60fb5a2..8638ecf 100644
--- a/blivet/devices/raid.py
+++ b/blivet/devices/raid.py
@@ -19,16 +19,15 @@
 # Red Hat Author(s): Anne Mulhern <amulhern@redhat.com>
 #
 
-import abc
-
 from six import add_metaclass
 
 from .. import errors
 from ..i18n import _, P_
+from ..threads import SynchronizedABCMeta
 
 from .storage import StorageDevice
 
-@add_metaclass(abc.ABCMeta)
+@add_metaclass(SynchronizedABCMeta)
 class RaidDevice(StorageDevice):
     """ Metaclass for devices that support RAID in some form. """
 
diff --git a/blivet/devicetree.py b/blivet/devicetree.py
index 1841262..5a5a526 100644
--- a/blivet/devicetree.py
+++ b/blivet/devicetree.py
@@ -26,6 +26,7 @@ import re
 import shutil
 import pprint
 import copy
+from six import add_metaclass
 
 from .errors import CryptoError, DeviceError, DeviceTreeError, DiskLabelCommitError, DMError, FSError, InvalidDiskLabelError, LUKSError, MDRaidError, StorageError, UnusableConfigurationError
 from .devices import BTRFSDevice, BTRFSSubVolumeDevice, BTRFSVolumeDevice, BTRFSSnapShotDevice
@@ -56,10 +57,12 @@ from .flags import flags
 from .storage_log import log_exception_info, log_method_call, log_method_return
 from .i18n import _
 from .size import Size
+from .threads import blivet_lock, SynchronizedMeta
 
 import logging
 log = logging.getLogger("blivet")
 
+@add_metaclass(SynchronizedMeta)
 class DeviceTree(object):
     """ A quasi-tree that represents the devices in the system.
 
@@ -79,6 +82,7 @@ class DeviceTree(object):
         :class:`~.deviceaction.DeviceAction` instances can only be registered
         for leaf devices, except for resize actions.
     """
+    _unsynchronized_methods = ['processActions']
 
     def __init__(self, conf=None, passphrase=None, luksDict=None,
                  iscsi=None, dasd=None):
@@ -356,7 +360,10 @@ class DeviceTree(object):
 
         for action in self._actions[:]:
             log.info("executing action: %s", action)
-            if not dryRun:
+            if dryRun:
+                continue
+
+            with blivet_lock:
                 try:
                     action.execute(callbacks)
                 except DiskLabelCommitError:
diff --git a/blivet/formats/__init__.py b/blivet/formats/__init__.py
index 0b84528..46b7825 100644
--- a/blivet/formats/__init__.py
+++ b/blivet/formats/__init__.py
@@ -21,6 +21,7 @@
 #
 
 import os
+from six import add_metaclass
 
 from ..util import notify_kernel
 from ..util import get_sysfs_path_by_name
@@ -32,6 +33,7 @@ from ..devicelibs.dm import dm_node_from_name
 from ..devicelibs.mdraid import md_node_from_name
 from ..i18n import N_
 from ..size import Size
+from ..threads import SynchronizedMeta
 
 import logging
 log = logging.getLogger("blivet")
@@ -136,6 +138,7 @@ def get_device_format_class(fmt_type):
 
     return fmt
 
+@add_metaclass(SynchronizedMeta)
 class DeviceFormat(ObjectID):
     """ Generic device format.
 
-- 
1.9.3

