Change in vdsm[master]: adding the StorageDomain.upgradeVersion verb

laravot at redhat.com laravot at redhat.com
Thu Feb 25 16:35:16 UTC 2016


Liron Aravot has uploaded a new change for review.

Change subject: adding the StorageDomain.upgradeVersion verb
......................................................................

adding the StorageDomain.upgradeVersion verb

Change-Id: Id8fb87c6e04e48072ec90d07a0f4c7a61411a808
Signed-off-by: laravot at redhat.com <laravot at redhat.com>
---
M client/vdsClient.py
M vdsm/API.py
M vdsm/rpc/BindingXMLRPC.py
M vdsm/rpc/vdsmapi-schema.json
M vdsm/storage/hsm.py
M vdsm/storage/imageRepository/formatConverter.py
M vdsm/storage/sp.py
M vdsm/storage/storage_exception.py
8 files changed, 148 insertions(+), 24 deletions(-)


  git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/78/42478/7

diff --git a/client/vdsClient.py b/client/vdsClient.py
index e17ba76..c3628c5 100755
--- a/client/vdsClient.py
+++ b/client/vdsClient.py
@@ -682,6 +682,15 @@
             return dom['status']['code'], dom['status']['message']
         return 0, ''
 
+    def upgradeStorageDomainVersion(self, args):
+        sdUUID = args[0]
+        spUUID = args[1]
+        version = args[2]
+        dom = self.s.upgradeStorageDomainVersion(sdUUID, spUUID, version)
+        if dom['status']['code']:
+            return dom['status']['code'], dom['status']['message']
+        return 0, ''
+
     def detachStorageDomainAnyStoragePoolHsm(self, args):
         sdUUID = args[0]
         hostID = args[1]
@@ -2521,6 +2530,12 @@
                                     'domain metadata is not modified to'
                                     'reflect its detached.'
                                     )),
+        'upgradeStorageDomainVersion': (serv.upgradeStorageDomainVersion,
+                                        ('<domain UUID> <pool UUID> <version>',
+                                         'Upgrades a storage domain that is'
+                                         'part of connected storage pool to'
+                                         'the given version.'
+                                         )),
         'detachStorageDomainAnyStoragePoolHsm':
         (serv.detachStorageDomainAnyStoragePoolHsm,
          ('<domain UUID>' '<hostId int>',
diff --git a/vdsm/API.py b/vdsm/API.py
index 3212616..3007d93 100644
--- a/vdsm/API.py
+++ b/vdsm/API.py
@@ -1023,6 +1023,10 @@
     def detachAnyStoragePoolHsm(self, hostID):
         return self._irs.detachAnyStoragePoolHsm(self._UUID, hostID)
 
+    def upgradeVersion(self, storagepoolID, version):
+        return self._irs.upgradeStorageDomainVersion(self._UUID, storagepoolID,
+                                                     version)
+
     def extend(self, storagepoolID, devlist, force=False):
         return self._irs.extendStorageDomain(self._UUID, storagepoolID,
                                              devlist, force)
diff --git a/vdsm/rpc/BindingXMLRPC.py b/vdsm/rpc/BindingXMLRPC.py
index 70db4ed..5294e6a 100644
--- a/vdsm/rpc/BindingXMLRPC.py
+++ b/vdsm/rpc/BindingXMLRPC.py
@@ -640,6 +640,10 @@
         domain = API.StorageDomain(sdUUID)
         return domain.detachAnyStoragePoolHsm(sdUUID, hostID)
 
+    def domainUpgradeVersion(self, sdUUID, spUUID, version):
+        domain = API.StorageDomain(sdUUID)
+        return domain.upgradeVersion(spUUID, version)
+
     def domainDetachForced(self, sdUUID, spUUID, options=None):
         domain = API.StorageDomain(sdUUID)
         return domain.detach(spUUID, None, None, force=True)
@@ -1089,7 +1093,8 @@
                 (self.domainDetachHsm, 'detachStorageDomainHsm'),
                 (self.domainDetachAnyStoragePoolHsm,
                  'detachAnyStoragePoolHsm'),
-                (self.domainGetStoredVmsInfo, 'getStorageDomainStoredVmsInfo'))
+                (self.domainGetStoredVmsInfo, 'getStorageDomainStoredVmsInfo'),
+                (self.domainUpgradeVersion, 'upgradeStorageDomainVersion'))
 
     def getIrsMethods(self):
         return ((self.domainActivate, 'activateStorageDomain'),
diff --git a/vdsm/rpc/vdsmapi-schema.json b/vdsm/rpc/vdsmapi-schema.json
index 86cfb6e..7d514e3 100644
--- a/vdsm/rpc/vdsmapi-schema.json
+++ b/vdsm/rpc/vdsmapi-schema.json
@@ -5173,6 +5173,22 @@
  'data': {'storagedomainID': 'UUID', 'hostID' : 'int'}}
 
 ##
