Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions docs/azmcp-commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -798,6 +798,37 @@ azmcp azuremanagedlustre filesystem required-subnet-size --subscription <subscri

azmcp azuremanagedlustre filesystem sku get --subscription <subscription> \
--location <location>

# Create an Azure Managed Lustre filesystem
azmcp azuremanagedlustre filesystem create --subscription <subscription> \
--sku <sku> \
--size <size> \
--subnet-id <subnet-id> \
--zone <zone> \
--maintenance-day <maintenance-day> \
--maintenance-time <maintenance-time> \
[--hsm-container <hsm-container>] \
[--hsm-log-container <hsm-log-container>] \
[--import-prefix <import-prefix>] \
[--root-squash-mode <root-squash-mode>] \
[--no-squash-nid-list <no-squash-nid-list>] \
[--squash-uid <squash-uid>] \
[--squash-gid <squash-gid>] \
[--custom-encryption] \
[--key-url <key-url>] \
[--source-vault <source-vault>] \
[--user-assigned-identity-id <user-assigned-identity-id>]

# Update an existing Azure Managed Lustre filesystem
azmcp azuremanagedlustre filesystem update --subscription <subscription> \
--resource-group <resource-group> \
--name <filesystem-name> \
[--maintenance-day <maintenance-day>] \
[--maintenance-time <HH:mm>] \
[--root-squash-mode <mode>] \
[--no-squash-nid-list <nid1,nid2,...>] \
[--squash-uid <uid>] \
[--squash-gid <gid>]
```

### Azure Native ISV Operations
Expand Down
2 changes: 1 addition & 1 deletion eng/pipelines/templates/jobs/live-test.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
parameters:
- name: TimeoutInMinutes
type: number
default: 60
default: 75

jobs:
- job: LiveTest
Expand Down
11 changes: 11 additions & 0 deletions servers/Azure.Mcp.Server/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,12 +69,23 @@ The Azure MCP Server updates automatically by default whenever a new release com
- Added support for retrieving knowledge index schema information in Azure AI Foundry projects via the command `azmcp_foundry_knowledge_index_schema`. [[#41](https://github.com/microsoft/mcp/pull/41)]
- Added support for listing service health events in a subscription via the command `azmcp_resourcehealth_service-health-events_list`. [[#367](https://github.com/microsoft/mcp/pull/367)]


### Breaking Changes

- Updated/removed options for the following commands: [[#108](https://github.com/microsoft/mcp/pull/108)]
- `azmcp_storage_account_create`: Removed the ability to configure `enable-https-traffic-only` (always `true` now), `allow-blob-public-access` (always `false` now), and `kind` (always `StorageV2` now).
- `azmcp_storage_blob_container_create`: Removed the ability to configure `blob-container-public-access` (always `false` now).
- `azmcp_storage_blob_upload`: Removed the ability to configure `overwrite` (always `false` now).
- Added the following Azure Managed Lustre commands: [[#50](https://github.com/microsoft/mcp/issues/50)]
- `azmcp_azuremanagedlustre_filesystem_create`: Create an Azure Managed Lustre filesystems.
- `azmcp_azuremanagedlustre_filesystem_update`: Update an Azure Managed Lustre filesystems.

### Breaking Changes

- Changed the following commands to change / remove available options
- Storage account create removed the ability to configure `enable-https-traffic-only` (always true now), `allow-blob-public-access` (always false now), and `kind` (always StorageV2 now).
- Storage blob container create removed the ability to configure `blob-container-public-access` (always false now).
- Storage blob upload removed the ability to configure `overwrite` (always false now).

### Bugs Fixed

Expand Down
1 change: 1 addition & 0 deletions servers/Azure.Mcp.Server/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ The Azure MCP Server supercharges your agents with Azure context. Here are some

* "List the Azure Managed Lustre clusters in resource group 'my-resource-group'"
* "How many IP Addresses I need to create a 128 TiB cluster of AMLFS 500?"
* Create a 4 TIB Azure Managed Lustre filesystem in 'my-region' attaching to 'my-subnet' in virtual network 'my-virtual-network'

### 📊 Azure Monitor

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,16 @@ public void ConfigureServices(IServiceCollection services)
public void RegisterCommands(CommandGroup rootGroup, ILoggerFactory loggerFactory)
{
var azureManagedLustre = new CommandGroup(Name,
"Azure Managed Lustre operations - Commands for listing and inspecting Azure Managed Lustre file systems (AMLFS) used for high-performance computing workloads.");
"Azure Managed Lustre operations - Commands for creating, listing and inspecting Azure Managed Lustre file systems (AMLFS) used for high-performance computing workloads. The tool focuses on managing all the aspects related to Azure Managed Lustre filesystem instances, import and export jobs from Azure Blob Storage.");
rootGroup.AddSubGroup(azureManagedLustre);

var fileSystem = new CommandGroup("filesystem", "Azure Managed Lustre file system operations - Commands for listing managed Lustre file systems.");
azureManagedLustre.AddSubGroup(fileSystem);

fileSystem.AddCommand("list", new FileSystemListCommand(loggerFactory.CreateLogger<FileSystemListCommand>()));
fileSystem.AddCommand("required-subnet-size", new FileSystemSubnetSizeCommand(loggerFactory.CreateLogger<FileSystemSubnetSizeCommand>()));
fileSystem.AddCommand("create", new FileSystemCreateCommand(loggerFactory.CreateLogger<FileSystemCreateCommand>()));
fileSystem.AddCommand("update", new FileSystemUpdateCommand(loggerFactory.CreateLogger<FileSystemUpdateCommand>()));

var sku = new CommandGroup("sku", "This group provides commands to discover and retrieve information about available Azure Managed Lustre SKUs, including supported tiers, performance characteristics, and regional availability. Use these commands to validate SKU options prior to provisioning or updating a filesystem.");
fileSystem.AddSubGroup(sku);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ namespace Azure.Mcp.Tools.AzureManagedLustre.Commands;
[JsonSerializable(typeof(FileSystemSubnetSizeCommand.FileSystemSubnetSizeResult))]
[JsonSerializable(typeof(FileSystemListCommand.FileSystemListResult))]
[JsonSerializable(typeof(SkuGetCommand.SkuGetResult))]
[JsonSerializable(typeof(FileSystemCreateCommand.FileSystemCreateResult))]
[JsonSerializable(typeof(FileSystemUpdateCommand.FileSystemUpdateResult))]
[JsonSerializable(typeof(LustreFileSystem))]
[JsonSerializable(typeof(AzureManagedLustreSkuInfo))]
[JsonSerializable(typeof(AzureManagedLustreSkuCapability))]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

using System.CommandLine.Parsing;
using System.Diagnostics.CodeAnalysis;
using Azure.Mcp.Core.Commands;
using Azure.Mcp.Core.Commands.Subscription;
using Azure.Mcp.Core.Extensions;
using Azure.Mcp.Tools.AzureManagedLustre.Options;
using Microsoft.Extensions.Logging;

Expand All @@ -15,4 +17,100 @@ public abstract class BaseAzureManagedLustreCommand<
{
// Currently no additional options beyond subscription + resource group
protected readonly ILogger<BaseAzureManagedLustreCommand<TOptions>> _logger = logger;

public virtual ValidationResult ValidateRootSquashOptions(CommandResult commandResult, CommandResponse? commandResponse = null)
{
var rootSquashMode = commandResult.GetValueOrDefault(AzureManagedLustreOptionDefinitions.RootSquashModeOption);
var noSquashNidLists = commandResult.GetValueOrDefault(AzureManagedLustreOptionDefinitions.NoSquashNidListsOption);
var squashUid = commandResult.GetValueOrDefault(AzureManagedLustreOptionDefinitions.SquashUidOption);
var squashGid = commandResult.GetValueOrDefault(AzureManagedLustreOptionDefinitions.SquashGidOption);


// If root squash mode is provided and not 'none', require UID, GID and no squash NID list
if (!string.IsNullOrWhiteSpace(rootSquashMode) && !rootSquashMode.Equals("None", StringComparison.OrdinalIgnoreCase))
{
if (!(squashUid.HasValue && squashGid.HasValue && !string.IsNullOrWhiteSpace(noSquashNidLists)))
{
if (commandResponse is not null)
{
commandResponse.Status = 400;
commandResponse.Message = "When --root-squash-mode is not 'None', --squash-uid, --squash-gid and --no-squash-nid-list must be provided.";
}
return new ValidationResult { IsValid = false, ErrorMessage = commandResponse?.Message };
}
}

return new ValidationResult { IsValid = true };

}

public virtual ValidationResult ValidateMaintenanceOptions(CommandResult commandResult, CommandResponse? commandResponse = null, bool update = false)
{
// Read values from the same option instances used during registration
var maintenanceDay = update ? commandResult.GetValueOrDefault(AzureManagedLustreOptionDefinitions.OptionalMaintenanceDayOption) : commandResult.GetValueOrDefault(AzureManagedLustreOptionDefinitions.MaintenanceDayOption);
var maintenanceTime = update ? commandResult.GetValueOrDefault(AzureManagedLustreOptionDefinitions.OptionalMaintenanceTimeOption) : commandResult.GetValueOrDefault(AzureManagedLustreOptionDefinitions.MaintenanceTimeOption);
var updateWithoutMaintenance = string.IsNullOrWhiteSpace(maintenanceDay) && string.IsNullOrWhiteSpace(maintenanceTime) && update;

if ((string.IsNullOrWhiteSpace(maintenanceDay) || string.IsNullOrWhiteSpace(maintenanceTime)) && !updateWithoutMaintenance)
{
if (commandResponse is not null)
{
commandResponse.Status = 400;
commandResponse.Message = "When updating maintenance window, both --maintenance-day and --maintenance-time must be specified.";
}
return new ValidationResult { IsValid = false, ErrorMessage = commandResponse?.Message };
}

return new ValidationResult { IsValid = true };

}

public virtual ValidationResult ValidateHSMOptions(CommandResult commandResult, CommandResponse? commandResponse = null)
{
// Read values from the same option instances used during registration
var hsmContainer = commandResult.GetValueOrDefault(AzureManagedLustreOptionDefinitions.HsmContainerOption);
var hsmLogContainer = commandResult.GetValueOrDefault(AzureManagedLustreOptionDefinitions.HsmLogContainerOption);
var hsmEnabled = !string.IsNullOrWhiteSpace(hsmContainer) || !string.IsNullOrWhiteSpace(hsmLogContainer);


// Always require both values if one is specified.
if (hsmEnabled && (string.IsNullOrWhiteSpace(hsmContainer) || string.IsNullOrWhiteSpace(hsmLogContainer)))
{
if (commandResponse is not null)
{
commandResponse.Status = 400;
commandResponse.Message = "When enabling Azure Blob Integration both data container and log container must be specified.";
}
return new ValidationResult { IsValid = false, ErrorMessage = commandResponse?.Message };
}

return new ValidationResult { IsValid = true };

}

public virtual ValidationResult ValidateEncryptionOptions(CommandResult commandResult, CommandResponse? commandResponse = null)
{
// Read values from the same option instances used during registration
var encryptionEnabled = commandResult.GetValueOrDefault(AzureManagedLustreOptionDefinitions.CustomEncryptionOption);
var keyUrl = commandResult.GetValueOrDefault(AzureManagedLustreOptionDefinitions.KeyUrlOption);
var sourceVault = commandResult.GetValueOrDefault(AzureManagedLustreOptionDefinitions.SourceVaultOption);
var userAssignedIdentityId = commandResult.GetValueOrDefault(AzureManagedLustreOptionDefinitions.UserAssignedIdentityIdOption);

if (encryptionEnabled == true)
{
if (string.IsNullOrWhiteSpace(keyUrl) || string.IsNullOrWhiteSpace(sourceVault) || string.IsNullOrWhiteSpace(userAssignedIdentityId))
{

if (commandResponse is not null)
{
commandResponse.Status = 400;
commandResponse.Message = "Missing Required options: key-url, source-vault, user-assigned-identity when custom-encryption is set";
}
return new ValidationResult { IsValid = false, ErrorMessage = commandResponse?.Message };
}
}

return new ValidationResult { IsValid = true };

}
}
Loading