This is an automated email from the ASF dual-hosted git repository.

bbannier pushed a commit to branch 1.8.x
in repository https://gitbox.apache.org/repos/asf/mesos.git


The following commit(s) were added to refs/heads/1.8.x by this push:
     new 4ce75b8  Gracefully handled duplicated volumes from non-conforming CSI 
plugins.
4ce75b8 is described below

commit 4ce75b824620d30fa8a0a50b2d493b96cd5e714d
Author: Chun-Hung Hsiao <[email protected]>
AuthorDate: Fri Aug 30 13:04:22 2019 +0200

    Gracefully handled duplicated volumes from non-conforming CSI plugins.
    
    If the SLRP uses a plugin that does not conform to the CSI spec and
    reports duplicated volumes, the duplicate would be removed.
    
    This is a backport of `43b86da531a889b1c4b1d7ca6acb2eb924ea01e1`. We
    are not backporting test changes as the original patch relies on
    periodic plugin polling.
    
    Review: https://reviews.apache.org/r/71769
---
 src/resource_provider/storage/provider.cpp | 78 +++++++++++++++++++-----------
 1 file changed, 50 insertions(+), 28 deletions(-)

diff --git a/src/resource_provider/storage/provider.cpp 
b/src/resource_provider/storage/provider.cpp
index 6d63260..e290b3a 100644
--- a/src/resource_provider/storage/provider.cpp
+++ b/src/resource_provider/storage/provider.cpp
@@ -656,8 +656,10 @@ Future<Nothing> 
StorageLocalResourceProviderProcess::recover()
         }
       }
 
-      LOG(INFO) << "Finished recovery for resource provider with type '"
-                << info.type() << "' and name '" << info.name() << "'";
+      LOG(INFO)
+        << "Recovered resources '" << totalResources << "' and "
+        << operations.size() << " operations for resource provider with type '"
+        << info.type() << "' and name '" << info.name() << "'";
 
       state = DISCONNECTED;
 
@@ -1049,45 +1051,73 @@ 
StorageLocalResourceProviderProcess::getExistingVolumes()
 
   return volumeManager->listVolumes()
     .then(defer(self(), [=](const vector<VolumeInfo>& volumeInfos) {
+      // If a volume is duplicated or a volume context has been changed by a
+      // non-conforming CSI plugin, we need to construct a resources conversion
+      // to remove the duplicate and update the metadata, so we maintain the
+      // resources to be removed and those to be added here.
+      Resources toRemove;
+      Resources toAdd;
+
       // Since we only support "exclusive" (MOUNT or BLOCK) disks, there should
       // be only one checkpointed resource for each volume ID.
       hashmap<string, Resource> checkpointedMap;
       foreach (const Resource& resource, totalResources) {
         if (resource.disk().source().has_id()) {
-          CHECK(!checkpointedMap.contains(resource.disk().source().id()));
-          checkpointedMap.put(resource.disk().source().id(), resource);
+          // If the checkpointed resources contain duplicated volumes because 
of
+          // a non-conforming CSI plugin, remove the duplicate.
+          if (checkpointedMap.contains(resource.disk().source().id())) {
+            LOG(WARNING) << "Removing duplicated volume '" << resource
+                         << "' from the total resources";
+
+            toRemove += resource;
+          } else {
+            checkpointedMap.put(resource.disk().source().id(), resource);
+          }
         }
       }
 
       // The "discovered" resources consist of RAW disk resources, one for each
       // volume reported by the CSI plugin.
       Resources discovered;
-
-      // If any volume context has been changed by a non-conforming CSI plugin,
-      // we need to construct a resources conversion to reflect the
-      // corresponding metadata changes, so we maintain the resources to be
-      // removed and those to be added here.
-      Resources metadataToRemove;
-      Resources metadataToAdd;
+      hashset<string> discoveredVolumeIds;
 
       foreach (const VolumeInfo& volumeInfo, volumeInfos) {
-        Option<string> profile;
-        Option<Labels> metadata = volumeInfo.context.empty()
+        const Option<string> profile =
+          checkpointedMap.contains(volumeInfo.id) &&
+          checkpointedMap.at(volumeInfo.id).disk().source().has_profile()
+            ? checkpointedMap.at(volumeInfo.id).disk().source().profile()
+            : Option<string>::none();
+
+        const Option<Labels> metadata = volumeInfo.context.empty()
           ? Option<Labels>::none()
           : convertStringMapToLabels(volumeInfo.context);
 
+        const Resource resource = createRawDiskResource(
+            info,
+            volumeInfo.capacity,
+            profile,
+            vendor,
+            volumeInfo.id,
+            metadata);
+
+        if (discoveredVolumeIds.contains(volumeInfo.id)) {
+          LOG(WARNING) << "Dropping duplicated volume '" << resource
+                       << "' from the discovered resources";
+
+          continue;
+        }
+
+        discovered += resource;
+        discoveredVolumeIds.insert(volumeInfo.id);
+
         if (checkpointedMap.contains(volumeInfo.id)) {
           const Resource& resource = checkpointedMap.at(volumeInfo.id);
 
-          if (resource.disk().source().has_profile()) {
-            profile = resource.disk().source().profile();
-          }
-
           // If the volume context has been changed by a non-conforming CSI
           // plugin, the changes will be reflected in a resource conversion.
           if (resource.disk().source().metadata() !=
               metadata.getOrElse(Labels())) {
-            metadataToRemove += resource;
+            toRemove += resource;
 
             Resource changed = resource;
             if (metadata.isSome()) {
@@ -1097,21 +1127,13 @@ 
StorageLocalResourceProviderProcess::getExistingVolumes()
               changed.mutable_disk()->mutable_source()->clear_metadata();
             }
 
-            metadataToAdd += changed;
+            toAdd += changed;
           }
         }
-
-        discovered += createRawDiskResource(
-            info,
-            volumeInfo.capacity,
-            profile,
-            vendor,
-            volumeInfo.id,
-            metadata);
       }
 
       ResourceConversion metadataConversion(
-          std::move(metadataToRemove), std::move(metadataToAdd));
+          std::move(toRemove), std::move(toAdd));
 
       Resources checkpointed = CHECK_NOTERROR(
           totalResources.filter([](const Resource& resource) {

Reply via email to