| 283 | |
| 284 | |
| 285 | Future<VolumeInfo> VolumeManagerProcess::createVolume( |
| 286 | const string& name, |
| 287 | const Bytes& capacity, |
| 288 | const CSIVolume::VolumeCapability& capability, |
| 289 | const Map<string, string>& parameters) |
| 290 | { |
| 291 | if (!controllerCapabilities->createDeleteVolume) { |
| 292 | return Failure( |
| 293 | "CREATE_DELETE_VOLUME controller capability is not supported for CSI " |
| 294 | "plugin type '" + info.type() + "' and name '" + info.name()); |
| 295 | } |
| 296 | |
| 297 | LOG(INFO) << "Creating volume with name '" << name << "'"; |
| 298 | |
| 299 | CreateVolumeRequest request; |
| 300 | request.set_name(name); |
| 301 | request.mutable_capacity_range()->set_required_bytes(capacity.bytes()); |
| 302 | request.mutable_capacity_range()->set_limit_bytes(capacity.bytes()); |
| 303 | *request.add_volume_capabilities() = evolve(capability); |
| 304 | *request.mutable_parameters() = parameters; |
| 305 | |
| 306 | // We retry the `CreateVolume` call for MESOS-9517. |
| 307 | return call( |
| 308 | CONTROLLER_SERVICE, &Client::createVolume, std::move(request), true) |
| 309 | .then(process::defer(self(), [=]( |
| 310 | const CreateVolumeResponse& response) -> Future<VolumeInfo> { |
| 311 | const string& volumeId = response.volume().volume_id(); |
| 312 | |
| 313 | // NOTE: If the volume is already tracked, there might already be |
| 314 | // operations running in its sequence. Since this continuation runs |
| 315 | // outside the sequence, we fail the call here to avoid any race issue. |
| 316 | // This also means that this call is not idempotent. |
| 317 | if (volumes.contains(volumeId)) { |
| 318 | return Failure("Volume with name '" + name + "' already exists"); |
| 319 | } |
| 320 | |
| 321 | VolumeState volumeState; |
| 322 | volumeState.set_state(VolumeState::CREATED); |
| 323 | *volumeState.mutable_volume_capability() = capability; |
| 324 | *volumeState.mutable_parameters() = parameters; |
| 325 | *volumeState.mutable_volume_context() = |
| 326 | response.volume().volume_context(); |
| 327 | |
| 328 | volumes.put(volumeId, std::move(volumeState)); |
| 329 | checkpointVolumeState(volumeId); |
| 330 | |
| 331 | return VolumeInfo{capacity, volumeId, response.volume().volume_context()}; |
| 332 | })); |
| 333 | } |
| 334 | |
| 335 | |
| 336 | Future<Option<Error>> VolumeManagerProcess::validateVolume( |