bool ProvisionLUDirect(VolumeEntry volumeEntry, string traceId, string size, string sizeType, uint servicePort) { bool fProvisionedLU = false; // Connect to the driver uint lastError = 0; IntPtr hDriver = ConnectToDevice(ref lastError); if (hDriver != INVALID_HANDLE_VALUE) { try { fProvisionedLU = ProvisionLUN(hDriver, volumeEntry.LUID, size, sizeType, volumeEntry.FileSystem, volumeEntry.Mountpoint, servicePort); } finally { // Close the handle to the driver if (!CloseHandle(hDriver)) { TraceWriter.WriteErrorWithId(Constants.TraceSource, traceId, "Unable to close handle to the driver."); } } } else { TraceWriter.WriteErrorWithId(Constants.TraceSource, traceId, String.Format("Unable to provision volume due to error: {0:X}", lastError)); } return(fProvisionedLU); }
// All the field should be set at createVolume step, if so return true void ValidateProvisionLUArgs(VolumeEntry volumeEntry, ref string size, ref string sizeType, ref int servicePort) { if (string.IsNullOrEmpty(volumeEntry.ServicePartitionID)) { throw new ArgumentNullException("ServicePartitionID is NullOrEmpty."); } if (ServiceExists(volumeEntry.ServicePartitionID) == false) { throw new InvalidOperationException("No service instance exists to mount the volume."); } if (string.IsNullOrEmpty(volumeEntry.LUID) || string.IsNullOrEmpty(volumeEntry.SizeDisk) || string.IsNullOrEmpty(volumeEntry.FileSystem)) { throw new ArgumentNullException("Disk information(LUID, SizeDisk, FileSystem) is NullOrEmpty."); } if (string.IsNullOrEmpty(volumeEntry.Mountpoint)) { throw new ArgumentNullException("Mountpoint is NullOrEmpty."); } int iPort = GetServicePort(volumeEntry.ServicePartitionID); if (iPort <= 0) { throw new ArgumentException("Invalid ServicePort specified: " + iPort); } else { servicePort = iPort; } if (!ParseSizeDisk(volumeEntry.SizeDisk, ref size, ref sizeType)) { throw new ArgumentException("Invalid disk size specified: {0}", volumeEntry.SizeDisk); } }
bool ProvisionLU(string name, VolumeEntry volumeEntry, string traceId) { bool provisionSuccessful = false; // Connect the socket to the remote endpoint. Catch any errors. try { string size = ""; string sizeType = ""; int servicePort = 0; this.ValidateProvisionLUArgs(volumeEntry, ref size, ref sizeType, ref servicePort); provisionSuccessful = ProvisionLUDirect(volumeEntry, traceId, size, sizeType, (uint)servicePort); } catch (Exception ex) { TraceWriter.WriteErrorWithId(Constants.TraceSource, traceId, String.Format("Unable to provision volume due to exception: {0}", ex.Message)); provisionSuccessful = false; } return(provisionSuccessful); }
// // Initialize information about any services and volume mounts. // private void Initialize() { string traceId = GetTraceId("VolumeMap.Initialize"); string servicesMetadataPath = Path.Combine(this.serviceContext.CodePackageActivationContext.WorkDirectory, servicesMetadata); Utilities.EnsureFolder(servicesMetadataPath); string servicesMetadataFile = Path.Combine(servicesMetadataPath, servicesMetadataFilenameWithExt); if (File.Exists(servicesMetadataFile)) { this.serviceRWLock.EnterWriteLock(); try { XElement xElementMap = XElement.Load(servicesMetadataFile); foreach (XElement el in xElementMap.Elements()) { serviceMappings.SetElementValue(el.Name.LocalName, el.Value); TraceWriter.WriteInfoWithId(Constants.TraceSource, traceId, String.Format("Read serviceMapping for servicePartitionId {0} and Port {1}", el.Name.LocalName, el.Value)); } } finally { this.serviceRWLock.ExitWriteLock(); } } else { TraceWriter.WriteInfoWithId(Constants.TraceSource, traceId, "No pre-existing Service metadata mappings found."); } string volumesPath = Path.Combine(this.serviceContext.CodePackageActivationContext.WorkDirectory, volumesMetadata); Utilities.EnsureFolder(volumesPath); var volumes = Directory.GetFiles(volumesPath); if (volumes == null || volumes.Length == 0) { TraceWriter.WriteInfoWithId(Constants.TraceSource, traceId, "No pre-existing Volume metadata mappings found."); } foreach (var metadataFile in volumes) { VolumeCreateRequest volume; string mountPoint; if (ReadMetadataFile(metadataFile, out volume, out mountPoint)) { this.volumeMappings[volume.Name] = new VolumeEntry() { VolumeOptions = volume.Opts, ServicePartitionID = volume.Opts[Constants.ServicePartitionID], LUID = volume.Opts[Constants.LUID], SizeDisk = volume.Opts[Constants.SizeDisk], #if DotNetCoreClrLinux FileSystem = "EXT4", #else FileSystem = volume.Opts[Constants.FileSystem], #endif Mountpoint = mountPoint }; VolumeEntry volumeEntry = this.volumeMappings[volume.Name]; TraceWriter.WriteInfoWithId(Constants.TraceSource, traceId, String.Format("Read volumeMapping for Volume:{0}, servicePartitionId:{1}, LUID:{2}, sizeDisk:{3}, fileSystem:{4}, mountPoint:{5}", volume.Name, volumeEntry.ServicePartitionID, volumeEntry.LUID, volumeEntry.SizeDisk, volumeEntry.FileSystem, volumeEntry.Mountpoint)); } } TraceWriter.WriteInfoWithId(Constants.TraceSource, traceId, "Volume map initialized."); }
public Response MountVolume(VolumeMountRequest request, string traceId) { if (!this.VolumeExists(request.Name)) { string errorMessage = String.Format("Attempt to mount volume {0} that does not exist.", request.Name); TraceWriter.WriteErrorWithId(Constants.TraceSource, traceId, errorMessage); return(new Response(errorMessage)); } this.volumeRWLock.EnterWriteLock(); try { if (!volumeMappings.ContainsKey(request.Name)) { string errorMessage = String.Format("Mapping for volume {0} was not found.", request.Name); TraceWriter.WriteErrorWithId(Constants.TraceSource, traceId, errorMessage); return(new Response(errorMessage)); } VolumeEntry volumeEntry = this.volumeMappings[request.Name]; string volumeDetails = String.Format("Volume:{0}, servicePartitionId:{1}, LUID:{2}, sizeDisk:{3}, fileSystem:{4}", request.Name, volumeEntry.ServicePartitionID, volumeEntry.LUID, volumeEntry.SizeDisk, volumeEntry.FileSystem); TraceWriter.WriteInfoWithId(Constants.TraceSource, traceId, String.Format("Processing mount request: {0}", volumeDetails)); bool fVolumeProvisioned = false; if (!System.IO.Directory.Exists(volumeEntry.Mountpoint)) { // The folder created here is which volume will be mounted System.IO.Directory.CreateDirectory(volumeEntry.Mountpoint); // Give built-in users access to the folder if (SetMountpointRWAccessForUsers(volumeEntry.Mountpoint, traceId)) { // Provision the volume TraceWriter.WriteInfoWithId(Constants.TraceSource, traceId, String.Format("Provisioning volume: {0}", volumeDetails)); fVolumeProvisioned = this.ProvisionLU(request.Name, volumeEntry, traceId); } // If volume provisioning fails, delete the mountpoint folder if (!fVolumeProvisioned) { System.IO.Directory.Delete(volumeEntry.Mountpoint); } } else { #if DotNetCoreClrLinux TraceWriter.WriteInfoWithId(Constants.TraceSource, traceId, "Attempting Umount before provisioning volume."); var returnValue = umount(volumeEntry.Mountpoint); TraceWriter.WriteInfoWithId(Constants.TraceSource, traceId, "Umount returned " + returnValue); #endif // Connect to BlockStore Native Service and send ProvisionLU cmd TraceWriter.WriteInfoWithId(Constants.TraceSource, traceId, String.Format("Provisioning existing mountpoint for volume: {0}", volumeDetails)); fVolumeProvisioned = this.ProvisionLU(request.Name, volumeEntry, traceId); } if (!fVolumeProvisioned) { string errorMessage = String.Format("Unable to provision volume: {0}", volumeDetails); TraceWriter.WriteErrorWithId(Constants.TraceSource, traceId, errorMessage); return(new Response(errorMessage)); } else { TraceWriter.WriteInfoWithId(Constants.TraceSource, traceId, String.Format("Successfully provisioned volume: {0}", volumeDetails)); } volumeEntry.MountIDs.Add(request.ID); ++volumeEntry.NumberOfMounts; #if DotNetCoreClrLinux Interlocked.Increment(ref BSDockerVolumePlugin.SynchronizedKestrelCommunicationListener.TotalMountedVolumesOnNode); #endif return(new VolumeMountResponse(volumeEntry.Mountpoint)); } catch (Exception ex) { string errorMesg = String.Format("Unable to mount volume {0} due to exception: {1}", request.Name, ex.Message); TraceWriter.WriteErrorWithId(Constants.TraceSource, traceId, errorMesg); return(new Response(errorMesg)); } finally { this.volumeRWLock.ExitWriteLock(); } }