Подключение файлов VHD в Hyper-V
Многие знают, что в Virtual Server 2005 существовала утилита vhdmount.exe. Она позволяла подключать образы жестких дисков формата VHD в виде каталога на разделе NTFS или отдельного диска.
В Hyper-V такой возможности нет. В связи с чем возникают больные вопросы — «доколе?» и «что делать?».
Выход из этой ситуации, конечно, есть. Точнее несколько выходов. Все они основаны на богатых возможностях управления Hyper-V через репозиторий WMI. Я приведу примеры подключения образов VHD для C#, VBScript и PowerShell. Если тема программного управления VM интересна, могу привести другие примеры.
PowerShell
#Specify the VHD to be mounted
$VHDName = "F:\Windows.vhd"
#Get the MSVM_ImageManagementService
$VHDService = get-wmiobject -class "Msvm_ImageManagementService" -namespace "root\virtualization" -computername "."
#Mount the VHD
$Result = $VHDService.Mount($VHDName)
Это, конечно, очень простой пример. Он использует готовый объект MSVM_ImageManagementService, который создается при установке роли Hyper-V, и вызывает для него метод Mount. Для отключения, что логично, используется метод UnMount.
Обратите внимание, что для успешного подключения образа виртуального диска требуется, чтобы он в данный момент не использовался запущенными виртуальными машинами. Иначе попытка подключения завершится ошибкой.
Более того — диск просто подключится к системе, но будет находиться в отключенном состоянии (offline). Перевести его в состояние online можно из оснастки Disk Management, которая входит в Server Manager. Затем там же потребуется присвоить диску букву или подключить в пустой каталог.
VBScript
Option Explicit
Dim WMIService
Dim VHDService
Dim VHD
'Specify the VHD to be mounted
VHD = "F:\Windows.vhd"
'Get instance of 'virtualization' WMI service on the local computer
Set WMIService = GetObject("winmgmts:\\.\root\virtualization")
'Get the MSVM_ImageManagementService
Set VHDService = WMIService.ExecQuery("SELECT * FROM Msvm_ImageManagementService").ItemIndex(0)
'Mount the VHD
VHDService.Mount(VHD)
Приведу также пример на C#. Но это немного сложнее, так что не обессудьте за большой объем кода. Я и так для облегчения восприятия убрал всевозможные необходимые в реальной жизни проверки ошибок.
C#
using System;
using System.Collections.Generic;
using System.Text;
using System.Management;
using System.IO;
using System.Security.AccessControl;
using Microsoft.Virtualization.Test.Utilities.CommandLineParser;
public static class Class1
{
private static ManagementClass mVhdSvc;
public static void Main(string[] args)
{
OpenVirtualization("localhost");
MountVHD("F:\\Windows.vhd");
}
static void OpenVirtualization(string ComputerName)
{
ManagementPath path = new ManagementPath();
path.Server = mHostName;
path.NamespacePath = @"root\virtualization";
path.ClassName = "Msvm_VirtualSystemManagementService";
ManagementClass vsManagementService = new ManagementClass(path);
foreach (ManagementObject vs in vsManagementService.GetInstances())
{
mVirtualization = vs;
break;
}
path.ClassName = "Msvm_ImageManagementService";
ManagementClass vhdSvc = new ManagementClass(path);
foreach (ManagementObject vhdsvc in vhdSvc.GetInstances())
{
mVhdSvc = vhdsvc;
break;
}
}
static void WaitForWmiComplete(string Task, string ErrorDescription, uint Result)
{
if (Result != 0 && Result != 4096)
{
throw new ManagementException(ErrorDescription + " Error=" + Result);
}
else if (Result == 4096)
{
VMTask task = new VMTask(new ManagementObject(Task));
task.WaitForCompletion(-1);
if (task.Status != VMTaskStatus.CompletedSuccessfully)
{
throw new ManagementException(
ErrorDescription + " Error Code: " + task.ErrorCode + "." +
"Error Description: " + task.ErrorDescription + "."
);
}
}
}
static void MountVHD(String VHDPath)
{
object[] arguments = new object[] { vhdPathInfo.FullName, null };
uint result = 0;
result = (uint)mVhdSvc.InvokeMethod("Mount", arguments);
WaitForWmiComplete((string)arguments[1], "Failed to mount VHD", result);
}
}
Comments
Anonymous
January 01, 2003
спасает команда diskpart а в ней: подключение: select vdisk file "d:file.vhdx" attach vdisk назначение буквы: list disk, определяем наш диск (предположим это диск 2) select disk 2 assign letter=Z отключение: select vdisk file "d:file.vhdx" detach vdiskAnonymous
February 02, 2009
Привет. А как можно с помощью powershell изменять параметры "resource control" в hyper-v? Александр Белов.Anonymous
February 04, 2009
Прошлый комент можно проигнорить нашёл решщение. Другой Вопрос: Как узнать букву примонтированного VHD диска? для дальнейшего использования в скрипте.Anonymous
May 03, 2016
Всем привет! Подскажите в какой кодировке смотреть страницы - везде вместо русского текста знаки вопросов.Anonymous
June 14, 2016
Не прошло и месяца. Поддержка блогов пофиксила проблемы с кодировкой.