+# @StorageDomain.upgradeVersion:
+#
+# Upgrades the StorageDomain version
+#
+# @storagedomainID:  The UUID of the Storage Domain
+#
+# @storagepoolID:    The UUID of the Storage Pool
+#
+# @version:    The target version
+#
+# Since: 4.18.0
+##
+{'command': {'class': 'StorageDomain', 'name': 'upgradeVersion'},
+ 'data': {'storagedomainID': 'UUID', 'storagepoolID': 'UUID', 'version': 'int'}}
+
+##
 # @StorageDomain.extend:
 #
 # Extend a block-based Storage Domain onto more block devices.
diff --git a/vdsm/storage/hsm.py b/vdsm/storage/hsm.py
index 95c4803..b1687da 100644
--- a/vdsm/storage/hsm.py
+++ b/vdsm/storage/hsm.py
@@ -844,6 +844,11 @@
             pool.detachSDHsm(sdUUID)
 
     @public
+    def upgradeStorageDomainVersion(self, sdUUID, spUUID, version):
+        pool = self.getPool(spUUID)
+        pool.upgradeDomainFormat(sdUUID, version)
+
+    @public
     def detachStorageDomainAnyStoragePoolHsm(self, sdUUID, hostID):
         """
         Clears the StoragePool entry (Detach) in the given domain metadata
diff --git a/vdsm/storage/imageRepository/formatConverter.py b/vdsm/storage/imageRepository/formatConverter.py
index f5f8f6f..b88dbca 100644
--- a/vdsm/storage/imageRepository/formatConverter.py
+++ b/vdsm/storage/imageRepository/formatConverter.py
@@ -87,16 +87,28 @@
                   "for the domain %s", targetVersion, domain.sdUUID)
 
 
+def v3_to_v4_DomainConvertor(repoPath, hostId, domain, isMsd):
+    domain.invalidateMetadata()
+    domain.setMetaParam(sd.DMDK_VERSION, 4)
+
+
 def v3DomainConverter(repoPath, hostId, domain, isMsd):
+    _v0_and_v2_to_v3v4DomainConverter(repoPath, hostId, domain, 3, isMsd)
+
+
+def v0v2_to_v4DomainConverter(repoPath, hostId, domain, isMsd):
+    _v0_and_v2_to_v3v4DomainConverter(repoPath, hostId, domain, 4, isMsd)
+
+
+def _v0_and_v2_to_v3v4DomainConverter(repoPath, hostId, domain,
+                                      targetVersion, isMsd):
     log = logging.getLogger('Storage.v3DomainConverter')
 
-    targetVersion = 3
     currentVersion = domain.getVersion()
 
     log.debug("Starting conversion for domain %s from version %s "
               "to version %s", domain.sdUUID, currentVersion, targetVersion)
 
-    targetVersion = 3
     currentVersion = domain.getVersion()
 
     # For block domains if we're upgrading from version 0 we need to first
@@ -349,6 +361,9 @@
     ('0', '2'): v2DomainConverter,
     ('0', '3'): v3DomainConverter,
     ('2', '3'): v3DomainConverter,
+    ('0', '4'): v0v2_to_v4DomainConverter,
+    ('2', '4'): v0v2_to_v4DomainConverter,
+    ('3', '4'): v3_to_v4_DomainConvertor,
 }
 
 
diff --git a/vdsm/storage/sp.py b/vdsm/storage/sp.py
index 0202866..aaba2c0 100644
--- a/vdsm/storage/sp.py
+++ b/vdsm/storage/sp.py
@@ -167,25 +167,7 @@
                     return
 
                 # This can never be the master
-                # Non data domain should not be upgraded
-                domClass = domain.getDomainClass()
-                if domClass != sd.DATA_DOMAIN:
-                    self.log.debug("Domain `%s` is not a data domain it is an "
-                                   "%s domain, not upgrading", sdUUID,
-                                   domClass)
-                else:
-                    domain.invalidateMetadata()
-                    domVersion = domain.getVersion()
-                    if domVersion > targetDomVersion:
-                        self.log.critical("Found a domain with a more advanced"
-                                          " version then the master domain")
-                    elif domVersion < targetDomVersion:
-                        try:
-                            self._convertDomain(domain, str(targetDomVersion))
-                        except:
-                            self.log.warn("Could not upgrade domain `%s`",
-                                          sdUUID, exc_info=True)
-                            return
+                self._upgradeDomainFormat(domain, targetDomVersion)
 
                 self._domainsToUpgrade.remove(sdUUID)
                 if len(self._domainsToUpgrade) == 0:
@@ -196,6 +178,55 @@
                             unregister(self._upgradeCallback)
                     except KeyError:
                         pass
+
+    @unsecured
+    def _upgradeDomainFormat(self, domain, targetDomVersion,
+                             raiseExceptions=False):
+        domClass = domain.getDomainClass()
+        sdUUID = domain.sdUUID
+        # Non data domain should not be upgraded
+        if domClass != sd.DATA_DOMAIN:
+            if raiseExceptions:
+                raise se.CannotUpgradeNonDataDomain
+
+            self.log.debug("Domain `%s` is not a data domain it is an "
+                           "%s domain, not upgrading", sdUUID,
+                           domClass)
+        else:
+            domain.invalidateMetadata()
+            domVersion = domain.getVersion()
+            if domVersion > targetDomVersion:
+                if raiseExceptions:
+                    raise se.CannotUpgradeCurrVersionHigher
+
+                self.log.critical("Found a domain with a more advanced"
+                                  " version then the target version n")
+
+            elif domVersion < targetDomVersion:
+                try:
+                    self._convertDomain(domain, str(targetDomVersion))
+                except Exception as e:
+                    if raiseExceptions:
+                        raise e
+                    self.log.warn("Could not upgrade domain `%s`",
+                                  sdUUID, exc_info=True)
+                    return
+
+    @unsecured
+    def upgradeDomainFormat(self, sdUUID, targetDomVersion):
+        self.validatePoolSD(sdUUID)
+        domain = sdCache.produce(sdUUID)
+        with rmanager.acquireResource(STORAGE, "upgrade_" + sdUUID,
+                                      rm.LockType.exclusive):
+            with rmanager.acquireResource(STORAGE, sdUUID,
+                                          rm.LockType.exclusive):
+                domain.acquireHostId(self.id)
+                try:
+                    domain.acquireClusterLock(self.id)
+                    self._upgradeDomainFormat(domain, targetDomVersion,
+                                              raiseExceptions=True)
+                finally:
+                    domain.releaseClusterLock()
 
     def _updateDomainsRole(self):
         for sdUUID in self.getDomains(activeOnly=True):
@@ -1058,7 +1089,8 @@
         # Remember to get the sdUUID before upgrading because the object is
         # broken after the upgrade
         sdUUID = domain.sdUUID
-        isMsd = (self.masterDomain.sdUUID == sdUUID)
+        isMsd = self.masterDomain is not None and \
+            self.masterDomain.sdUUID == sdUUID
 
         if targetFormat is None:
             targetFormat = self.getFormat()
@@ -1096,7 +1128,21 @@
 
         # Domain conversion requires the links to be present
         self._refreshDomainLinks(dom)
-        self._backend.setDomainRegularRole(dom)
+
+    @unsecured
+    def _performDomainClusterLockOp(self, domain, releaseHostId, method,
+                                    *args, **kwargs):
+        try:
+            domain.acquireHostId(self.id)
+            try:
+                domain.acquireClusterLock(self.id)
+                method(*args, **kwargs)
+            finally:
+                domain.releaseClusterLock()
+        finally:
+            if releaseHostId:
+                domain.releaseHostId(self.id)
+
 
         if dom.getDomainClass() == sd.DATA_DOMAIN:
             self._convertDomain(dom)
diff --git a/vdsm/storage/storage_exception.py b/vdsm/storage/storage_exception.py
index 2077964..50b522b 100644
--- a/vdsm/storage/storage_exception.py
+++ b/vdsm/storage/storage_exception.py
@@ -924,6 +924,24 @@
     code = 443
 
 
+class CannotUpgradeNonDataDomain(StorageException):
+    def __init__(self, sdUUID):
+        self.value = "domain=%s" % sdUUID
+        self.message = ("As the domain `%s` is not a data domain, it is an "
+                        "%s domain an upgrade isn't supported." % (sdUUID,))
+    code = 444
+
+
+class CannotUpgradeCurrVersionHigher(StorageException):
+    def __init__(self, sdUUID, currVersion, targetVersion):
+        self.value = "sdUUID=%s, currentVersion=%s, targetVersion=%s" % \
+                     (sdUUID, currVersion, targetVersion)
+        self.message = ("As the domain `%s` version '%s' is higher then "
+                        "the target version '%s' upgrade cannot be performed" %
+                        (sdUUID, currVersion, targetVersion,))
+    code = 445
+
+
 #################################################
 # Task Exceptions
 #################################################


-- 
To view, visit https://gerrit.ovirt.org/42478
To unsubscribe, visit https://gerrit.ovirt.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: Id8fb87c6e04e48072ec90d07a0f4c7a61411a808
Gerrit-PatchSet: 7
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Liron Aravot <laravot at redhat.com>
Gerrit-Reviewer: Jenkins CI RO
Gerrit-Reviewer: Liron Aravot <laravot at redhat.com>
Gerrit-Reviewer: gerrit-hooks <automation at ovirt.org>


More information about the vdsm-patches mailing list