| 741 | |
| 742 | |
| 743 | Future<bool> VolumeManagerProcess::_deleteVolume(const std::string& volumeId) |
| 744 | { |
| 745 | CHECK(volumes.contains(volumeId)); |
| 746 | VolumeState& volumeState = volumes.at(volumeId).state; |
| 747 | |
| 748 | if (volumeState.node_publish_required()) { |
| 749 | CHECK_EQ(VolumeState::PUBLISHED, volumeState.state()); |
| 750 | |
| 751 | const string targetPath = paths::getMountTargetPath(mountRootDir, volumeId); |
| 752 | |
| 753 | // NOTE: Normally the volume should have been cleaned up. However this may |
| 754 | // not be true for preprovisioned volumes (e.g., leftover from a previous |
| 755 | // resource provider instance). To prevent data leakage in such cases, we |
| 756 | // clean up the data (but not the target path) here. |
| 757 | Try<Nothing> rmdir = os::rmdir(targetPath, true, false); |
| 758 | if (rmdir.isError()) { |
| 759 | return Failure( |
| 760 | "Failed to clean up volume '" + volumeId + "': " + rmdir.error()); |
| 761 | } |
| 762 | |
| 763 | volumeState.set_node_publish_required(false); |
| 764 | checkpointVolumeState(volumeId); |
| 765 | } |
| 766 | |
| 767 | if (volumeState.state() != VolumeState::CREATED) { |
| 768 | // Retry after transitioning the volume to `CREATED` state. |
| 769 | return _detachVolume(volumeId) |
| 770 | .then(process::defer(self(), &Self::_deleteVolume, volumeId)); |
| 771 | } |
| 772 | |
| 773 | // NOTE: The last asynchronous continuation, which is supposed to be run in |
| 774 | // the volume's sequence, would cause the sequence to be destructed, which |
| 775 | // would in turn discard the returned future. However, since the continuation |
| 776 | // would have already been run, the returned future will become ready, making |
| 777 | // the future returned by the sequence ready as well. |
| 778 | return __deleteVolume(volumeId) |
| 779 | .then(process::defer(self(), [this, volumeId](bool deleted) { |
| 780 | removeVolume(volumeId); |
| 781 | |
| 782 | return deleted; |
| 783 | })); |
| 784 | } |
| 785 | |
| 786 | |
| 787 | Future<bool> VolumeManagerProcess::__deleteVolume( |