This project is read-only.

Support for Windows Server 2008 R2 and CSVs

Aug 30, 2010 at 4:58 PM

Hi, I've been working on backing up some virtual machines on our Server 2008 R2 Datacenter Hyper V servers for some time.  I currently have a solution in place that uses a mishmash of vbscript, VB6, and Diskshadow to create vm backups, but its not too terribly scalable and its not something I can see keeping around for the long run.  I've been messing with moving to a managed code solution (most likely C#) but since I'm anything but an expert its been slow going.  Alpha VSS looks like it could be a life saver - I was just getting ready to start writing my own wrappers - but before I jump in head first I'd like to know if anybody has tested Alpha VSS on Server 2008 R2 with Cluster Shared Volumes. 

If nobody has attempted this just yet I don't mind being the first... although I probably won't get to a point where I can get/share results for some time since this is a back burner project.

Thanks,

Scott

Aug 30, 2010 at 6:01 PM

Hi,

Unfortunately I personally have not tried it on 2008 R2, but I would really like to hear what you come up with.  If there are any problems, or if there are new features in VSS (according to MSDN) in 2008 R2 that you would like to see in AlphaVSS, please let me know and I will see if I can get it done.

Sincerely, Peter

Sep 15, 2010 at 3:12 PM

Ok, I've finally had a chance to work on this, but I've run into some questions I can't find any solid documentation on - no surprise.  I'm wondering weather or not I need to work in component mode with the Hyper-V VSS writer.  From what I have seen on this and other forums, no one has been specifically using the Hyper-V writer, but I was wondering if anybody knows where documentation on working with any of the VSS writers is stored?  I might stumble onto what I'm looking for.

I'll continue searching around and will more than likely just try shadowing the whole volume.  I might have some results to share sometime this week if all goes well.

-Scott

Sep 30, 2010 at 1:47 PM

Keeping a close eye on this one as I want to do a similar thing.  There's a big discussion on MSDN about this very thing and someone's come up with a similar solution to yours

http://hyper-v-stuff.blogspot.com/2010/04/csv-backup-troubles-and-definitely-not.html

http://social.technet.microsoft.com/Forums/en/windowsserver2008r2highavailability/thread/1f08c5a3-2366-4fe6-8cdb-e85a11f383c6

 

Oct 4, 2010 at 5:23 PM

Sorry about the long delay...  I got to testing two weeks ago.  I wrote a test app that simply backs up the whole drive (not working in component mode).

I started off with backing up plain files... .doc, .txt, and so on.  That worked great.  When I moved on to backing up a running virtual machine on a 'regular' local drive (non clustered, simple volume) the shadow copy completes and I can copy off of the VHD via exposed drive, but it is a crash consistent copy.  Not what I want. 

This tells me I'm not getting the Hyper-V VSS Writer involved correctly - I most likely have to work in component mode.  I've looked over an over again for documentation on working with the Hyper-V writer, or any writer for that matter, and have struck out.  Does anybody have any ideas on where I can get some better information, or at least some how tos/lessons learned on working in component mode?

Thanks,

-Scott

Oct 5, 2010 at 8:08 AM

I'll see what I can find.  In the meantime, can you show what you managed to do so far?  I'm interested in being able to make a snapshot of a CSV and then copy off the VHDs to a local/network drive.

 

Nov 2, 2010 at 10:04 PM

Okay, finally had a chance to get back to this.  As before, I am able to create snapshots, expose them as a local drive, and copy data off, but I only get crash consistent backups of Virtual Machines on the volumes I snapshot.  I'm pretty sure I'm not getting the Hyper-V writer involved since I'm currently not using component mode.  Not looking at this for a while has actually been benificial since I've got a better idea about what I want to do, but I'm still a little confused on how to get there.  Specifically, I know I need to create an instance of IVssExamineWriterMetadata, but I'm not sure how to do that since it looks like the AlphaVSS implemenatation only allows an instance to be created from a pre-existing XML document.  Is that true?  The MSDN documentation states that what I need is an instance of this interface that corresponds to the active writer, which is returned by IVssBackupComponents::GetWriterMetadata - this method is not implemented by the AlphaVSS interface although GatherWriterMetadata is.  Is there some other way to get at the metadata for the active writers?  Am I even close?

Here is the important part of the code I have right now:

public void CreateShadowCopies(ArrayList drivesToShadowCopy)
{
	if (_backup != null)
	{
		throw new InvalidOperationException("IVss_backupComponent object has already been intantiated.");
	}
	IVssImplementation vss = VssUtils.LoadImplementation();
	_backup = vss.CreateVss_backupComponents();
	_backup.InitializeFor_backup(null);
	_backup.Set_backupState(false, false, Vss_backupType.Full, false);
	using (IVssAsync async = _backup.GatherWriterMetadata())
	{
		async.Wait();
		async.Dispose();
	}
	_backup.SetContext(VssSnapshotContext.AppRollback);
	_shadowCopySetID = _backup.StartSnapshotSet();
	foreach (string drive in drivesToShadowCopy)
	{
		Guid scID;
		scID = _backup.AddToSnapshotSet(drive);
		ShadowCopyID newScID = new ShadowCopyID();
		newScID.DriveID = drive;
		newScID.SnapshotID = scID;
		_shadowCopyIds.Add(newScID);
	}
	using (IVssAsync async = _backup.PrepareFor_backup())
	{
		async.Wait();
		async.Dispose();
	}
	using (IVssAsync async = _backup.GatherWriterStatus())
	{
		async.Wait();
		async.Dispose();
	}
	using (IVssAsync async = _backup.DoSnapshotSet())
	{
		async.Wait();
		async.Dispose();
	}
	using (IVssAsync async = _backup.GatherWriterStatus())
	{
		async.Wait();
		async.Dispose();
	}
}
Any help is greatly appreciated!
-Scott
Dec 7, 2010 at 4:01 PM
Edited Dec 7, 2010 at 4:02 PM

Did you ever make any progress?  The best I could get was crash-consistent copies too.  It seems that it is VERY difficult to use the HyperV VSS Writer with CSVs.  Or, at least, Microsoft are making it difficult to find out so that we have to buy DPM!

I NEED to work in component mode as we only want to backup the VHDs containing the C: drives of each VM

Jan 11, 2011 at 10:23 PM

Again I appologize for the long gap - holidays sort of got in the way of all sorts of things.  I've yet to really come across anything new with this topic.  According to what I've found on MSDN,  an instance of IVssExamineWriterMetadata corresponding to the active writers returned from IVssBackupComponents::GetWriterMetadata is what I really need. 

decaf, you mentioned at the start of this thread that you could add additional features to AlphaVSS.  If my understanding of this issue is correct, is this a change you would be able to make?

Thanks,

-Scott

Jan 12, 2011 at 1:14 PM

If I'm not misunderstanding, it is already in there, in the Alphaleonis.Win32.Vss.IVssBackupComponents.WriterMetadata property.  Let me know if this is not what you were looking for.

Mar 11, 2011 at 5:13 PM
Edited Mar 11, 2011 at 5:16 PM

Okay... found some time to mess with this again...

Finally figured out component mode.  Thanks, decaf, for pointing out the WriterMetadata property - I blew right past that one.  Of course, now that I'm working in component mode, I've run into some more issues.  The first, and most significant, is that I am still getting crash consistent backups.  I have tried numerous variations of options with these backups including:  only enabling the Hyper-V writer and adding all its components; enabling all the writers avalable but only adding the Hyper-V wrtier's components; enabling all writers and adding the selectable components for each writer; setting the backups for bootable system state. 

Here is the code I'm currently using (I tried cleaning up the irrelevant debug stuff, but I missed some please disregard).  I kept in the commented out code where I disable everything besides the Hyper-V writer for reference....

public void CreateShadowCopies(List<string> drivesToShadowCopy)
        {
            if (_backup != null)
            {
                throw new InvalidOperationException("IVssBackupComponent object has already been intantiated.");
            }
            
            _log.WriteToLog("Initializing Shadow Copy Job");
            IVssImplementation vss = VssUtils.LoadImplementation();
            _backup = vss.CreateVssBackupComponents();
            _backup.InitializeForBackup(null);

            _log.WriteToLog("  - DEBUG - Setting VSS Backup Type (State) to Component Mode and Full");
            _backup.SetBackupState(true, true, VssBackupType.Full, false);

            
            /*
            _log.WriteToLog("  - DEBUG - Disabling unwanted writers");
            List<IVssExamineWriterMetadata> writers = GetAvailableWriters();
            foreach (IVssExamineWriterMetadata writer in writers)
            {
                if (writer.WriterName.Equals("Microsoft Hyper-V VSS Writer"))
                {
                    _backup.EnableWriterClasses(writer.WriterId);
                }
                else
                {
                    _backup.DisableWriterClasses(writer.WriterId);
                }
            }
            foreach (IVssExamineWriterMetadata writer in writers)
            {
                writer.Dispose();
            }
            writers = null;
            _log.WriteToLog("  - DEBUG - Unwanted writers disabled");

             */ 
            
            using (IVssAsync async = _backup.GatherWriterMetadata())
            {
                async.Wait();
                async.Dispose();
            }

            _backup.SetContext(VssSnapshotContext.AppRollback);

            foreach (IVssExamineWriterMetadata writer in _backup.WriterMetadata)
            {
                if (writer.WriterName.Equals("Microsoft Hyper-V VSS Writer"))
                {
                    foreach (IVssWMComponent component in writer.Components)
                    {
                        bool addComponent = false;
                        foreach (VssWMFileDescription file in component.Files)
                        {
                            if (!string.IsNullOrEmpty(file.Path))
                            {
                                //
                                // This needs alteration to support CSVs
                                //
                                string drive = file.Path.Substring(0, 3);
                                if (drive.Contains(':') && drive.Contains('\\') && drivesToShadowCopy.Contains(drive))
                                {
                                    addComponent = true;
                                    break;
                                }
                            }
                        }
                        if (addComponent)
                        {
                            _backup.AddComponent(writer.InstanceId, writer.WriterId, component.Type, component.LogicalPath, component.ComponentName);
                        }
                    }
                }
                else
                {
                    foreach (IVssWMComponent comp in writer.Components)
                    {
                        if (comp.Selectable)
                        {
                            _backup.AddComponent(writer.InstanceId, writer.WriterId, comp.Type, comp.LogicalPath, comp.ComponentName);
                        }
                    }
                }
            }

            _shadowCopySetID = _backup.StartSnapshotSet();

            foreach (string drive in drivesToShadowCopy)
            {
                Guid scID;
                scID = _backup.AddToSnapshotSet(drive);
                _log.WriteToLog("VSS has assigned Shadow Copy the ID " + scID.ToString());
                ShadowCopyID newScID = new ShadowCopyID();
                newScID.DriveID = drive;
                newScID.SnapshotID = scID;
                _shadowCopyIds.Add(newScID);
            }

            using (IVssAsync async = _backup.PrepareForBackup())
            {
                async.Wait();
                async.Dispose();
            }

            using (IVssAsync async = _backup.GatherWriterStatus())
            {
                async.Wait();
                async.Dispose();
            }

            _log.WriteToLog(" *** WRITER STATUS:");
            foreach (VssWriterStatusInfo status in _backup.WriterStatus)
            {
                _log.WriteToLog(" *** Writer NAME: " + status.Name + " - STATE: " + status.State + " - FAILURE: " + status.Failure);
            }

            _log.WriteToLog("Creating Shadow Copy of drive...");
            using (IVssAsync async = _backup.DoSnapshotSet())
            {
                async.Wait();
                async.Dispose();
            }
                    
            using (IVssAsync async = _backup.GatherWriterStatus())
            {
                async.Wait();
                async.Dispose();
            }

            _log.WriteToLog(" *** WRITER STATUS:");
            foreach (VssWriterStatusInfo status in _backup.WriterStatus)
            {
                _log.WriteToLog(" *** Writer NAME: " + status.Name + " - STATE: " + status.State + " - FAILURE: " + status.Failure);
            }


            _log.WriteToLog("Shadow Copy of drive completed.");

        }
 Another strange thing I'm seeing is VSSADMIN reports the shadow copies I'm making as Differentials.  VSSADMIN output:

vssadmin 1.1 - Volume Shadow Copy Service administrative command-line tool
(C) Copyright 2001-2005 Microsoft Corp.

 

Contents of shadow copy set ID: {be98b759-3253-47a5-bc6b-730013460a3b}
   Contained 2 shadow copies at creation time: 3/10/2011 4:20:48 PM
      Shadow Copy ID: {a4a5a646-1786-412b-9983-1ce5e383748e}
         Original Volume: (M:)\\?\Volume{038e6092-49ab-11e0-b23a-0022198fb98b}\
         Shadow Copy Volume: \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy30
         Originating Machine: HV-TEST01.virtual.rp
         Service Machine: HV-TEST01.virtual.rp
         Provider: 'Microsoft Software Shadow Copy provider 1.0'
         Type: ApplicationRollback
         Attributes: Persistent, No auto release, Differential, Auto recovered

 

      Shadow Copy ID: {aebba370-42b7-4d9f-9794-285e0fe18c98}
         Original Volume: (C:)\\?\Volume{7bf5d79d-490a-11e0-9fdd-806e6f6e6963}\
         Shadow Copy Volume: \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy29
         Originating Machine: HV-TEST01.virtual.rp
         Service Machine: HV-TEST01.virtual.rp
         Provider: 'Microsoft Software Shadow Copy provider 1.0'
         Type: ApplicationRollback
         Attributes: Persistent, No auto release, Differential, Auto recovered

 

 

So thats where I am. Anybody have any ideas or suggestions? Am I setting the context and state correctly for full backups?

 

Thanks for the help...

 

-Scott

May 12, 2011 at 11:17 AM

Scott,

Had any more luck?  I've now been asked to amend the tool I wrote (I didn't use AlphaVSS, I leveraged DiskShadow and wrote out the input script for it) so that I can back up individual VHDs on an ad-hoc basis. 

