You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by ch...@apache.org on 2018/04/13 03:39:21 UTC

[3/3] mesos git commit: Added `STAGE_UNSTAGE_VOLUME` capability to the test CSI plugin.

Added `STAGE_UNSTAGE_VOLUME` capability to the test CSI plugin.

Now it is required to call `NodeStageVolume` before `NodePublishVolume`
for the test CSI plugin. `NodeStageVolume` would bind-mount the volume
directory to the specified staging path, and then `NodePublishVolume`
would bind-mount the staging path to the target path.

Review: https://reviews.apache.org/r/66576/


Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/5a105893
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/5a105893
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/5a105893

Branch: refs/heads/master
Commit: 5a105893acbae841f68fe95c109a6ff3c3fd63a9
Parents: a9aa3ad
Author: Chun-Hung Hsiao <ch...@apache.org>
Authored: Thu Apr 12 19:42:29 2018 -0700
Committer: Chun-Hung Hsiao <ch...@mesosphere.io>
Committed: Thu Apr 12 19:42:29 2018 -0700

----------------------------------------------------------------------
 src/examples/test_csi_plugin.cpp | 144 +++++++++++++++++++++++++++++++++-
 1 file changed, 140 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/5a105893/src/examples/test_csi_plugin.cpp
----------------------------------------------------------------------
diff --git a/src/examples/test_csi_plugin.cpp b/src/examples/test_csi_plugin.cpp
index 357e022..9c4da88 100644
--- a/src/examples/test_csi_plugin.cpp
+++ b/src/examples/test_csi_plugin.cpp
@@ -216,6 +216,16 @@ public:
       const csi::v0::ControllerGetCapabilitiesRequest* request,
       csi::v0::ControllerGetCapabilitiesResponse* response) override;
 
