generated from amazon-archives/__template_MIT-0
-
Notifications
You must be signed in to change notification settings - Fork 40
Add Netapp Ontap utils and custom tasks for horde #848
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
MaorNetApp
wants to merge
2
commits into
aws-games:main
Choose a base branch
from
MaorNetApp:add-netapp-ontap-custom-tasks-for-horde
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| # Unreal Engine BuildGraph ONTAP Integration | ||
|
|
||
| Custom BuildGraph tasks for integrating Perforce syncing with NetApp ONTAP FlexClone operations. | ||
|
|
||
| ## Files | ||
|
|
||
| **Tasks/** - C# BuildGraph task implementations | ||
| - `SyncAndSnapshotTask.cs` - Sync from Perforce and create ONTAP snapshot | ||
| - `CloneVolumeTask.cs` - Create FlexClone volume from snapshot | ||
| - `DeleteVolumeTask.cs` - Delete ONTAP volume | ||
| - `DeleteSnapshotTask.cs` - Delete ONTAP snapshot | ||
|
|
||
| **AutomationUtils/** - Helper utilities | ||
| - `OntapUtils.cs` - ONTAP REST API operations and AWS Secrets Manager integration | ||
|
|
||
| **Examples/** - BuildGraph XML workflows | ||
| - `SyncAndSnapshotExample.xml` - Sync from Perforce and snapshot | ||
| - `CloneVolumeExample.xml` - Create FlexClone from snapshot | ||
| - `DeleteVolumeExample.xml` - Delete clone and snapshot | ||
|
|
||
| ## Prerequisites | ||
|
|
||
| - AWS CLI configured with credentials | ||
hwkiem marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| - Perforce client (p4) | ||
| - AWS Secrets Manager secret containing FSx ONTAP password | ||
MaorNetApp marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| - FSx ONTAP file system with SVM configured | ||
|
|
||
| ## Common Parameters | ||
|
|
||
| | Parameter | Description | Default | | ||
| |-----------|-------------|---------| | ||
| | `FsxAdminIp` | FSx ONTAP management IP | - | | ||
| | `OntapUser` | ONTAP username | fsxadmin | | ||
| | `OntapPasswordSecretName` | AWS secret name for ONTAP password | - | | ||
| | `AwsRegion` | AWS region | us-east-1 | | ||
| | `SvmName` | Storage Virtual Machine name | fsx | | ||
|
|
||
| ## Notes | ||
|
|
||
| - Snapshot deletion may fail immediately after clone deletion due to ONTAP lock timing | ||
| - FlexClone volumes are full read/write volumes with instant creation | ||
| - AWS Secrets Manager password retrieval is handled automatically by OntapUtils class | ||
| - All ONTAP operations use REST API over HTTPS (self-signed certificates accepted) | ||
MaorNetApp marked this conversation as resolved.
Show resolved
Hide resolved
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| <?xml version='1.0' ?> | ||
| <BuildGraph xmlns="http://www.epicgames.com/BuildGraph" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.epicgames.com/BuildGraph ../../Schema.xsd" > | ||
|
|
||
| <!-- Example usage of the CloneVolume custom task --> | ||
| <!-- This creates a FlexClone volume from an existing snapshot --> | ||
|
|
||
| <!-- Parameters that can be set from Horde --> | ||
| <Option Name="SourceVolume" Description="Source volume to clone from" /> | ||
| <Option Name="SnapshotName" Description="Snapshot to use for cloning" /> | ||
| <Option Name="CloneVolumeName" Description="Name for the new FlexClone volume" /> | ||
| <Option Name="SvmName" DefaultValue="fsx" Description="Storage Virtual Machine name" /> | ||
| <Option Name="FsxAdminIp" Description="FSx ONTAP management IP address" /> | ||
| <Option Name="OntapUser" DefaultValue="fsxadmin" Description="ONTAP username" /> | ||
hwkiem marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| <Option Name="OntapPasswordSecretName" Description="AWS Secrets Manager secret name for ONTAP password" /> | ||
| <Option Name="AwsRegion" DefaultValue="us-east-1" Description="AWS region for the secret" /> | ||
|
|
||
| <Agent Name="CloneAgent" Type="AnyAgent"> | ||
| <Node Name="Clone Volume"> | ||
| <!-- Create FlexClone volume from existing snapshot --> | ||
| <CloneVolume | ||
| SourceVolume="$(SourceVolume)" | ||
| SnapshotName="$(SnapshotName)" | ||
| CloneVolumeName="$(CloneVolumeName)" | ||
| SvmName="$(SvmName)" | ||
| FsxAdminIp="$(FsxAdminIp)" | ||
| OntapUser="$(OntapUser)" | ||
| OntapPasswordSecretName="$(OntapPasswordSecretName)" | ||
| AwsRegion="$(AwsRegion)" /> | ||
| </Node> | ||
| </Agent> | ||
| </BuildGraph> | ||
MaorNetApp marked this conversation as resolved.
Show resolved
Hide resolved
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| <?xml version='1.0' ?> | ||
| <BuildGraph xmlns="http://www.epicgames.com/BuildGraph" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.epicgames.com/BuildGraph ../../Schema.xsd" > | ||
|
|
||
| <!-- Example usage of DeleteVolume and DeleteSnapshot tasks --> | ||
| <!-- This deletes a cloned volume first, then its source snapshot --> | ||
|
|
||
| <!-- Parameters that can be set from Horde --> | ||
| <Option Name="CloneVolumeName" Description="Name of the cloned volume to delete" /> | ||
| <Option Name="SourceVolumeName" Description="Name of the source volume containing the snapshot" /> | ||
| <Option Name="SnapshotName" Description="Name of the snapshot to delete (that was used to create the clone)" /> | ||
| <Option Name="SvmName" DefaultValue="fsx" Description="Storage Virtual Machine name" /> | ||
| <Option Name="FsxAdminIp" Description="FSx ONTAP management IP address" /> | ||
| <Option Name="OntapUser" DefaultValue="fsxadmin" Description="ONTAP username" /> | ||
| <Option Name="OntapPasswordSecretName" Description="AWS Secrets Manager secret name for ONTAP password" /> | ||
| <Option Name="AwsRegion" DefaultValue="us-east-1" Description="AWS region for the secret" /> | ||
|
|
||
| <Agent Name="CleanupAgent" Type="AnyAgent"> | ||
| <Node Name="Delete Clone and Snapshot"> | ||
| <!-- Step 1: Delete the cloned volume first --> | ||
| <DeleteVolume | ||
| VolumeName="$(CloneVolumeName)" | ||
| SvmName="$(SvmName)" | ||
| FsxAdminIp="$(FsxAdminIp)" | ||
| OntapUser="$(OntapUser)" | ||
| OntapPasswordSecretName="$(OntapPasswordSecretName)" | ||
| AwsRegion="$(AwsRegion)" /> | ||
|
|
||
| <!-- Step 2: Delete the snapshot that was used to create the clone --> | ||
| <DeleteSnapshot | ||
| VolumeName="$(SourceVolumeName)" | ||
| SnapshotName="$(SnapshotName)" | ||
| FsxAdminIp="$(FsxAdminIp)" | ||
| OntapUser="$(OntapUser)" | ||
| OntapPasswordSecretName="$(OntapPasswordSecretName)" | ||
| AwsRegion="$(AwsRegion)" /> | ||
| </Node> | ||
| </Agent> | ||
|
|
||
| </BuildGraph> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| <?xml version='1.0' ?> | ||
| <BuildGraph xmlns="http://www.epicgames.com/BuildGraph" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.epicgames.com/BuildGraph ../../Schema.xsd" > | ||
|
|
||
| <!-- Example usage of the SyncAndSnapshot custom task --> | ||
|
|
||
| <!-- Parameters that can be set from Horde --> | ||
| <Option Name="Stream" Description="Perforce stream to sync from" /> | ||
| <Option Name="P4Port" DefaultValue="perforce:1666" Description="Perforce server address" /> | ||
| <Option Name="P4User" DefaultValue="perforce" Description="Perforce username" /> | ||
| <Option Name="SyncDir" Description="Directory to sync files to, need to be the path to the fsx volume (defaults to current working directory)" /> | ||
| <Option Name="WorkspaceName" DefaultValue="checkoutWorkspace" Description="Perforce workspace name" /> | ||
|
|
||
| <!-- ONTAP Snapshot Parameters --> | ||
| <Option Name="SnapshotName" Description="Name for the ONTAP snapshot" /> | ||
| <Option Name="FsxAdminIp" Description="FSx ONTAP management IP address" /> | ||
| <Option Name="OntapUser" DefaultValue="fsxadmin" Description="ONTAP username" /> | ||
| <Option Name="OntapPasswordSecretName" Description="AWS Secrets Manager secret name for ONTAP password" /> | ||
| <Option Name="AwsRegion" DefaultValue="us-east-1" Description="AWS region for the secret" /> | ||
| <Option Name="VolumeName" Description="ONTAP volume name to take the snapshot from" /> | ||
|
|
||
| <Agent Name="SyncAgent" Type="AnyAgent"> | ||
| <Node Name="Sync From Stream"> | ||
| <!-- Sync from Perforce stream and create ONTAP snapshot --> | ||
| <SyncAndSnapshot Stream="$(Stream)" P4Port="$(P4Port)" P4User="$(P4User)" SyncDir="$(SyncDir)" WorkspaceName="$(WorkspaceName)" SnapshotName="$(SnapshotName)" FsxAdminIp="$(FsxAdminIp)" OntapUser="$(OntapUser)" OntapPasswordSecretName="$(OntapPasswordSecretName)" AwsRegion="$(AwsRegion)" VolumeName="$(VolumeName)" /> | ||
| </Node> | ||
| </Agent> | ||
| </BuildGraph> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,234 @@ | ||
| using System; | ||
| using System.Collections.Generic; | ||
| using System.IO; | ||
| using System.Linq; | ||
| using System.Threading.Tasks; | ||
| using System.Xml; | ||
| using EpicGames.Core; | ||
| using Microsoft.Extensions.Logging; | ||
| using UnrealBuildBase; | ||
|
|
||
| namespace AutomationTool.Tasks | ||
| { | ||
| /// <summary> | ||
| /// Parameters for the CloneVolume task | ||
| /// </summary> | ||
| public class CloneVolumeTaskParameters | ||
| { | ||
| /// <summary> | ||
| /// Name of the source volume to clone from. | ||
| /// </summary> | ||
| [TaskParameter] | ||
| public string SourceVolume { get; set; } | ||
|
|
||
| /// <summary> | ||
| /// Name of the snapshot to use for cloning. | ||
| /// </summary> | ||
| [TaskParameter] | ||
| public string SnapshotName { get; set; } | ||
|
|
||
| /// <summary> | ||
| /// Name for the new FlexClone volume. | ||
| /// </summary> | ||
| [TaskParameter] | ||
| public string CloneVolumeName { get; set; } | ||
|
|
||
| /// <summary> | ||
| /// Storage Virtual Machine (SVM) name in ONTAP. | ||
| /// </summary> | ||
| [TaskParameter] | ||
| public string SvmName { get; set; } | ||
|
|
||
| /// <summary> | ||
| /// FSx ONTAP management IP address. | ||
| /// </summary> | ||
| [TaskParameter] | ||
| public string FsxAdminIp { get; set; } | ||
|
|
||
| /// <summary> | ||
| /// ONTAP username (e.g., vsadmin). | ||
| /// </summary> | ||
| [TaskParameter] | ||
| public string OntapUser { get; set; } | ||
|
|
||
| /// <summary> | ||
| /// AWS Secrets Manager secret name containing the FSx password. | ||
| /// </summary> | ||
| [TaskParameter] | ||
| public string OntapPasswordSecretName { get; set; } | ||
|
|
||
| /// <summary> | ||
| /// AWS region where the secret is stored. | ||
| /// </summary> | ||
| [TaskParameter] | ||
| public string AwsRegion { get; set; } | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Creates a FlexClone volume from an existing snapshot. | ||
| /// </summary> | ||
| [TaskElement("CloneVolume", typeof(CloneVolumeTaskParameters))] | ||
| public class CloneVolumeTask : CustomTask | ||
| { | ||
| /// <summary> | ||
| /// Parameters for the task | ||
| /// </summary> | ||
| private readonly CloneVolumeTaskParameters _parameters; | ||
|
|
||
| /// <summary> | ||
| /// Constructor | ||
| /// </summary> | ||
| /// <param name="parameters">Parameters for this task</param> | ||
| public CloneVolumeTask(CloneVolumeTaskParameters parameters) | ||
| { | ||
| _parameters = parameters; | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Execute the task. | ||
| /// </summary> | ||
| /// <param name="job">Information about the current job</param> | ||
| /// <param name="buildProducts">Set of build products produced by this node.</param> | ||
| /// <param name="tagNameToFileSet">Mapping from tag names to the set of files they include</param> | ||
| public override void Execute(JobContext job, HashSet<FileReference> buildProducts, Dictionary<string, HashSet<FileReference>> tagNameToFileSet) | ||
| { | ||
| // Validate all required parameters | ||
| ValidateParameters(); | ||
|
|
||
| Logger.LogInformation("Starting FlexClone volume creation"); | ||
| Logger.LogInformation("Source Volume: {SourceVolume}", _parameters.SourceVolume); | ||
| Logger.LogInformation("Snapshot: {SnapshotName}", _parameters.SnapshotName); | ||
| Logger.LogInformation("Clone Volume: {CloneVolumeName}", _parameters.CloneVolumeName); | ||
| Logger.LogInformation("SVM: {SvmName}", _parameters.SvmName); | ||
|
|
||
| try | ||
| { | ||
| CreateFlexCloneVolumeAsync().Wait(); | ||
| Logger.LogInformation("FlexClone volume creation completed successfully"); | ||
| } | ||
| catch (Exception ex) | ||
| { | ||
| Logger.LogError(ex, "Failed to create FlexClone volume '{CloneVolumeName}'", _parameters.CloneVolumeName); | ||
| throw; | ||
| } | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Validates that all required parameters are provided | ||
| /// </summary> | ||
| private void ValidateParameters() | ||
| { | ||
| if (String.IsNullOrEmpty(_parameters.SourceVolume)) | ||
| { | ||
| throw new AutomationException("SourceVolume parameter is required"); | ||
| } | ||
| if (String.IsNullOrEmpty(_parameters.SnapshotName)) | ||
| { | ||
| throw new AutomationException("SnapshotName parameter is required"); | ||
| } | ||
| if (String.IsNullOrEmpty(_parameters.CloneVolumeName)) | ||
| { | ||
| throw new AutomationException("CloneVolumeName parameter is required"); | ||
| } | ||
| if (String.IsNullOrEmpty(_parameters.SvmName)) | ||
| { | ||
| throw new AutomationException("SvmName parameter is required"); | ||
| } | ||
| if (String.IsNullOrEmpty(_parameters.FsxAdminIp)) | ||
| { | ||
| throw new AutomationException("FsxAdminIp parameter is required"); | ||
| } | ||
| if (String.IsNullOrEmpty(_parameters.OntapUser)) | ||
| { | ||
| throw new AutomationException("OntapUser parameter is required"); | ||
| } | ||
| if (String.IsNullOrEmpty(_parameters.OntapPasswordSecretName)) | ||
| { | ||
| throw new AutomationException("OntapPasswordSecretName parameter is required"); | ||
| } | ||
| if (String.IsNullOrEmpty(_parameters.AwsRegion)) | ||
| { | ||
| throw new AutomationException("AwsRegion parameter is required"); | ||
| } | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Creates a FlexClone volume from an existing snapshot | ||
| /// </summary> | ||
| private async Task CreateFlexCloneVolumeAsync() | ||
| { | ||
| try | ||
| { | ||
| // Create OntapUtils instance | ||
| OntapUtils ontapUtils = new OntapUtils( | ||
| _parameters.FsxAdminIp, | ||
| _parameters.OntapUser, | ||
| _parameters.OntapPasswordSecretName, | ||
| _parameters.AwsRegion, | ||
| Logger); | ||
|
|
||
| // Verify source volume exists | ||
| Logger.LogInformation("Verifying source volume '{SourceVolume}' exists...", _parameters.SourceVolume); | ||
| bool sourceExists = await ontapUtils.VolumeExistsAsync(_parameters.SourceVolume, _parameters.SvmName); | ||
|
|
||
| if (!sourceExists) | ||
| { | ||
| throw new AutomationException($"Source volume '{_parameters.SourceVolume}' not found in SVM '{_parameters.SvmName}'"); | ||
| } | ||
|
|
||
| Logger.LogInformation("Source volume '{SourceVolume}' verified", _parameters.SourceVolume); | ||
|
|
||
| // Check if clone volume already exists | ||
| Logger.LogInformation("Checking if clone volume '{CloneVolumeName}' already exists...", _parameters.CloneVolumeName); | ||
| bool cloneExists = await ontapUtils.VolumeExistsAsync(_parameters.CloneVolumeName, _parameters.SvmName); | ||
|
|
||
| if (cloneExists) | ||
| { | ||
| throw new AutomationException($"Clone volume '{_parameters.CloneVolumeName}' already exists. Please delete it first or use a different name."); | ||
| } | ||
|
|
||
| // Create the FlexClone volume | ||
| string cloneVolumeName = await ontapUtils.CreateFlexCloneVolumeAsync( | ||
| _parameters.SourceVolume, | ||
| _parameters.SnapshotName, | ||
| _parameters.CloneVolumeName, | ||
| _parameters.SvmName); | ||
|
|
||
| Logger.LogInformation("FlexClone volume '{CloneVolumeName}' created successfully", cloneVolumeName); | ||
| Logger.LogInformation("Junction Path: /{CloneVolumeName}", cloneVolumeName); | ||
| Logger.LogInformation("✅ Full read/write regular NetApp volume"); | ||
| } | ||
| catch (Exception ex) | ||
| { | ||
| Logger.LogError(ex, "Failed to create FlexClone volume"); | ||
| throw new AutomationException(ex, "Failed to create FlexClone volume"); | ||
| } | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Output this task out to an XML writer. | ||
| /// </summary> | ||
| public override void Write(XmlWriter writer) | ||
| { | ||
| Write(writer, _parameters); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Find all the tags which are used as inputs to this task | ||
| /// </summary> | ||
| /// <returns>The tag names which are read by this task</returns> | ||
| public override IEnumerable<string> FindConsumedTagNames() | ||
| { | ||
| return Enumerable.Empty<string>(); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Find all the tags which are modified by this task | ||
| /// </summary> | ||
| /// <returns>The tag names which are modified by this task</returns> | ||
| public override IEnumerable<string> FindProducedTagNames() | ||
| { | ||
| return Enumerable.Empty<string>(); | ||
| } | ||
| } | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why create a new tasks for syncing and snapshotting as opposed to using the built in sync capabilities of Horde?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In built in sync of horde it will create folder named the task we run, and in the folder the project will be inside /Sync/ProjectName.
So if we will clone the volume and mount it the project will be under /TaskName/Sync/Project
I can remove the sync task at all, but there will be other files except the project folder
what will be best approach of that ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@hwkiem Please advise how to progress