| 719 | |
| 720 | |
| 721 | Future<bool> VolumeManagerProcess::_deleteVolume(const std::string& volumeId) |
| 722 | { |
| 723 | CHECK(volumes.contains(volumeId)); |
| 724 | VolumeState& volumeState = volumes.at(volumeId).state; |
| 725 | |
| 726 | if (volumeState.node_publish_required()) { |
| 727 | CHECK_EQ(VolumeState::PUBLISHED, volumeState.state()); |
| 728 | |
| 729 | const string targetPath = paths::getMountTargetPath(mountRootDir, volumeId); |
| 730 | |
| 731 | // NOTE: Normally the volume should have been cleaned up. However this may |
| 732 | // not be true for preprovisioned volumes (e.g., leftover from a previous |
| 733 | // resource provider instance). To prevent data leakage in such cases, we |
| 734 | // clean up the data (but not the target path) here. |
| 735 | Try<Nothing> rmdir = os::rmdir(targetPath, true, false); |
| 736 | if (rmdir.isError()) { |
| 737 | return Failure( |
| 738 | "Failed to clean up volume '" + volumeId + "': " + rmdir.error()); |
| 739 | } |
| 740 | |
| 741 | volumeState.set_node_publish_required(false); |
| 742 | checkpointVolumeState(volumeId); |
| 743 | } |
| 744 | |
| 745 | if (volumeState.state() != VolumeState::CREATED) { |
| 746 | // Retry after transitioning the volume to `CREATED` state. |
| 747 | return _detachVolume(volumeId) |
| 748 | .then(process::defer(self(), &Self::_deleteVolume, volumeId)); |
| 749 | } |
| 750 | |
| 751 | // NOTE: The last asynchronous continuation, which is supposed to be run in |
| 752 | // the volume's sequence, would cause the sequence to be destructed, which |
| 753 | // would in turn discard the returned future. However, since the continuation |
| 754 | // would have already been run, the returned future will become ready, making |
| 755 | // the future returned by the sequence ready as well. |
| 756 | return __deleteVolume(volumeId) |
| 757 | .then(process::defer(self(), [this, volumeId](bool deleted) { |
| 758 | removeVolume(volumeId); |
| 759 | |
| 760 | return deleted; |
| 761 | })); |
| 762 | } |
| 763 | |
| 764 | |
| 765 | Future<bool> VolumeManagerProcess::__deleteVolume( |