So it looks like I'm going to need to use AlphaVSS to do it :)  I see there is a comment there about needing to amend it for CSVs.  Can you clarify what you mean?  I already use the ClusterPrepareSharedVolumeForBackup

API call in my current tool, is that what you are referring to?

May 13, 2011 at 2:14 PM

Using your code I get "The requested object does not exist" when executing the AddToSnapShot method.  I'm trying to add a cluster volume using the \\VOLUME\GUID syntax. 

It works with DiskShadow though which is odd.

May 18, 2011 at 2:24 PM
Edited May 18, 2011 at 4:12 PM

HA!  Figured it out.  That'll teach me to read the documentation!  The Volume Mount Point needs a trailing slash.  The GUID of a CSV from WMI doesn't have it.

As is stands I now have code to prepare a CSV for backup, create a shadowset of it and expose it as a local drive.  I'm now copying off a VHD of a running machine.  I'll then create a new VM using the backup VHD and we'll see if it's crash-consistent.

edit:  Nope, it wasn't :(

May 19, 2011 at 5:21 PM

Ginolard,

Thanks for carrying this forward.  My company currently uses Veeam to backup our vmware environments and now that Veeam has announced that it will be supporting HyperV later this year this project has been pretty muched shelved... as long as the Veeam licensing isn't too outrageous anyway.

