1
Vote

Why include processID in the WMI query?

description

When backing up multiple turned off vms, one of them will not be backed up, because of the incorrect wmi query built in BackupManager.cs
Eg.
backing up 3 machines: vm1, vm2, vm3 creates the below query:
query = SELECT Name, ElementName FROM Msvm_ComputerSystem WHERE ProcessID >= 0 AND ElementName = 'vm1' OR ElementName = 'vm2' OR ElementName = 'vm3'
Since in logical operator precendence AND is above OR this means: select vm2, vm3 but select vm1 only if processid is exists, which is for turned off machines always missing (null).
(ProcessID >= 0 AND ElementName = 'vm1')  OR (ElementName = 'vm2') OR (ElementName = 'vm3')
Anyways, adventuring through the source code I'm wondering why ProcessID is needed at all?

I modified this source file a bit:
string query = "SELECT Name, ElementName FROM Msvm_ComputerSystem WHERE ";
//"ProcessID >= 0";
if(vmNames != null && vmNames.Count() > 0)
  query += GetORStr(inField, vmNames);
  //query += " AND " + GetORStr(inField, vmNames);
And now it's working perfectly for me.

file attachments

comments

beatcracker wrote Sep 26, 2013 at 1:41 PM

> Anyways, adventuring through the source code I'm wondering why ProcessID is needed at all?

I believe, it's used to exclude Hyper-V host from the list of VMs. This WMI query returns all VMs on the host including host itself:
SELECT Name, ElementName FROM Msvm_ComputerSystem WHERE ProcessID >= 0
E.g. if you're running Hyper-V host VMHost with 2 VMs VM1 and VM2, the query above will return VMHost, VM1, VM2.

So, to exclude Hyper-V host from the list, author relied on the fact, that in Windows Server 2008 host's ProcessId is empty, while offline VMs have ProcessId = 0 and online VMs have ProcessId = PID of vmwp.exe. This makes sense.

But, the problem is, that in Windows Server 2012 both host's and offline vm's ProcessId = empty, so
HV Backup also strips all offline VMs from the list.

To fix this and the logical operator precedence error you mentioned, I've modified source code this way:

In IDictionary<string, string> GetVMNames(IEnumerable<string> vmNames, VMNameType nameType)
// Include only items that have string "Virtual" in description 
string query = "SELECT Name, ElementName FROM Msvm_ComputerSystem WHERE Description like'%Virtual%'";
In private static string GetORStr(string fieldName, IEnumerable<string> vmNames)
StringBuilder sb = new StringBuilder();
foreach (var vmName in vmNames)
{
if (sb.Length > 0)
    sb.Append(" OR ");
sb.Append(string.Format("{0} = '{1}'", fieldName, EscapeWMIStr(vmName)));
}

// Wrap in parentheses, to fix logical operator precedence
sb.Insert(0, "(");
sb.Append(")");

return sb.ToString();
And now it's working perfectly for me (с) :)

wrote Sep 26, 2013 at 1:46 PM

beatcracker wrote Sep 26, 2013 at 1:46 PM

I'm attaching fixed build, for everyone without a Visual Studio. If you don't trust random exe files from the web (and you really shouldn't), you can build it yourself with free version of VS 2012 Express for Desktop.

alexp wrote Nov 4, 2013 at 5:13 PM

Hi, thanks for your help!

Can you please check this binary?

https://dl.dropboxusercontent.com/u/9060190/HVBackup_1_0_1_Beta.zip

It's a while since I didn't work on codeplex, next time please send me the equivalent of a pull request to review / merge your code. :-)

mw wrote Nov 24, 2013 at 11:13 PM

Hi AlexP,

your fix ("SELECT Name, ElementName FROM Msvm_ComputerSystem WHERE Caption = 'Virtual Machine'") doesn't work on a german windows server 2012. That's because someone at Microsoft decided that the caption has to be 'Virtueller Computer' on a german windows.

So I changed your query to "SELECT Name, ElementName FROM Msvm_ComputerSystem WHERE Description LIKE '%Virtual%'" as in beatcracker's suggestion above. Now it works on a german windows, too.

Markus

alexp wrote Nov 25, 2013 at 10:31 AM

Good catch Markus!

What is the complete value of Description in your case? We need to find a solution that works on every locale.

Thanks

beatcracker wrote Nov 25, 2013 at 11:06 AM

That's because someone at Microsoft decided that the caption has to be 'Virtueller Computer' on a german windows.

Oh, they localized WMI... Mother of god.

What is the complete value of Description in your case? We need to find a solution that works on every locale.

Beware of Cyrillic. I'll try to take a look inside Win 2012 with a Russian localization.

dougkinzinger wrote Dec 3, 2013 at 9:11 PM

NICE - thanks - the older 1.0 published version was giving me errors in Server 2012 R2, but the 1.0.1 beta appears to be working properly in Windows Server 2012 R2 now. Thanks a ton.

dougkinzinger wrote Dec 3, 2013 at 9:17 PM

With Server 2012 R2 the VM wants to enter a saved state prior to backup. How can that be worked around?

dougkinzinger wrote Dec 5, 2013 at 6:39 PM

Disregard, the latest Hyper-V components need installing on the guests in order for VSS to grab without shutting down the running VM. Works great.

beatcracker wrote Dec 9, 2013 at 1:11 PM

Since we have no reliable way to determine Hyper-V host via WMI properties (ProcessId and Description, which is localized) between different versions of Windows Server and yet we need to remove it from the list of VM's returned by WMI query, I propose another approach.

What if we get Hyper-V host name beforehand (using http://msdn.microsoft.com/en-us/library/system.environment.machinename.aspx for ex.)? And then, pass it to WMI query, making it look like this:
"SELECT Name, ElementName FROM Msvm_ComputerSystem WHERE ElementName != 'VMHost' AND (ElementName = 'VM1' OR ElementName = 'VM2')"
The code is (but please mind that I'm sysadmin, not a developer, so it could be ugly):
string hvhost = Environment.MachineName;
string query = "SELECT Name, ElementName FROM Msvm_ComputerSystem WHERE ElementName != '" + hvhost + "'";
alexpi wrote:

It's a while since I didn't work on codeplex, next time please send me the equivalent of a pull request to review / merge your code. :-)

I've submitted this patch to the source code of the Backup Manager.cs via "Upload patch", hope this will suffice.

majo053 wrote Dec 16, 2013 at 2:35 PM

Hi, please where is source code?

DavidBE wrote Feb 4, 2014 at 10:00 AM

Hi,

My locale is french, so I had to modify the query :

__In IDictionary<string, string> GetVMNames(IEnumerable<string> vmNames, VMNameType nameType)
// Include only items that have string "Virtual" in description 
string query = "SELECT Name, ElementName FROM Msvm_ComputerSystem WHERE Description like'%Virtuel%'";
Regards,

David

alexp wrote Mar 14, 2014 at 9:38 PM

Hi, this new release should solve this issue:

https://hypervbackup.codeplex.com/releases/view/119695

Please let me know if it works for you.

Thanks,

Alessandro