Example #1
0
        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);
        }
Example #2
0
        // 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);
            }
        }
Example #3
0
        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);
        }
Example #4
0
        //
        // 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.");
        }
Example #5
0
        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();
            }
        }