In using/testing Veeam for vmware (which does, according to the documentation, take non crash-consistent backups) I did come across an interesting nugget.  When the backed up vms are booted, the OS still comes up as though it just crashed - you get the boot menu saying the machine was not properly shutdown.  From what I've read in the Veeam documentation, this is what is supposed to happen.  Apparently the applications running on the vm dump their data and are consistent, but the OS is not.  We've tested MS exchange 2003 a few times and it has always come up clean.  I will say that I'm not completely sold on this however... it feels like the OS should come up clean as well.

So what all that means is that I'm not so sure that the backups I was taking using AlphaVss were crash consistent.  I pretty much got the same results as we saw with the Veeam backups.

Any ideas on fully testing this out?  I can honestly say that I don't have a ton of time to invest in it right now... perhaps later in the summer.

-Scott

May 20, 2011 at 6:39 AM

I've tested Hyperoo as well and it works very well.  It also uses the AlphaVSS libraries although whether they include the writers or not I'm not sure.  It's also very reasonably priced ($670 for 10 licences)

Jul 14, 2011 at 9:03 AM
Edited Jul 14, 2011 at 9:43 AM

Woooohoooo!  Finally.  After months of messing about, leaving it and then coming back to it and general teeth-gnashing I now have a small tool that will

 

a) Enumerate every CSV in the cluster

