When you are managing a large number of virtual machines, it can get tricky to keep track of everything. One thing that I see many people doing to help with this is to make sure that the guest operating system has the same network name as the virtual machine name. This makes life a lot easier when moving between different tools.
However, I tend to rename and copy virtual machines a lot, which makes it difficult to keep the virtual machine and guest operating system name synchronized. To handle this I wrote the following script:
# Get the virtual machine name from the parent partition $vmName = (Get-ItemProperty –path “HKLM:\SOFTWARE\Microsoft\Virtual Machine\Guest\Parameters”).VirtualMachineName # Replace any non-alphanumeric characters with an underscore $vmName = [Regex]::Replace($vmName,"\W","_") # Trim names that are longer than 15 characters $vmName = $vmName.Substring(0,[System.Math]::Min(15, $vmName.Length)) # Check the trimmed and cleaned VM name against the guest OS name # If it is different, change the guest OS name and reboot if ($env:computername -ne $vmName) {(gwmi win32_computersystem).Rename($vmName); shutdown -r -t 0}What this script does is:
I have this script inside my virtual machines, configured to run automatically when the guest operating system boots.
Cheers,
Ben
Hyper-V Replica provides protection to VMs by tracking and replicating changes to the virtual hard disks (VHDs) of the VM. Hyper-V Replica runs 24 hours, 365 days in a year; for any VM that has been enabled for replication it ensures that the data on the primary site and the Replica site are kept as closely in sync as supported.
To begin with, Hyper-V Replica (HVR) requires that the data on the virtual hard disks (VHDs) of the primary and replica VMs be the same. This is achieved through the process of initial replication, and establishes a baseline on which replicated changes can be applied. However, due to factors beyond the control of the administrator – such as faulty hardware and OS bugchecks – it is possible that the primary and Replica VMs are not in sync.
Thus in a rainy day scenario (details in following section), when HVR determines that the replica VM can no longer be kept in sync with the primary by applying the replicated changes then resynchronization is required. Resynchronization (or Resync) is the process of re-establishing the baseline – by ensuring that the primary and replica VHDs have exactly the same data stored.
(NOTE: In this post we will use a VM named “RESYNC VM” in all examples and screenshots.)
When does resynchronization happen?
It would become quite obvious after going through this table below that Resync is not expected to occur regularly. In fact, in the normal course of replication this is quite a rare event. The VM enters the “Resynchronization Required” state when any one of the conditions are encountered:
Site Condition Scenario examplePrimary
Modify VHD when VM is turned off
Mount/modify VHD outside the VM, Edit disk, Offline patching
Primary
Size of tracking log files > 50% of total VHD size for a VM
Network outage causes logs to accumulate
Primary
Write failure to tracking log file
VHD and logs are on SMB and connectivity to the SMB storage is flaky.
Primary
Tracking log file is not closed gracefully
Host crash with primary VM running. Applicable to VMs in a cluster also.
Primary
Reverting the volume to an older point in time
Reverting the VM to an older snapshot
Volume/snapshot backup and restore
Secondary
Out-of-sequence or Invalid log file is applied
Restoring a backed-up copy of the Replica VM
Importing an older VM copy, when migration by using export-import
Reverting volume to an older point in time using Volume backup and restore.
Reverting the VM to an older snapshot
When the VM enters the “Resynchronization Required” state, the replication health becomes “Critical” and the VM is scheduled for resynchronization. At the same time, HVR stops tracking the guest writes for the VM and nothing is replicated.
The replication health will also show this message:
Initiating and scheduling resynchronization
Depending on the VM setting, the user might have to trigger the resynchronization operation explicitly. When that is required, follow the instructions as given in the replication health screen:
You will be presented with the screen to schedule the resynchronization operation:
To start the resync operation from PowerShell, use the Resume-VMReplication commandlet:
Resume-VMReplication –VMName “RESYNC VM” -Resynchronize –ResynchronizeStartTime “04/15/2013 12:00:00”
User-initiated resynchronization is also possible, but unless absolutely necessary it should be avoided. In order to explicitly force resynchronization on a VM that is not in the “Resynchronization Required” state, first suspend the replication and then initiate resync:
Suspend-VMReplication -VMName "RESYNC VM" Resume-VMReplication -VMName "RESYNC VM" -Resynchronize
The scheduling of the resynchronization operation can be configured for each VM:
The default option is to schedule the resynchronization operation during off-peak hours. The resource intensive nature of the operation makes such scheduling useful, and aims to reduce the impact on running VMs.
The same can be configured in PowerShell using the Set-VMReplication commandlet:
# Manual resync Set-VMReplication -VMName "RESYNC VM" -AutoResynchronizeEnabled 0 # Automatic resync Set-VMReplication –VMName "RESYNC VM" -AutoResynchronizeEnabled 1 -AutoResynchronizeIntervalStart 00:00:00 -AutoResynchronizeIntervalEnd 23:59:59 # Scheduled resync Set-VMReplication –VMName "RESYNC VM" -AutoResynchronizeEnabled 1 -AutoResynchronizeIntervalStart 00:00:00 -AutoResynchronizeIntervalEnd 06:00:00
To see the resynchronization settings in PowerShell, use the Get-VMReplication commandlet and look for the AutoResynchronizeEnabled, AutoResynchronizeIntervalStart, and AutoResynchronizeIntervalEnd fields:
Get-VMReplication -VMname "RESYNC VM" | fl *
The process of resynchronization
When the resync operation is triggered – either automatically or by the user – the following high-level sub-operations are executed in sequence:
Resynchronization performance
Resynchronization performance was tested and compared against the performance of Online Initial Replication (IR). The setup consisted of a standalone server with 4 running VMs – 2 File Servers and 2 SQL servers running typical workloads. Two VMs were replicated to a standalone Replica server. The network bandwidth was varied to see the impact. Data size that was replicated during Online IR was approximately 80GB.
Network speed Online IR size Online IR time Resync size Resync time Resync – offline scheduling 1 Gbps ~80 GB ~1.5 hrs ~5.5 GB ~2 hrs Resync – immediate 1 Gbps ~80 GB ~1 hr ~100 MB ~1 hr Resync – offline scheduling 1.5 Mbps ~80 GB 4 days ~10 GB ~1 day Resync – immediate 1.5 Mbps ~80 GB 4 days ~ 78 MB ~1 hourThe tests indicate that resync is preferable to Online IR in low speed networks. When the two sites are connected by a high speed network, resync works well for low churn workloads.
There is also a perfmon counter for measuring the resynchronized bytes: \Hyper-V Replica VM\Resynchronized Bytes.
Conclusion
The disks going out of sync is a rainy-day event in Hyper-V Replica. However with the Resynchronization operation, this is handled gracefully within the product to optimize the administrative overhead and the resources used in bringing the disks back into sync.
I got a few notes about my signature line on my previous post ‘Program Manager, Hyper-V’… Yep I am now a program manager on the Hyper-V team – I moved over from the Hyper-V test team a few weeks ago and now work on Ben Armstrong’s (virtual pc guy) team. I have spent almost my entire career in test, over 11 years including over nine years on the virtualization team, first on Virtual PC then Virtual Server and most recently on Hyper-V. I loved being a tester and the Hyper-V test team is among the best in the industry in my opinion but it was time for a new challenge. Microsoft is an amazing company to work for with excellent managers that enabled me for many years to walk a line between the roles and responsibilities of a tester and those of a PM and over the past few years I’ve deviated further and further toward the PM side so this was a pretty natural move to make. There aren’t many companies that allow you to craft your own role and facilitate your growth in that role for years, Microsoft is an amazing company to work for…
-Taylor Brown
-Program Manager, Hyper-V
In Part 1 of this blog series about adding custom FTP providers with the IIS Configuration Editor, I showed you how to add a custom FTP provider with a custom setting for the provider that is stored in your IIS configuration settings. For my examples, I showed how to do this by using both the AppCmd.exe application from a command line and by using the IIS Configuration Editor. In part 2 of this blog series, I will show you how to use the IIS Configuration Editor to add custom FTP providers to your FTP sites.
As a brief review from Part 1, the following XML excerpt illustrates what the provider's settings should resemble when added to your IIS settings:
<system.ftpServer>
<providerDefinitions>
<add name="FtpXmlAuthorization"
type="FtpXmlAuthorization, FtpXmlAuthorization, version=1.0.0.0, Culture=neutral, PublicKeyToken=426f62526f636b73" />
<activation>
<providerData name="FtpXmlAuthorization">
<add key="xmlFileName"
value="C:\inetpub\FtpUsers\Users.xml" />
</providerData>
</activation>
</providerDefinitions>
</system.ftpServer>
The above example shows the settings that are added globally to register an FTP provider. Note that this example only contains the settings for my custom provider; you would normally see the settings for the IisManagerAuth and AspNetAuth providers that ship with the FTP service in the providerDefinitions collection.
To actually use a provider for an FTP site, you would need to add the provider to the settings for the FTP site in your IIS settings. So for part 2 of this blog series, we will focus on how to add a custom provider to an FTP site by using the IIS Configuration Editor.
Having said all of that, the rest of this blog is broken down into the following sections:
Before continuing, I should reiterate that custom FTP providers fall into two categories: providers that are used for authentication and providers that are used for everything else. This distinction is important, because the settings are stored in different sections of your IIS settings. With that in mind, let's take a look at the settings for an example FTP site.
Step 1 - Looking at the configuration settings for custom FTP providersThe following example shows an FTP site with several custom FTP providers added:
<site name="ftp.contoso.com" id="2">
<application path="/">
<virtualDirectory path="/"
physicalPath="c:\inetpub\www.contoso.com\wwwroot" />
</application>
<bindings>
<binding protocol="ftp"
bindingInformation="*:21:ftp.contoso.com" />
</bindings>
<ftpServer>
<security>
<ssl controlChannelPolicy="SslAllow"
dataChannelPolicy="SslAllow" />
<authentication>
<customAuthentication>
<providers>
<add name="MyCustomFtpAuthenticationProvider" />
</providers>
</customAuthentication>
</authentication>
</security>
<customFeatures>
<providers>
<add name="MyCustomFtpHomeDirectoryProvider" />
<add name="MyCustomFtpLoggingProvider" />
</providers>
</customFeatures>
<userIsolation mode="Custom" />
</ftpServer>
</site>
If you look at the above example, you will notice the following providers have been added:
As I mentioned earlier, you will notice that the settings for FTP custom providers are stored in different sections of the ftpServer collection depending on whether they are used for authentication or some other purpose.
Step 2 - Navigate to an FTP Site in the Configuration EditorOpen the IIS Manager and click on the Configuration Editor at feature the server level:
Click the Section drop-down menu, expand the the system.applicationHost collection, and then highlight the sites node:
If you click on the Collection row, an ellipsis [...] will appear:
When you click the ellipsis [...], IIS will display the Collection Editor dialog box for your sites; both HTTP and FTP sites will be displayed:
Expand the ftpServer node, which is where all of the site-level settings for an FTP site are kept.
Step 3 - Add custom FTP providers to an FTP siteAs I mentioned earlier, custom FTP providers fall into two categories: providers that are used for authentication and everything else. Because of this distinction, the following steps show you how to add a provider to the correct section of your settings depending on the provider's purpose.
Add a custom FTP provider to an FTP site that is not used for authenticationExpand the customFeatures node, which is located under the ftpServer node for an FTP site; this collection defines the custom providers for an FTP site that are not used for authentication, for example: home directory providers, logging providers, etc. When you highlight the providers row, an ellipsis [...] will appear:
When you click the ellipsis [...], IIS will display the Collection Editor dialog box for your custom features (providers). When you click Add in the Actions pane, you need to enter the name of an FTP provider that you entered by following the instructions in Part 1 of this blog series:
Once you enter the name of your FTP provider in the Collection Editor dialog box for your custom features, you can close that dialog box. The Collection Editor for your sites will reflect the updated provider count for your FTP site:
Important Note: If you are adding a custom FTP Home Directory Provider, you have to configure the mode for FTP's User Isolation features. To do so, you need to expand the userIsolation node, which is located under the ftpServer node for an FTP site. Once you have done so, click the mode drop-down menu and choose Custom from the list of choices:
When you close the Collection Editor dialog box for your sites, you need to click Apply in the Actions pane to commit the changes to your IIS settings:
Add a custom FTP authentication provider to an FTP siteFirst and foremost - there is built-in support for adding custom authentication providers in IIS Manager; to see the steps to do so, see the FTP Custom Authentication <customAuthentication> article on the IIS.NET website. However, if you want to add a custom FTP authentication provider to an FTP site by using the IIS Configuration Editor, you can do so by using the following steps.
Expand the security node under the ftpServer node for an FTP site, then expand the authentication node, and then expand the customAuthentication node; this collection defines the custom authentication providers for an FTP site. When you highlight the providers row, an ellipsis [...] will appear:
When you click the ellipsis [...], IIS will display the Collection Editor dialog box for your custom authentication providers. When you click Add in the Actions pane, you need to enter the name of an FTP authentication provider that you entered by following the instructions in Part 1 of this blog series:
Once you enter the name of your FTP authentication provider in the Collection Editor dialog box for your custom authentication providers, you can close that dialog box. The Collection Editor for your sites will reflect the updated authentication provider count for your FTP site:
When you close the Collection Editor dialog box for your sites, you need to click Apply in the Actions pane to commit the changes to your IIS settings:
Summary and Parting ThoughtsAs I mentioned in part 1 of this series, I admit that this might seem like a lot of steps to go through, but it's not that difficult once you understand how the configuration settings are organized and you get the hang of using the IIS Configuration Editor to add or modify these settings.
Disabling Custom User IsolationIn the Add a custom FTP provider to an FTP site that is not used for authentication section of this blog, I added a step to specify Custom as the User Isolation mode. Since this is something of an advanced feature, there is no user interface for enabling custom user isolation; this was a design decision to keep people from breaking their FTP sites. Here's why: if you enable custom user isolation and you don't install a custom Home Directory provider for FTP, all users will be denied access to your FTP site.
That being said, once you have enabled custom user isolation, the option to disable custom user isolation will "magically" appear in the FTP User Isolation feature in the IIS Manager. To see this for yourself, you would first need to follow the steps to custom user isolation in the Add a custom FTP provider to an FTP site that is not used for authentication section of this blog.
Once you have enabled custom user isolation, highlight your FTP site in the list of Sites pane of IIS Manager, then open the FTP User Isolation feature:
When you open the FTP User Isolation feature, you will see that an option for Custom now appears in the list of user isolation modes:
This option will appear as long as custom user isolation is enabled. If you change the user isolation mode to something other than Custom, this option will continue appear in the list of user isolation modes until you navigate somewhere else in IIS Manager. Once you have changed the user isolation mode to one of the built-in modes and you navigate somewhere else, the Custom option will not show up in the FTP User Isolation feature until you follow the steps to re-enable custom user isolation.
Additional InformationIf you want additional information about configuring the settings for FTP providers, you can find detailed reference documentation at the following URLs:
Each of these articles contain "How-To" steps, detailed information about each of the configuration settings, and code samples for AppCmd.exe, C#/VB.NET, and JavaScript/VBScript.
As always, let me know if you have any questions. ;-]
(Cross-posted from http://blogs.msdn.com/robert_mcmurray/)A long time ago, Didier Van Hoye asked me how to configure the networks that should be used for live migration by a Hyper-V cluster using nothing but PowerShell. Unfortunately, I never got around to getting an answer for him – until today.
Didier – this one is for you.
Now for a bit of background: When you create a Hyper-V cluster, you need to configure which networks are used for virtual machine live migration. You want to ensure that virtual machine live migration is going over a network with enough bandwidth available (a minimum of 500mbit per concurrent live migration is recommended) and where we are not going to disrupt other network traffic (i.e. do not have live migration run over your storage network). You also want to ensure that the network used by live migration is appropriately secure – either physically secure, or using technology like IPsec – as we do not do any encryption of the data being sent over this network.
You can do this through the UI quite easily:
But how do you do this with PowerShell? Well, after a lot of digging around it turns out that it is not that hard. It is not obvious, but it is not hard. If you only have one network for live migration – you can actually do this in one line. If you know the cluster network name you can run:
Get-ClusterResourceType -Name "Virtual Machine" | Set-ClusterParameter -Name MigrationExcludeNetworks -Value ([String]::Join(";",(Get-ClusterNetwork | Where-Object {$_.Name -ne "Migration Network"}).ID))
Or, if you just know the IP subnet for the live migration network you can run this:
Get-ClusterResourceType -Name "Virtual Machine" | Set-ClusterParameter -Name MigrationExcludeNetworks -Value ([String]::Join(";",(Get-ClusterNetwork | Where-Object {$_.Address -ne "192.168.210.0"}).ID))
So what is this doing?
Well, it is getting the “Virtual Machine” resource from the cluster (which is actually a global resource – that is not specific to a single virtual machine – bad naming, I know) and then it is setting the “MigrationExcludeNetworks” parameter on this resource. Which, unsurprisingly, is a list of the cluster networks to exclude from live migration.
Where things get a little fiddly here is:
It would get quite fiddly (but not impossible) if you wanted to configure multiple networks for live migration – but hopefully you should have the gist of how to do it from reading this article.
Cheers,
Ben
Some folks have asked creating there own VMConnect application – it’s actually really easy. Here’s a very basic example of how to create your own VMConnect application. You would likely want to add some error handling, change the window sizing, maybe a WMI call to retrieve the name of the VM vs the ID but with Hyper-V’s WMI API you can do all of that and more after all now it’s your VMConnect application.
Steps To Create Basic ApplicationStep 1 - Create a new C# Windows Forms project In Visual Studio
Step 4 - Add a text box for the VM ID and a connect button to the form
-taylorb
Program Manager, Hyper-V
Publishing technical documentation is an interesting business, and a lot of discussion & deliberation goes into the creation process for articles and videos that we produce at Microsoft. For example, when I am writing an article for IIS, should I publish that on www.iis.net, or technet.microsoft.com, or msdn.microsoft.com? Or should I just write a blog about it? And after I have published an article, how will my intended audience find it? As we continue to publish hundreds of technical articles to the websites that I just mentioned, the navigation hierarchy becomes increasingly complex, and content discoverability suffers.
Some time ago a few of our writers began to experiment with a new way to consolidate lists of related content into something that we called a "Content Map." The following pages will show you an example of what the Content Map concept looks like:
Each of these articles received a great deal of positive feedback from customers, but our team wanted to see if there was a way that customers could help us to improve on this design. We know that there is a great deal of third-party content on the Internet, and we wanted a way to recognize that. We also asked several customers about what kinds of content they need to be successful, and we added their suggestions to our deliberation process.
As a result of our collective discussions, we came up with an idea for what we are internally calling "Curated Content Views." These "views" are lists of related content topics that are organized to answer a particular question or customer need. A view is assembled by someone at Microsoft based on input from anyone who thinks that an article, blog, video, or code sample might be beneficial as part of the view.
With that in mind, here are three conceptual content views that a few of the writers on our content team have assembled:
Our team is requesting feedback from members of the community regarding these conceptual views with regard to the level of detail that is included in each view, the conceptual layouts that were used, and any thoughts about how this content compares with existing table of contents topics or content maps. You can reply to our content team via email, or you can post a response to this blog.
While we are interested in any feedback you may have, our team has put together the following list of specific questions to think about:
Thanks!
(Cross-posted from http://blogs.msdn.com/robert_mcmurray/)A while ago I did a blog post that showed you how easy it was to check what version of the Integration Services were installed inside your virtual machines. However, a number of people came back to me and said: “Ben, I do not really care about the version number of the integration services – what I want to know is whether I need to update the integration services or not”.
Hmm…
That is a much trickier problem to solve. In fact, in Windows Server 2008 and Windows Server 2008 R2 it is not really possible to write a good script that will do this. Luckily, it is possible to write a script for this in Windows 8 / Windows Server 2012. Unfortunately, it is not the simplest script around.
There are a couple of reasons for this:
With that in mind – here is the script that will get you the information you need:
# GetSummaryInformation documented here: http://msdn.microsoft.com/en-us/library/hh850062(v=vs.85).aspx # MSVM_SummaryInformation documented here: http://msdn.microsoft.com/en-us/library/hh850217(v=vs.85).aspx # Get the Management Service from the v2 namespace $VMMS = gwmi -namespace root\virtualization\v2 Msvm_VirtualSystemManagementService # 1 == VM friendly name. 123 == Integration State $RequestedSummaryInformationArray = 1,123 $vmSummaryInformationArray = $VMMS.GetSummaryInformation($null, $RequestedSummaryInformationArray).SummaryInformation # Create an empty array to store the results in $outputArray = @() # Go over the results of the GetSummaryInformation Call foreach ($vmSummaryInformation in [array] $vmSummaryInformationArray) { # Turn result codes into readable English switch ($vmSummaryInformation.IntegrationServicesVersionState) { 1 {$vmIntegrationServicesVersionState = "Up-to-date"} 2 {$vmIntegrationServicesVersionState = "Version Mismatch"} default {$vmIntegrationServicesVersionState = "Unknown"} } # Use Hyper-V PowerShell cmdlets to quickly get the integration version number $vmIntegrationServicesVersion = (get-vm $vmSummaryInformation.ElementName).IntegrationServicesVersion # Display "Unknown" if we got a null result if ($vmIntegrationServicesVersion -eq $null) {$vmIntegrationServicesVersion = "Unknown"} # Put the VM Name, Integration Service Version and State in a PSObject - so we can display a nice table at the end $output = new-object psobject $output | add-member noteproperty "VM Name" $vmSummaryInformation.ElementName $output | add-member noteproperty "Integration Services Version" $vmIntegrationServicesVersion $output | add-member noteproperty "Integration Services State" $vmIntegrationServicesVersionState # Add the PSObject to the output Array $outputArray += $output } # Display information in nicely formatted table write-output $outputArray | sort "VM Name"If I run this script on one of my Hyper-V servers – I get this:
Looks like I need to do a lot of integration service updates. Bummer.
But getting back to the script – what is GetSummaryInformation and why is it so tricky to use? GetSummaryInformation is a WMI method that we implemented to allow people to get a lot of random information about virtual machines in a quick and efficient method. The way it works is that you call it and pass in an array of numbers – this array indicates the information that you want to get about the virtual machines. You can read all of the possible options here: http://msdn.microsoft.com/en-us/library/hh850217(v=vs.85).aspx
One final note – in order to get the Integration Services state – you need to use the WMI v2 namespace.
Cheers,
Ben
A few years ago I wrote the following blog, wherein I described how the WebDAV functionality in IIS 6.0 worked with files that are Compound Document format:
IIS 6.0 WebDAV and Compound Document Format Files
As I explained in that blog post, WebDAV needs somewhere to store "properties" for files that are uploaded to the server, and WebDAV uses the compound document format to accomplish this according to the following implementation logic:
I recently had a customer contact me in order to ask if there was a way to disable this functionality since he didn't want his files modified in order to store the WebDAV properties. Unfortunately there is no built-in option for IIS that will disable this functionality, but there are a few workarounds.
Workaround #1 - Change the File TypeFirst and foremost - you can change your file type to something other than the compound document format. For example, if you are uploading files that were created in Microsoft Office, if you can upload your files in the newer Office Open XML formats, then you will not run into this problem. By way of explanation, older Microsoft Office files are in compound document format, whereas files that are that are created with Microsoft Office 2010 and later are in a zipped, XML-based file format. These files will have extensions like *.DOCX for Microsoft Word documents, *.XLSX for Microsoft Excel spreadsheets, and *.PPTX for Microsoft PowerPoint presentations.
Workaround #2 - Wrap Compound Document Files in a Separate File TypeIf you are using a file that must be in compound document format, like a setup package in Microsoft Installer (*.MSI) format, you can upload the file in a *.ZIP file, or you can wrap the setup package inside a self-extracting executable by using a technology like Microsoft's IExpress Wizard (which ships as a built-in utility with most versions of Windows).
Workaround #3 - Block WebDAV PropertiesIf you absolutely cannot change your document from compound document format, I have a completely unsupported workaround that I can suggest. Since the problem arises when properties are added to a file, you can find a way to intercept the WebDAV commands that try to set properties. The actual HTTP verb that is used is PROPPATCH, so if you can find a way to keep this command from being used, then you can prevent files from being modified. Unfortunately you cannot simply suppress PROPPATCH commands by using a security tool like Microsoft's UrlScan to block the command, because this will cause many WebDAV clients to fail.
Instead, what I did as a workaround was to write an example ISAPI filter for IIS 6.0 that intercepts incoming PROPPATCH commands and always sends a successful (e.g. "200 OK") response to the WebDAV client, but in reality the filter does nothing with the properties and ends the request processing. This tricks a WebDAV client into thinking that it succeeded, and it prevents your files in compound document format from being modified. However, this also means that no WebDAV properties will ever be stored with your files; but if that's acceptable to you, (and it usually should be), then you can use this workaround.
With that in mind, here's the C++ code for my example ISAPI filter, and please remember that this is a completely unsupported workaround that is intended for use only when you cannot repackage your files to use something other than the compound document format.
#define _WIN32_WINNT 0x0400 #include <windows.h> #include <httpfilt.h> #define STRSAFE_LIB #include <strsafe.h> #define BUFFER_SIZE 2048 const char xmlpart1[] = "<?xml version=\"1.0\"?>" "<a:multistatus xmlns:a=\"DAV:\">" "<a:response>" "<a:href>"; const char xmlpart2[] = "</a:href>" "<a:propstat>" "<a:status>HTTP/1.1 200 OK</a:status>" "</a:propstat>" "</a:response>" "</a:multistatus>"; BOOL WINAPI GetFilterVersion(PHTTP_FILTER_VERSION pVer) { HRESULT hr = S_OK; // Set the filter's version. pVer->dwFilterVersion = HTTP_FILTER_REVISION; // Set the filter's description. hr = StringCchCopyEx( pVer->lpszFilterDesc,256,"PROPPATCH", NULL,NULL,STRSAFE_IGNORE_NULLS); if (FAILED(hr)) return FALSE; // Set the filter's flags. pVer->dwFlags = SF_NOTIFY_ORDER_HIGH | SF_NOTIFY_PREPROC_HEADERS; return TRUE; } DWORD WINAPI HttpFilterProc( PHTTP_FILTER_CONTEXT pfc, DWORD NotificationType, LPVOID pvNotification ) { // Verify the correct notification. if ( NotificationType == SF_NOTIFY_PREPROC_HEADERS) { PHTTP_FILTER_PREPROC_HEADERS pHeaders; HRESULT hr = S_OK; bool fSecure = false; char szServerName[BUFFER_SIZE] = ""; char szSecure[2] = ""; char szResponseXML[BUFFER_SIZE] = ""; char szResponseURL[BUFFER_SIZE] = ""; char szRequestURL[BUFFER_SIZE] = ""; char szMethod[BUFFER_SIZE] = ""; DWORD dwBuffSize = 0; pHeaders = (PHTTP_FILTER_PREPROC_HEADERS) pvNotification; // Get the method of the request dwBuffSize = BUFFER_SIZE-1; // Exit with an error status if a failure occured. if (!pfc->GetServerVariable( pfc, "HTTP_METHOD", szMethod, &dwBuffSize)) return SF_STATUS_REQ_ERROR; if (strcmp(szMethod, "PROPPATCH") == 0) { // Send the HTTP status to the client. if (!pfc->ServerSupportFunction( pfc, SF_REQ_SEND_RESPONSE_HEADER,"207 Multi-Status", 0, 0)) return SF_STATUS_REQ_ERROR; // Get the URL of the request. dwBuffSize = BUFFER_SIZE-1; if (!pfc->GetServerVariable( pfc, "URL", szRequestURL, &dwBuffSize)) return SF_STATUS_REQ_ERROR; // Determine if request was sent over secure port. dwBuffSize = 2; if (!pfc->GetServerVariable( pfc, "SERVER_PORT_SECURE", szSecure, &dwBuffSize)) return SF_STATUS_REQ_ERROR; fSecure = (szSecure[0] == '1'); // Get the server name. dwBuffSize = BUFFER_SIZE-1; if (!pfc->GetServerVariable( pfc, "SERVER_NAME", szServerName, &dwBuffSize)) return SF_STATUS_REQ_ERROR; // Set the response URL. hr = StringCchPrintf( szResponseURL,BUFFER_SIZE-1, "http%s://%s/%s", (fSecure ? "s" : ""), szServerName, &szRequestURL[1]); // Exit with an error status if a failure occurs. if (FAILED(hr)) return SF_STATUS_REQ_ERROR; // Set the response body. hr = StringCchPrintf( szResponseXML,BUFFER_SIZE-1, "%s%s%s", xmlpart1, szResponseURL, xmlpart2); // Exit with an error status if a failure occurs. if (FAILED(hr)) return SF_STATUS_REQ_ERROR; // Write the response body to the client. dwBuffSize = strlen(szResponseXML); if (!pfc->WriteClient( pfc, szResponseXML, &dwBuffSize, 0)) return SF_STATUS_REQ_ERROR; // Flag the request as completed. return SF_STATUS_REQ_FINISHED; } } return SF_STATUS_REQ_NEXT_NOTIFICATION; }I hope this helps. ;-]
(Cross-posted from http://blogs.msdn.com/robert_mcmurray/)There is a great post over on the virtualization team blog about how to install the Hyper-V integration components offline. Go check it out: http://blogs.technet.com/b/virtualization/archive/2013/04/19/how-to-install-integration-services-when-the-virtual-machine-is-not-running.aspx
Cheers,
Ben
We’ve been talking to a lot of people about deploying integration services (integration components) lately. As it turns out, they’re pretty easy to patch offline with existing Hyper-V tools.
First, why would you update integration services on a not-running (offline) VM?
Offline VM servicing is valuable for VM templates places that create new VMs frequently since it allows you to keep VM templates up-to-date. While this post targets exclusively integration service updates, the same update approach applies to many updates as well as any configurations specific to the environment. Keeping the VM images fully up to date and configured before they are deployed saves significant setup time and support every time a new VM is created.
Here is a detailed write-up about deploying and updating integration services on an offline VM – both VHD/VHDX – using out of box PowerShell tools and a cab (cabinet) file that comes bundled with Server 2008 or later Hyper-V hosts.
Before you start, open a PowerShell console as administrator. Make sure Hyper-V is installed and you’re working from the management (host) OS. The management OS must be Server 2008R2 or newer and more recent than the VM OS you’re patching. I tested this script with a Server 2012 host.
For default Hyper-V installs, the CAB containing the up-to-date integration components will be located in [HostDrive]:\windows\vmguest\support. From there, choose your architecture; for my machine, I choose amd64. X86 people, you’re files are there too. This file contains all of the components built into the VM Guest ISO. To update integration components offline, we’re only interested in the two cab files highlighted below.
There will be two files:
Note: this process only works for Windows 2008R2 / Windows 7 and later operating systems. It works with both vhd and vhdx files.
You will need the path to this file. From here on out I’ll refer to it as $integrationServicesCabPath. If you pick the wrong one it will fail a version check without harming the guest.
$integrationServicesCabPath="C:\Windows\vmguest\support\amd64\Windows6.2-HyperVIntegrationServices-x64.cab"
The next step is to apply the cab to the offline VM.
First, you’ll need the path to your VM image, I’m going to refer to this as $virtualHardDiskToUpdate.
$virtualHardDiskToUpdate="D:\client_professional_en-us_vl.vhd"
Next, mount the image as a pass-through disk (unprotected data and direct I/O) and keep track of the disk number returned.
$diskNo=(Mount-VHD -Path $ virtualHardDiskToUpdate –Passthru).DiskNumber
Check to make sure the operational status is online and find the drive letter so we know which drive to patch.
(Get-Disk $diskNo).OperationalStatus
$driveLetter=(Get-Disk $diskNo | Get-Partition | Get-Volume).DriveLetter
In my case this returned “online” and “E” (stored in $driveLetter). If you mounted a VM with Windows fully installed, the chances are good it’ll mount more than one drive depending on the VMs particular setup. If this is the case, find the drive with all of the Windows OS files – apply the integration service update to that one. If the status returns not online prepare the image by running:
Set-Disk $diskNo -IsOffline:$false -IsReadOnly:$false
Now the mounted VHD is ready to be patched.
Add-WindowsPackage -PackagePath $integrationServicesCabPath -Path ($driveLetter+":\")
You should see a blue progress bar at the top of PowerShell. Enjoy watching the little yellow o’s fill your screen. If the cab couldn’t apply, make sure you’re using the right version for your guest OS and the right drive. If the VM is running, it will not patch.
Finally, dismount the VHD. Notice you dismount using the image path and not the mounted drive letter.
Dismount-VHD -Path $virtualHardDiskToUpdate
Here’s a more reasonable, consolidated, PowerShell Script:
$virtualHardDiskToUpdate="D:\client_professional_en-us_vl.vhd"
$integrationServicesCabPath="C:\Windows\vmguest\support\amd64\Windows6.2-HyperVIntegrationServices-x64.cab"
#Mount the VHD
$diskNo=(Mount-VHD -Path $virtualHardDiskToUpdate –Passthru).DiskNumber
#Get the driver letter associated with the mounted VHD, note this assumes it only has one partition if there are more use the one with OS bits
$driveLetter=(Get-Disk $diskNo | Get-Partition).DriveLetter
#Check to see if the disk is online if it is not online it
if ((Get-Disk $diskNo).OperationalStatus -ne 'Online')
{Set-Disk $MountedVHD.Number -IsOffline:$false -IsReadOnly:$false}
#Install the patch
Add-WindowsPackage-PackagePath $integrationServicesCabPath -Path ($driveLetter + ":\")
#Dismount the VHD
Dismount-VHD-Path $virtualHardDiskToUpdate
Thank you to Taylor Brown (http://blogs.msdn.com/b/taylorb), for the script!
Cheers,
Sarah Cooley
A new article has appeared on the TechNet Wiki that provides a complete list of updates for Hyper-V on Windows Server 2012:
I am really happy to see this online, as we have received lots of positive feedback about how useful the existing documentation is for updates that are available for Hyper-V on Windows Server 2008 R2 and on Windows Server 2008. Hopefully this will help everyone in planning and managing their Hyper-V deployments.
Cheers,
Ben
We have had a number of queries on how to enable replication using certificates created from makecert. Though the Understanding and Troubleshooting guide for Hyper-V Replica discusses this aspect, I am posting a separate article on this. The below steps are applicable for a simple lab deployment consisting of two standalone servers – PrimaryServer.domain.com and ReplicaServer.domain.com. This can be easily extended to clustered deployments with the Hyper-V Replica Broker.
Makecert is a certificate creation tool which generates certificates for testing purpose. Information on makecert is available here - http://msdn.microsoft.com/en-us/library/bfsktky3.aspx.
1. Copy the makecert.exe tool to your primary server
2. Run the following command from an elevated command prompt, on the primary server. This command creates a self-signed root authority certificate. The command also installs a test certificate in the root store of the local machine and is saved as a file locally
makecert -pe -n "CN=MyTestRootCA" -ss root -sr LocalMachine -sky signature -r "MyTestRootCA.cer"3. Run the following command couple of times, from an elevated command prompt to create new certificate(s) signed by the test root authority certificate
makecert -pe -n "CN=<FQDN>" -ss my -sr LocalMachine -sky exchange -eku 1.3.6.1.5.5.7.3.1,1.3.6.1.5.5.7.3.2 -in "MyTestRootCA" -is root -ir LocalMachine -sp "Microsoft RSA SChannel Cryptographic Provider" -sy 12 <MachineName>.cerEach time:
The command installs a test certificate in the Personal store of the local machine and is saved as a file locally. The certificate can be used for both Client and Server authentication
4. The certificates can be viewed by mmc->File->Add/Remove Snap in…->Certificates->Add->”Computer Account”->Next->Finish->Ok
You will find the Personal certificate (with the machine names) and the Root certificate (MyTestRootCA) in the highlighted folders:
5. Export the replica server certificate with the private key.
6. Copy MyTestRootCA.cer and the above exported certificate (RecoveryServer.pfx) to the Replica server.
7. Run the following command from an elevated prompt in ReplicaServer.domain.com
certutil -addstore -f Root "MyTestRootCA.cer"8. Open the certificate mmc in ReplicaServer.domain.com and import the certificate (RecoveryServer.pfx) in the Personal store of the server. Provide the pfx file and password as input:
9. By default, a certificate revocation check is mandatory and Self-Signed Certificates don’t support Revocation checks. To work around it, modify the following registry key on Primary, Replica Servers
reg add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Virtualization\Replication" /v DisableCertRevocationCheck /d 1 /t REG_DWORD /f