Follow Me Widget

четверг, 25 августа 2011 г.

Windows Azure Drives. Особенности использования.

Windows Azure Drive – это виртуальный диск (VHD), работающий под управлением файловой системы NTFS и функционирующий на основе страничного блоба. Диски обеспечивают постоянное хранилище для наших ролей. Это значит, что содержимое таких дисков остается неизменным даже после перезапуска роли. Сегодня мы познакомимся чуть более подробно с особенностями взаимодействия с дисками на примере тестового приложения, выводящего список файлов в определенном каталоге на диске.
Итак, в первую очередь создадим новое облачное решение в VS 2010  и добавим к нему Web-роль на основе ASP.NET MVC 3, которая будет показывать нам содержимое нашего диска. Сначала нам необходимо будет добавить ссылку на сборку Microsoft.WindowsAzure.CloudDrive.dll так как по умолчанию она отсутствует во всех облачных темплейтах VS 2010.


Windows Azure Cloud Drive Assembly

После этого  необходимо задать основные настройки приложения, которые в дальнейшем обязательно понадобятся. Для этого перейдем в раздел настроек роли и добавим туда 3 основных параметра, показанных на рисунке ниже:

Windows Azure Drives Settings

Параметр DataConnectionString представляет собой строку соединения с Windows Azure Storage. Параметр PageBlobURI представляет собой уникальное имя блоба, на который в дальнейшем будет проецироваться диск. Кроме того необходимо настроить локальное хранилище, которое будет выступать  в качестве локального кеша для используемого диска.

Local Storage Cache

После завершения настройки можно перейти к самому приложению. Наиболее интересная его часть сосредоточена в Global.asax, где происходит создание и монтирование диска. Давайте посмотрим на специфику этого процесса. 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using Microsoft.WindowsAzure;
using Microsoft.WindowsAzure.ServiceRuntime;
using Microsoft.WindowsAzure.StorageClient;
using System.Diagnostics;

namespace MvcWebRole1
{
// Note: For instructions on enabling IIS6 or IIS7 classic mode, 
// visit http://go.microsoft.com/?LinkId=9394801

      public class MvcApplication : System.Web.HttpApplication
    {
       public static string FilesPath { get; set; }

       public static void RegisterGlobalFilters(GlobalFilterCollection filters)
      {
        filters.Add(new HandleErrorAttribute());
      }

       public static void RegisterRoutes(RouteCollection routes)
      {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        routes.MapRoute(
         "Default", // Route name
         "{controller}/{action}/{id}", // URL with parameters
         new { controller = "Home", action = "Index", id = UrlParameter.Optional });
      }

       protected void Application_Start()
      {
        AreaRegistration.RegisterAllAreas();
        RegisterGlobalFilters(GlobalFilters.Filters);
        RegisterRoutes(RouteTable.Routes);
        MountDrive();
      }

       protected void MountDrive()
      {
         // инициализация аккаунта
         CloudStorageAccount.SetConfigurationSettingPublisher((configName, configSetter) =>
          {
            string connectionString = RoleEnvironment.GetConfigurationSettingValue(configName);
            configSetter(connectionString);
           });

         try
       {
          // инициализация локального кеша для Windows Azure Drive
          LocalResource cache = RoleEnvironment.GetLocalResource("LocalDriveCache");
          CloudDrive.InitializeCache(cache.RootPath + "cache", cache.MaximumSizeInMegabytes);

          // получение аккаунта 
         CloudStorageAccount account = CloudStorageAccount.FromConfigurationSetting("DataConnectionString");

         // получение уникального адреса блоба, на который будет проецироваться диск 
         string imageStoreBlobUri = RoleEnvironment.GetConfigurationSettingValue("PageBlobURI");

         // создание диска и ассоциированного с ним блоба
         CloudDrive imageStoreDrive = account.CreateCloudDrive(imageStoreBlobUri);
         try
       {
         imageStoreDrive.Create(16);
       }
        catch (CloudDriveException)
      {
          // диск уже существует
      }

       // монтирование диска и сохранение нового места хранения файлов
       FilesPath = imageStoreDrive.Mount(cache.MaximumSizeInMegabytes / 2, DriveMountOptions.None);
      }
      catch (CloudDriveException driveException)
    {
       Trace.WriteLine("Error: " + driveException.Message);
    }
  }
     public void Application_End(object sender, EventArgs e)
   {
     // obtain a reference to the cloud drive and unmount it
     CloudStorageAccount account = CloudStorageAccount.FromConfigurationSetting("DataConnectionString");
     string imageStoreBlobUri = RoleEnvironment.GetConfigurationSettingValue("PageBlobURI");
     CloudDrive imageStoreDrive = account.CreateCloudDrive(imageStoreBlobUri);
     imageStoreDrive.Unmount();
   }
}
}

Наибольшего внимания заслуживает метод MountDrive, который вызывается на событии Application_Start. Не будем углубляться в подробности (думаю по комментариям смысл метода будет понятен), но в целом сначала нам необходимо настроить локальный кеш, после чего получить валидную строку соединения с хранилищем и в конце концов создать и примонтировать к текущей роли диск с данными. На этом этап настройки диска закончен и можно приступить к получения списка файлов на диске. Давайте посмотрим на файл HomeController.cs, который ответственен за это.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.IO;
using MvcWebRole1.Models;
using Microsoft.WindowsAzure.StorageClient;