b) Enumerate every VM on each node in turn and retrieve the VHD linked to the System drive (data on other VHDs are handled by Legato)

b) Check if the VHD is on the CSV being backed up.

c) If so. put the CSV in "redirected mode"

d) Copy the VHDs off to a remote share

e) Put the CSV back in Direct Access mode and move it back to the original owning node.

 

Like Scott, I'm not 100% certain that they are crash-consitent copies as I get the "Windows Recovery" menu when I boot from a restore.  However, I've done several tests and the OS always restarts without a problem.

Given that we have no other backup solution other than the ridiculously expensive DPM this will suffice for now. 

Scott, thanks for all your work on this.  It helped me understand the AlphaVSS libraries immensely.  Figuring out the Cluster API was a bitch though!  Then there were nasty little gotchas like the CSV GUID bloody well changing when it moves host (which it does when you put it in re-directed I/O state).  That one got me for ages.  I couldn't understand why I KNEW I had the correct GUID but the ShadowSet would never create using said GUID.  Oh no, you have to get the GUID of the CSV AFTER it's been put into re-directed state.  And then you have to use WMI to get it.

Nov 3, 2012 at 8:45 PM

Hello,

sorry, somebody has a working app/example code/snippets which can create a shadow copy of clustered shared volumes using alphavss?

Maybe he is willing to share this with me/us?

Regards 

Aug 29, 2013 at 2:10 PM
Not sure if you are still checking this thread but yeah I have some. Strictly speaking I can't just give it to you as I wrote it for my employer so they "own" it.

I can give you plenty of advice though