+  virtual Status NodeStageVolume(
+      ServerContext* context,
+      const csi::v0::NodeStageVolumeRequest* request,
+      csi::v0::NodeStageVolumeResponse* response) override;
+
+  virtual Status NodeUnstageVolume(
+      ServerContext* context,
+      const csi::v0::NodeUnstageVolumeRequest* request,
+      csi::v0::NodeUnstageVolumeResponse* response) override;
+
   virtual Status NodePublishVolume(
       ServerContext* context,
       const csi::v0::NodePublishVolumeRequest* request,
@@ -594,6 +604,112 @@ Status TestCSIPlugin::ControllerGetCapabilities(
 }
 
 
+Status TestCSIPlugin::NodeStageVolume(
+    ServerContext* context,
+    const csi::v0::NodeStageVolumeRequest* request,
+    csi::v0::NodeStageVolumeResponse* response)
+{
+  LOG(INFO) << request->GetDescriptor()->name() << " '" << *request << "'";
+
+  // TODO(chhsiao): Validate required fields.
+
+  if (!volumes.contains(request->volume_id())) {
+    return Status(
+        grpc::NOT_FOUND,
+        "Volume '" + request->volume_id() + "' is not found");
+  }
+
+  const VolumeInfo& volumeInfo = volumes.at(request->volume_id());
+  const string path = getVolumePath(volumeInfo);
+
+  auto it = request->volume_attributes().find("path");
+  if (it == request->volume_attributes().end() || it->second != path) {
+    return Status(grpc::INVALID_ARGUMENT, "Invalid volume attributes");
+  }
+
+  if (!os::exists(request->staging_target_path())) {
+    return Status(
+        grpc::INVALID_ARGUMENT,
+        "Target path '" + request->staging_target_path() + "' is not found");
+  }
+
+  Try<fs::MountInfoTable> table = fs::MountInfoTable::read();
+  if (table.isError()) {
+    return Status(
+        grpc::INTERNAL,
+        "Failed to get mount table: " + table.error());
+  }
+
+  foreach (const fs::MountInfoTable::Entry& entry, table->entries) {
+    if (entry.target == request->staging_target_path()) {
+      return Status::OK;
+    }
+  }
+
+  Try<Nothing> mount = fs::mount(
+      path,
+      request->staging_target_path(),
+      None(),
+      MS_BIND,
+      None());
+
+  if (mount.isError()) {
+    return Status(
+        grpc::INTERNAL,
+        "Failed to mount from '" + path + "' to '" +
+        request->staging_target_path() + "': " + mount.error());
+  }
+
+  return Status::OK;
+}
+
+
+Status TestCSIPlugin::NodeUnstageVolume(
+    ServerContext* context,
+    const csi::v0::NodeUnstageVolumeRequest* request,
+    csi::v0::NodeUnstageVolumeResponse* response)
+{
+  LOG(INFO) << request->GetDescriptor()->name() << " '" << *request << "'";
+
+  // TODO(chhsiao): Validate required fields.
+
+  if (!volumes.contains(request->volume_id())) {
+    return Status(
+        grpc::NOT_FOUND,
+        "Volume '" + request->volume_id() + "' is not found");
+  }
+
+  Try<fs::MountInfoTable> table = fs::MountInfoTable::read();
+  if (table.isError()) {
+    return Status(
+        grpc::INTERNAL,
+        "Failed to get mount table: " + table.error());
+  }
+
+  bool found = false;
+  foreach (const fs::MountInfoTable::Entry& entry, table->entries) {
+    if (entry.target == request->staging_target_path()) {
+      found = true;
+      break;
+    }
+  }
+
+  if (!found) {
+    return Status::OK;
+  }
+
+  Try<Nothing> unmount = fs::unmount(request->staging_target_path());
+  if (unmount.isError()) {
+    return Status(
+        grpc::INTERNAL,
+        "Failed to unmount '" + request->staging_target_path() +
+        "': " + unmount.error());
+  }
+
+  return Status::OK;
+}
+
+
 Status TestCSIPlugin::NodePublishVolume(
     ServerContext* context,
     const csi::v0::NodePublishVolumeRequest* request,
@@ -623,6 +739,12 @@ Status TestCSIPlugin::NodePublishVolume(
         "Target path '" + request->target_path() + "' is not found");
   }
 
+  if (request->staging_target_path().empty()) {
+    return Status(
+        grpc::FAILED_PRECONDITION,
+        "Expecting 'staging_target_path' to be set");
+  }
+
   Try<fs::MountInfoTable> table = fs::MountInfoTable::read();
   if (table.isError()) {
     return Status(
@@ -630,6 +752,20 @@ Status TestCSIPlugin::NodePublishVolume(
         "Failed to get mount table: " + table.error());
   }
 
+  bool found = false;
+  foreach (const fs::MountInfoTable::Entry& entry, table->entries) {
+    if (entry.target == request->staging_target_path()) {
+      found = true;
+      break;
+    }
+  }
+
+  if (!found) {
+    return Status(
+        grpc::FAILED_PRECONDITION,
+        "Volume '" + request->volume_id() + "' has not been staged yet");
+  }
+
   foreach (const fs::MountInfoTable::Entry& entry, table->entries) {
     if (entry.target == request->target_path()) {
       return Status::OK;
@@ -637,7 +773,7 @@ Status TestCSIPlugin::NodePublishVolume(
   }
 
   Try<Nothing> mount = fs::mount(
-      path,
+      request->staging_target_path(),
       request->target_path(),
       None(),
       MS_BIND,
@@ -700,9 +836,6 @@ Status TestCSIPlugin::NodeUnpublishVolume(
     return Status::OK;
   }
 
-  const VolumeInfo& volumeInfo = volumes.at(request->volume_id());
-  const string path = getVolumePath(volumeInfo);
-
   Try<Nothing> unmount = fs::unmount(request->target_path());
   if (unmount.isError()) {
     return Status(
@@ -735,6 +868,9 @@ Status TestCSIPlugin::NodeGetCapabilities(
 {
   LOG(INFO) << request->GetDescriptor()->name() << " '" << *request << "'";
 
+  response->add_capabilities()->mutable_rpc()->set_type(
+      csi::v0::NodeServiceCapability::RPC::STAGE_UNSTAGE_VOLUME);
+
   return Status::OK;
 }