| 1051 | |
| 1052 | |
| 1053 | Future<Nothing> VolumeManagerProcess::__publishVolume(const string& volumeId) |
| 1054 | { |
| 1055 | CHECK(volumes.contains(volumeId)); |
| 1056 | VolumeState& volumeState = volumes.at(volumeId).state; |
| 1057 | |
| 1058 | if (volumeState.state() == VolumeState::VOL_READY) { |
| 1059 | CHECK(!volumeState.boot_id().empty()); |
| 1060 | return Nothing(); |
| 1061 | } |
| 1062 | |
| 1063 | if (volumeState.state() != VolumeState::NODE_READY && |
| 1064 | volumeState.state() != VolumeState::NODE_STAGE && |
| 1065 | volumeState.state() != VolumeState::NODE_UNSTAGE) { |
| 1066 | // Retry after transitioning the volume to `NODE_READY` state. |
| 1067 | return _attachVolume(volumeId) |
| 1068 | .then(process::defer(self(), &Self::__publishVolume, volumeId)); |
| 1069 | } |
| 1070 | |
| 1071 | if (!nodeCapabilities->stageUnstageVolume) { |
| 1072 | // Since this is a no-op, no need to checkpoint here. |
| 1073 | volumeState.set_state(VolumeState::VOL_READY); |
| 1074 | volumeState.set_boot_id(CHECK_NOTNONE(bootId)); |
| 1075 | return Nothing(); |
| 1076 | } |
| 1077 | |
| 1078 | // A previously failed `NodeUnstageVolume` call can be recovered through an |
| 1079 | // extra `NodeUnstageVolume` call. See: |
| 1080 | // https://github.com/container-storage-interface/spec/blob/v1.1.0/spec.md#nodeunstagevolume // NOLINT |
| 1081 | if (volumeState.state() == VolumeState::NODE_UNSTAGE) { |
| 1082 | // Retry after recovering the volume to `NODE_READY` state. |
| 1083 | return _unpublishVolume(volumeId) |
| 1084 | .then(process::defer(self(), &Self::__publishVolume, volumeId)); |
| 1085 | } |
| 1086 | |
| 1087 | const string stagingPath = paths::getMountStagingPath(mountRootDir, volumeId); |
| 1088 | |
| 1089 | // NOTE: The staging path will be cleaned up in during volume removal. |
| 1090 | Try<Nothing> mkdir = os::mkdir(stagingPath); |
| 1091 | if (mkdir.isError()) { |
| 1092 | return Failure( |
| 1093 | "Failed to create mount staging path '" + stagingPath + |
| 1094 | "': " + mkdir.error()); |
| 1095 | } |
| 1096 | |
| 1097 | if (volumeState.state() == VolumeState::NODE_READY) { |
| 1098 | volumeState.set_state(VolumeState::NODE_STAGE); |
| 1099 | checkpointVolumeState(volumeId); |
| 1100 | } |
| 1101 | |
| 1102 | LOG(INFO) << "Calling '/csi.v1.Node/NodeStageVolume' for volume '" << volumeId |
| 1103 | << "'"; |
| 1104 | |
| 1105 | NodeStageVolumeRequest request; |
| 1106 | request.set_volume_id(volumeId); |
| 1107 | *request.mutable_publish_context() = volumeState.publish_context(); |
| 1108 | request.set_staging_target_path(stagingPath); |
| 1109 | *request.mutable_volume_capability() = |
| 1110 | evolve(volumeState.volume_capability()); |
nothing calls this directly
no test coverage detected