namespace MvcWebRole1.Controllers
{
    public class HomeController : Controller
    {
        public ActionResult Index()
       {
         return View(new DriveInfoModel
         {
          DriveFiles = new DirectoryInfo(MvcApplication.FilesPath).GetFiles(),
          MountedDrives = CloudDrive.GetMountedDrives().ToDictionary(entry => entry.Key, entry => entry.Value.ToString())
         });
        }

         public ActionResult About()
        {
           return View();
        }
    }
}

Как видим код очень прост. Все, что мы делаем это получаем список файлов на диске и дополнительно список примонтированных дисков так сказать для справочной информации. После чего передаем нашу кастомную модель-контейнер во вьюху. Код самой вьюхи также чрезвычайно прост.
@model MvcWebRole1.Models.DriveInfoModel
   @{
     ViewBag.Title = "Home Page";
    }

    <h2>@ViewBag.Message</h2>

    Mounted Drives: 
      @Html.DropDownListFor(model => model.MountedDrives, new SelectList(Model.MountedDrives))

    Mounted Drive Files:
      <table>
      @foreach (var file in Model.DriveFiles) {
        <tr>
          <td>
          @file.Name
          </td>
          <td>
          @file.Length
          </td>
          <td>
          @file.CreationTime
          </td>
          <td>
          @file.LastWriteTime
          </td>
        </tr> 
      } 
      </table>

В разметке мы отображаем полученную от контроллера информацию в приемлемом виде. В итоге, после запуска мы получим на экране следующую картинку:

Windows Azure Drive

Как видим мы смонтировали один диск, которому была присвоена метка A:, а также уникальный адрес блоба. Самих файлов мы не видим так как диск только что создан и он пуст. Мы запустили приложение локально поэтому для того, чтобы добраться до локально смонтированного диска необходимо открыть Local Storage Emulator и выбрать пункт меню File > Open Azure Drive Folder in Window Explorer

Local Storage Emulator

После этого откроется место хранения смонтированного диска куда для теста мы отправим несколько файлов. В итоге приложение среагирует на наше действие и выведет на странице список недавно добавленных файлов.

Windows Azure Drive

На данный момент наше приложение работает локально поэтому для того, чтобы запустить его в облаке нам необходимо загрузить наш диск в удаленное хранилище. Для этого мы можем сперва создать VHD-файл у себя на машине, после чего загрузить его в хранилище блобов. Для создание VHD-файла можно воспользоваться встроенными  в Windows 7 возможностями по работе с виртуальными дисками. Отправной точкой в процессе создания диска является консоль “Управление дисками” (добраться до нее можно выполнив команду diskmgmt.msc). Сперва нам необходимо создать диск – за это отвечает пункт меню Действие > Создать виртуальный диск. В открывшемся окне необходимо выбрать место хранения диска, а также его размер.

VHD Creation Wizard

Как только диск будет создан, его можно будет увидеть в консоли управления дисками. Следующим шагом необходимо инициализировать диск.

VHD Initialization

После успешной инициализации следует перейти к мастеру создания новых томов. Для этого кликнем правой кнопкой мыши на неразмеченном пространстве виртуального диска и выберем пункт “Создать простой том”. При выборе этой команды откроется всем знакомый мастер по созданию новых томов, который предложит нам пройти несколько шагов для завершения процедуры. Как только она завершится мы увидим в Windows Explorer успешно смонтированный диск. У меня он получил метку G: и называется Files Drive.

Local Computer Hard Drives

Диск готов, осталось скопировать на него пару файлов и подготовить к загрузке в облако. Уверен процедура копирования файлов не вызовет у вас проблем поэтому перейдем к стадии загрузки. Для этих целей мы можем воспользоваться бесплатной командной утилиткой от Microsoft, при помощи которой можно загрузить VHD-файл в облако. Утилита принимает 3 параметра:

  • Место хранения VHD-файла на локальном компьютере
  • Название блоба, который будет создан по окончании загрузки
  • Идентификатор storage-аккаунта
  • Ключ доступа к хранилищу
В моем случае получилась следующая строка:

vhdupload D:\FilesDrive.vhd mydrives/Files.vhd feschenkoalex [my secret storage key]

После запуска команды ждем пока диск загрузиться и по завершению переходим обратно к нашему приложению. Все, что нам необходимо сделать – это перенаправить приложение на использование не локального эмулятора хранилища, а облачного. Как только мы закончим с этим можно смело приступать к разворачиванию приложения в облаке. Как это делать я напоминать не стану, можно посмотреть особенности этого процесса в моих более ранних публикациях.
Итак, наше приложение успешно развернуто в облаке, диск создан и загружен, необходимо посмотреть, что у нас получилось. Открываем временный урл тестового слота Windows Azure и получаем на экране следующую картинку.

Windows Azure Cloud Drive

БИНГО !! Диск успешно смонтирован и ему присвоена метка E:\. Как мы видим диски – это прекрасная возможность использования стандартных функций файловой системы для взаимодействия (чтение/запись) с хранилищем блобов. В принципе практически весь код приложения можно увидеть в данной публикации, но на всякий случай все-таки выкладываю ссылку на скачивание исходного кода проекта, а также ссылку на утилиту для загрузки VHD-файлов в облако. Спасибо за внимание !  В случае, если остались вопросы, оставляйте их в блоке для комментариев – с удовольствием отвечу на них

Комментариев нет: