none
Mount VHD and create IIS Virtual Directory from code

    Question

  • I'm trying to migrate a CMS System (InsiteCreation) we're using to Windows Azure. I'm done migrating the MsSQL database, what's remaining is the resource folder where user uploaded files gets saved. I don't wish to dig into and rewrite the source code to the CMS system. I figured the easiest way to get this to work is to create a VHD, Mount the VHD, and Create a Virtual Directory in IIS that has the same name as the resource folder, then move the resource folder inside the VHD file and link the Virtual Directory to it.

    I've done some code but I don't get it to run when I deploy it. I'm not able to get any error messages either, and in the window azure administration web ui does it only say unhandled exception.

    I find myself stuck. I can’t figure what causes the unhandled exception or if I should try a different approach. In any case I would appreciate new eyes on the code, perhaps figure how to make the code run or suggestions on other ways to achive the same result.

    Here's the code:

        public class UKSiteRole : RoleEntryPoint
        {
            public override bool OnStart()
            {
                // For information on handling configuration changes
                // see the MSDN topic at http://go.microsoft.com/fwlink/?LinkId=166357.
    
                var cloudDrive = createCloudDrive();
                var drivePath = mountCloudDrive(cloudDrive);
                CreateVirtualDirectory("Resources", drivePath);
                
                return base.OnStart();
            }
    
            private CloudDrive createCloudDrive()
            {
                CloudStorageAccount.SetConfigurationSettingPublisher((configName, configSetter) =>
                {
                    configSetter(RoleEnvironment.GetConfigurationSettingValue("CloudStorageAccount"));
                });
    
                CloudStorageAccount storageAccount = CloudStorageAccount.FromConfigurationSetting("CloudStorageAccount");
                LocalResource localCache = RoleEnvironment.GetLocalResource("BlobCache");
                CloudDrive.InitializeCache(localCache.RootPath, localCache.MaximumSizeInMegabytes);
                CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
                string containerName = "ukvirtualdrive";
                CloudBlobContainer container = new CloudBlobContainer(containerName, blobClient);
                container.CreateIfNotExist();
                // Unmount any previously-mounted drives (Dev fabric seems to need this)
                foreach (var item in CloudDrive.GetMountedDrives())
                {
                    CloudDrive d = new CloudDrive(item.Value, storageAccount.Credentials);
                    d.Unmount();
                }
    
                CloudPageBlob pageBlob = container.GetPageBlobReference("ukVirtualDrive.vhd");
                pageBlob.DeleteIfExists();
                pageBlob.Create(896 * 1024 * 1024);
                CloudDrive cloudDrive = storageAccount.CreateCloudDrive(pageBlob.Uri.AbsoluteUri);
                cloudDrive.CreateIfNotExist(1024);
                return cloudDrive;
            }
    
            private string mountCloudDrive(CloudDrive cloudDrive)
            {
                string driveLetter = cloudDrive.Mount(25, DriveMountOptions.Force);
                Directory.CreateDirectory(Path.Combine(driveLetter, "Resources").ToString());
                return driveLetter;
            }
    
            public static void CreateVirtualDirectory(string VDirName, string driveLetter)
            {
                string vdirWithSlash = "/" + VDirName;
                string strPhysicalPath = driveLetter + VDirName;
                using (var serverManager = new ServerManager())
                {
                    string strSiteName = RoleEnvironment.CurrentRoleInstance.Id + "_" + "Web";
                    Site theSite = serverManager.Sites[strSiteName];
                    foreach (var app in theSite.Applications)
                    {
                        if (app.Path == vdirWithSlash)
                        {
                            // already exists
                            return;
                        }
                    }
    
                    Microsoft.Web.Administration.VirtualDirectory vDir = theSite.Applications[0].VirtualDirectories.Add(vdirWithSlash, strPhysicalPath);
                    serverManager.CommitChanges();
                }
            }
        }

    Monday, June 04, 2012 7:26 AM

Answers

  • Hi ArneHB,

    I was able to get your code working by changing the line: 

    string driveLetter = cloudDrive.Mount(25, DriveMountOptions.Force);

    to

     string driveLetter = cloudDrive.Mount(0, DriveMountOptions.Force);

    Hope this helps.



    Monday, June 25, 2012 4:47 AM

All replies

  • Hi,

    Why dont you login to azure VM through RDP and see the real error logged in to event log on the VM!

    Or is it failing before even spinning up the role instance?


    Veerendra Balla

    Monday, June 04, 2012 5:34 PM
  • Thanks for the reply Veerenda! Yeah this is before the role instance starts, so it's in OnStart() somewhere. I implemented some logging with the diagnostic to windows Azure. The problem seems it's not able to mount the drive. The mounting seems to work in the Compute Emulator environment, but not when i deply it. I get this error: 

    Unknown Error HRESULT=D000000D    at Microsoft.WindowsAzure.StorageClient.CloudDrive.MountAt(String location, Int32 cacheSize, DriveMountOptions options)
      at UKSite.UKSiteRole.mountCloudDrive(CloudDrive cloudDrive) in C:\Users\ac446\documents\visual studio 2010\Projects\InsiteAzure2\UKSite\UKSiteRole.cs:line 125
      at UKSite.UKSiteRole.OnStart() in C:\Users\ac446\documents\visual studio 2010\Projects\InsiteAzure2\UKSite\UKSiteRole.cs:line 38

    When it continues to the virtual directory do I get a permission error:

    Filename: \\?\D:\windows\system32\inetsrv\config\applicationHost.config
    Error: Cannot write configuration file due to insufficient permissions
    Tuesday, June 05, 2012 7:11 AM
  • Hi ArneHB,

    I was able to get your code working by changing the line: 

    string driveLetter = cloudDrive.Mount(25, DriveMountOptions.Force);

    to

     string driveLetter = cloudDrive.Mount(0, DriveMountOptions.Force);

    Hope this helps.



    Monday, June 25, 2012 4:47 AM