| 1012 | |
| 1013 | |
| 1014 | Future<Nothing> VolumeManagerProcess::__publishVolume(const string& volumeId) |
| 1015 | { |
| 1016 | CHECK(volumes.contains(volumeId)); |
| 1017 | VolumeState& volumeState = volumes.at(volumeId).state; |
| 1018 | |
| 1019 | if (volumeState.state() == VolumeState::VOL_READY) { |
| 1020 | CHECK(!volumeState.boot_id().empty()); |
| 1021 | return Nothing(); |
| 1022 | } |
| 1023 | |
| 1024 | if (volumeState.state() != VolumeState::NODE_READY && |
| 1025 | volumeState.state() != VolumeState::NODE_STAGE && |
| 1026 | volumeState.state() != VolumeState::NODE_UNSTAGE) { |
| 1027 | // Retry after transitioning the volume to `NODE_READY` state. |
| 1028 | return _attachVolume(volumeId) |
| 1029 | .then(process::defer(self(), &Self::__publishVolume, volumeId)); |
| 1030 | } |
| 1031 | |
| 1032 | if (!nodeCapabilities->stageUnstageVolume) { |
| 1033 | // Since this is a no-op, no need to checkpoint here. |
| 1034 | volumeState.set_state(VolumeState::VOL_READY); |
| 1035 | volumeState.set_boot_id(CHECK_NOTNONE(bootId)); |
| 1036 | return Nothing(); |
| 1037 | } |
| 1038 | |
| 1039 | // A previously failed `NodeUnstageVolume` call can be recovered through an |
| 1040 | // extra `NodeUnstageVolume` call. See: |
| 1041 | // https://github.com/container-storage-interface/spec/blob/v0.2.0/spec.md#nodeunstagevolume // NOLINT |
| 1042 | if (volumeState.state() == VolumeState::NODE_UNSTAGE) { |
| 1043 | // Retry after recovering the volume to `NODE_READY` state. |
| 1044 | return _unpublishVolume(volumeId) |
| 1045 | .then(process::defer(self(), &Self::__publishVolume, volumeId)); |
| 1046 | } |
| 1047 | |
| 1048 | const string stagingPath = paths::getMountStagingPath(mountRootDir, volumeId); |
| 1049 | |
| 1050 | // NOTE: The staging path will be cleaned up in during volume removal. |
| 1051 | Try<Nothing> mkdir = os::mkdir(stagingPath); |
| 1052 | if (mkdir.isError()) { |
| 1053 | return Failure( |
| 1054 | "Failed to create mount staging path '" + stagingPath + |
| 1055 | "': " + mkdir.error()); |
| 1056 | } |
| 1057 | |
| 1058 | if (volumeState.state() == VolumeState::NODE_READY) { |
| 1059 | volumeState.set_state(VolumeState::NODE_STAGE); |
| 1060 | checkpointVolumeState(volumeId); |
| 1061 | } |
| 1062 | |
| 1063 | LOG(INFO) << "Calling '/csi.v0.Node/NodeStageVolume' for volume '" << volumeId |
| 1064 | << "'"; |
| 1065 | |
| 1066 | NodeStageVolumeRequest request; |
| 1067 | request.set_volume_id(volumeId); |
| 1068 | *request.mutable_publish_info() = volumeState.publish_context(); |
| 1069 | request.set_staging_target_path(stagingPath); |
| 1070 | *request.mutable_volume_capability() = |
| 1071 | evolve(volumeState.volume_capability()); |
nothing calls this directly
no test coverage detected