Skip to content
Merged
Show file tree
Hide file tree
Changes from 95 commits
Commits
Show all changes
100 commits
Select commit Hold shift + click to select a range
24a2db9
Create extension
saifaldin14 Oct 22, 2025
f5b4378
Update src/migrate/azext_migrate/__init__.py
saifaldin14 Oct 22, 2025
67bb359
Fix import issues
saifaldin14 Oct 22, 2025
70c525b
Merge branch 'main' of https://github.com/saifaldin14/azure-cli-exten…
saifaldin14 Oct 22, 2025
c3021fb
Update src/migrate/setup.py
saifaldin14 Oct 22, 2025
f6e2dd8
Small
saifaldin14 Oct 22, 2025
0174a38
Merge branch 'main' of https://github.com/saifaldin14/azure-cli-exten…
saifaldin14 Oct 22, 2025
ae26651
Small lint
saifaldin14 Oct 22, 2025
09ff801
Small
saifaldin14 Oct 22, 2025
749bd43
disable lint for this check
saifaldin14 Oct 22, 2025
8002b06
Add json
saifaldin14 Oct 22, 2025
be276db
Fix licesnse issue
saifaldin14 Oct 22, 2025
8da3466
fix small
saifaldin14 Oct 22, 2025
d9fa098
Small
saifaldin14 Oct 22, 2025
68f0d46
Get rid of unused variables
saifaldin14 Oct 22, 2025
f916208
Add service name and code owner
saifaldin14 Oct 23, 2025
9ad08a3
Merge branch 'main' of https://github.com/saifaldin14/azure-cli-exten…
saifaldin14 Oct 23, 2025
8ae69d2
New version
saifaldin14 Oct 23, 2025
532cbb3
Style
saifaldin14 Oct 23, 2025
f216aa3
Small
saifaldin14 Oct 23, 2025
77d8eb0
Update
saifaldin14 Oct 23, 2025
f7558d6
Follow standard
saifaldin14 Oct 23, 2025
ea8d636
Add suggestions
saifaldin14 Oct 23, 2025
7117986
Small
saifaldin14 Oct 23, 2025
143028f
Not preview
saifaldin14 Oct 23, 2025
242fb99
Add flag to become experimental
saifaldin14 Oct 23, 2025
4dae020
Merge branch 'Azure:main' into main
saifaldin14 Oct 23, 2025
6a1f184
Update history
saifaldin14 Oct 23, 2025
4178016
Merge branch 'main' of https://github.com/saifaldin14/azure-cli-exten…
saifaldin14 Oct 23, 2025
8874d5e
Fix
saifaldin14 Oct 23, 2025
38b0de2
small
saifaldin14 Oct 23, 2025
cf0b180
Adding "Migrate" folder to the project
mettursathish Oct 23, 2025
0f7acb7
Create get job and remove replication commands
saifaldin14 Oct 24, 2025
5d4d83b
Add better error handling for jobs command
saifaldin14 Nov 3, 2025
2f8b6d8
Add better messages to remove protected item
saifaldin14 Nov 3, 2025
9ffb8e6
Return job id in remove command
saifaldin14 Nov 3, 2025
d3120e3
Move helpers
saifaldin14 Nov 3, 2025
ff6f498
Rename get discovered server helper
saifaldin14 Nov 3, 2025
0f4af5b
Refactor _initialize_replication_infrastructure_helpers
saifaldin14 Nov 3, 2025
cb8370b
Refactor new replication
saifaldin14 Nov 3, 2025
f4514e8
Refactor jobs
saifaldin14 Nov 3, 2025
5b482a7
Refactor delete protected item
saifaldin14 Nov 3, 2025
15ab074
Fix lint issues
saifaldin14 Nov 12, 2025
314d750
Merge branch 'main' into user/saif/newCommands
saifaldin14 Nov 12, 2025
f0dc844
Change release version
saifaldin14 Nov 12, 2025
743370b
Merge branch 'user/saif/newCommands' of https://github.com/saifaldin1…
saifaldin14 Nov 12, 2025
c373e29
Fix lint issues
saifaldin14 Nov 12, 2025
93ff490
Add fix
saifaldin14 Nov 12, 2025
86547d4
Updae correct version
saifaldin14 Nov 18, 2025
c71edfa
Put beta version before
saifaldin14 Nov 18, 2025
5c85e2b
Fix
saifaldin14 Nov 19, 2025
096fcc0
Update
saifaldin14 Nov 19, 2025
05a82bd
Fix bifurcation tool issue
saifaldin14 Nov 19, 2025
4ff904e
Update amh correctly if not proper
saifaldin14 Nov 19, 2025
d562112
Use current subscription id if not passed in
saifaldin14 Nov 19, 2025
c38da1d
Fix correct location and target resource group creation
saifaldin14 Nov 19, 2025
9b6e4c0
Create list protected items command
saifaldin14 Nov 19, 2025
7921583
Update versions
saifaldin14 Dec 22, 2025
8488ad7
Add __init__.py to all folders
saifaldin14 Dec 23, 2025
087bf1a
Create unit tests for get replication
saifaldin14 Dec 23, 2025
3613a0e
Update readme with accurate description of commands
saifaldin14 Dec 23, 2025
3a44467
Update readme
saifaldin14 Dec 23, 2025
9dac4d4
Create tests for jobs and remove commands
saifaldin14 Dec 23, 2025
93adc8f
Add more tests to increase coverage to 74%
saifaldin14 Dec 23, 2025
3b19466
Merge branch 'main' of https://github.com/mettursathish/azure-cli-ext…
mettursathish Dec 23, 2025
ffc8eac
Added migrate command
mettursathish Dec 23, 2025
9206119
Add start migration command
saifaldin14 Dec 23, 2025
e194aac
Address fixes
saifaldin14 Dec 26, 2025
709efcf
Merge branch 'main' into user/saif/newCommands
saifaldin14 Dec 26, 2025
3516cb0
Remove doc strings from custom.py
saifaldin14 Dec 26, 2025
ef3d351
Merge branch 'user/saif/newCommands' of https://github.com/saifaldin1…
saifaldin14 Dec 26, 2025
6f645fa
Add init
saifaldin14 Dec 26, 2025
9c628fd
Remove old file locations
saifaldin14 Dec 26, 2025
bc56712
Adding preview tag for commands, moving migration to a seperate folde…
mettursathish Dec 26, 2025
54be25e
Addressing style issues
mettursathish Dec 26, 2025
fc9b6d6
addressing the styles and removing the duplicate key
mettursathish Dec 26, 2025
189fbcf
addressing style issues
mettursathish Dec 26, 2025
12f8085
addesssing more style issues
mettursathish Dec 26, 2025
bac3d75
addressing inline disable at the specific line
mettursathish Dec 26, 2025
85ef1ed
Added R1702 to the pylint disable comment on the function definition.
mettursathish Dec 26, 2025
52efe2a
Addressing to disable too many nested blocks R1702
mettursathish Dec 26, 2025
e1995cb
Merge branch 'main' into user/saif/newCommands
saifaldin14 Dec 29, 2025
f4f58ec
fix failing tests
saifaldin14 Dec 29, 2025
6bfea6b
Fixing test cases and updating version changes
mettursathish Dec 29, 2025
2e469fa
Fix secret test
saifaldin14 Dec 30, 2025
384a0bf
Fix test
saifaldin14 Dec 30, 2025
3317afe
Fix secret detection
saifaldin14 Dec 30, 2025
faa2716
Fix duplicates
saifaldin14 Dec 30, 2025
59fd97f
Merge branch 'main' into user/saif/newCommands
saifaldin14 Dec 30, 2025
a898c56
Fix get-discovered-server parameter errors
saifaldin14 Jan 7, 2026
3a46f57
Merge branch 'Azure:main' into user/saif/newCommands
saifaldin14 Jan 8, 2026
3e23b99
Small
saifaldin14 Jan 12, 2026
b0cd11d
Merge branch 'Azure:main' into user/saif/newCommands
saifaldin14 Jan 13, 2026
620d94d
Update version
saifaldin14 Jan 13, 2026
06892a8
Merge branch 'user/saif/newCommands' of https://github.com/saifaldin1…
saifaldin14 Jan 13, 2026
b3bc481
Fix style issues
saifaldin14 Jan 13, 2026
370eb7d
Fix linter help
saifaldin14 Jan 13, 2026
2215b78
Disable linter
saifaldin14 Jan 13, 2026
3f55d7a
Fix help examples
saifaldin14 Jan 13, 2026
90ab86a
Exclusions
saifaldin14 Jan 13, 2026
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
4 changes: 4 additions & 0 deletions src/migrate/HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
Release History
===============

3.0.0b3
+++++++++++++++
* Fix edge case bugs with az migrate get-discovered-server.

3.0.0b2
+++++++++++++++
* Added replication list, get and start migration commands.
Expand Down
13 changes: 9 additions & 4 deletions src/migrate/azext_migrate/custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ def get_discovered_server(cmd,
from azext_migrate.helpers._utils import APIVersion
from azext_migrate.helpers._server import (
validate_get_discovered_server_params,
extract_machine_name_from_id,
build_base_uri,
fetch_all_servers,
filter_servers_by_display_name,
Expand All @@ -33,6 +34,10 @@ def get_discovered_server(cmd,
validate_get_discovered_server_params(
project_name, resource_group, source_machine_type)

# Extract machine name if a full resource ID was provided for --name
if name:
name = extract_machine_name_from_id(name)

# Use current subscription if not provided
if not subscription_id:
from azure.cli.core.commands.client_factory import \
Expand All @@ -50,8 +55,8 @@ def get_discovered_server(cmd,

# Prepare query parameters
query_params = [f"api-version={api_version}"]
if not appliance_name and display_name:
query_params.append(f"$filter=displayName eq '{display_name}'")
# Note: Azure Migrate API does not support OData $filter for machines endpoint
# We'll apply client-side filtering after fetching all results
Comment thread
saifaldin14 marked this conversation as resolved.

# Construct the full URI
request_uri = (
Expand All @@ -64,8 +69,8 @@ def get_discovered_server(cmd,
values = fetch_all_servers(cmd, request_uri, send_get_request)

# Apply client-side filtering for display_name when using site
# endpoints
if appliance_name and display_name:
# endpoints or when using the migrateprojects endpoint
if display_name:
values = filter_servers_by_display_name(values, display_name)

# Format and display the discovered servers information
Expand Down
92 changes: 81 additions & 11 deletions src/migrate/azext_migrate/helpers/_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,30 @@ def validate_get_discovered_server_params(project_name,
raise CLIError("source_machine_type is not 'VMware' or 'HyperV'.")


def extract_machine_name_from_id(name_or_id):
"""
Extract the machine name from a full resource ID or return the name as-is.

Handles formats like:
- Full ID: /subscriptions/.../Machines/5939691e-5505-4016-b4cd-4fa2d862a975
- Simple name: 5939691e-5505-4016-b4cd-4fa2d862a975
"""
Comment thread
saifaldin14 marked this conversation as resolved.
if not name_or_id:
return None

# If it looks like a full resource ID, extract the machine name
if name_or_id.startswith('/subscriptions/') or name_or_id.startswith('/Subscriptions/'):
parts = name_or_id.rstrip('/').split('/')
# The machine name should be the last part after "machines" or "Machines"
for i, part in enumerate(parts):
if part.lower() == 'machines' and i + 1 < len(parts):
return parts[i + 1]
# If we can't find machines, return the last segment
return parts[-1] if parts else name_or_id

return name_or_id


def build_base_uri(subscription_id, resource_group_name, project_name,
appliance_name, name, source_machine_type):
"""Build the base URI for the API request."""
Expand Down Expand Up @@ -66,23 +90,40 @@ def fetch_all_servers(cmd, request_uri, send_get_request):
"""Fetch all servers including paginated results."""
response = send_get_request(cmd, request_uri)
data = response.json()
values = data.get('value', [])

while data.get('nextLink'):
response = send_get_request(cmd, data.get('nextLink'))
data = response.json()
values += data.get('value', [])

return values

# Handle single item response (when fetching by name/ID)
# Single items have 'id' and 'properties' at root level, not 'value'
if 'value' in data:
values = data.get('value', [])
while data.get('nextLink'):
response = send_get_request(cmd, data.get('nextLink'))
data = response.json()
values += data.get('value', [])
return values
elif 'id' in data and 'properties' in data:
# Single machine response - wrap in list
return [data]
else:
return []


def filter_servers_by_display_name(servers, display_name):
"""Filter servers by display name."""
"""Filter servers by display name or machine name."""
filtered = []
for server in servers:
properties = server.get('properties', {})

# Check properties.displayName first
if properties.get('displayName', '') == display_name:
filtered.append(server)
continue

# Also check discoveryData[0].machineName
discovery_data = properties.get('discoveryData', [])
if discovery_data:
Comment thread
saifaldin14 marked this conversation as resolved.
machine_name = discovery_data[0].get('machineName', '')
if machine_name == display_name:
filtered.append(server)
return filtered


Expand All @@ -93,16 +134,16 @@ def extract_server_info(server, index):

# Default values
machine_name = "N/A"
machine_id = "N/A"
machine_id = server.get('id', 'N/A')
Comment thread
saifaldin14 marked this conversation as resolved.
ip_addresses_str = 'N/A'
os_name = "N/A"
boot_type = "N/A"
os_disk_id = "N/A"

if discovery_data:
# Format from Microsoft.Migrate/migrateprojects/machines
latest_discovery = discovery_data[0]
machine_name = latest_discovery.get('machineName', 'N/A')
machine_id = server.get('id', 'N/A')
ip_addresses = latest_discovery.get('ipAddresses', [])
ip_addresses_str = ', '.join(ip_addresses) if ip_addresses else 'N/A'
os_name = latest_discovery.get('osName', 'N/A')
Expand All @@ -114,6 +155,35 @@ def extract_server_info(server, index):
disk_details = json.loads(disk_details_json)
if disk_details:
os_disk_id = disk_details[0].get("InstanceId", "N/A")
else:
# Format from Microsoft.OffAzure/VMwareSites/machines or HyperVSites/machines
machine_name = properties.get('displayName', 'N/A')

# Try to get IP addresses from different locations
network_adapters = properties.get('networkAdapters', [])
if network_adapters:
all_ips = []
for adapter in network_adapters:
ips = adapter.get('ipAddressList', [])
all_ips.extend(ips)
ip_addresses_str = ', '.join(all_ips) if all_ips else 'N/A'

# Get OS info from guestOSDetails or operatingSystemDetails
guest_os = properties.get('guestOSDetails', {})
if guest_os:
os_name = guest_os.get('osName', 'N/A')
else:
os_details = properties.get('operatingSystemDetails', {})
os_name = os_details.get('osName', os_details.get('osType', 'N/A'))

# Get firmware/boot type
firmware = properties.get('firmware', 'N/A')
boot_type = firmware.lower() if firmware and firmware != 'N/A' else 'N/A'
Comment thread
saifaldin14 marked this conversation as resolved.

# Get disk info
disks = properties.get('disks', [])
if disks:
os_disk_id = disks[0].get('uuid', disks[0].get('diskId', 'N/A'))

return {
'index': index,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -211,11 +211,13 @@ def _format_protected_item(item):
# Add custom properties if available
if custom_properties:
formatted_item['instanceType'] = custom_properties.get('instanceType', 'N/A')
formatted_item['sourceMachineName'] = custom_properties.get('sourceMachineName', 'N/A')
formatted_item['targetVmName'] = custom_properties.get('targetVmName', 'N/A')
formatted_item['targetResourceGroupId'] = custom_properties.get('targetResourceGroupId', 'N/A')
formatted_item['customLocationRegion'] = custom_properties.get('customLocationRegion', 'N/A')

# Use sourceVmName from API response (the actual VM display name)
formatted_item['sourceMachineName'] = custom_properties.get('sourceVmName', 'N/A')

return formatted_item


Expand Down
2 changes: 1 addition & 1 deletion src/migrate/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

from setuptools import setup, find_packages

VERSION = "3.0.0b2"
VERSION = "3.0.0b3"

CLASSIFIERS = [
'Development Status :: 4 - Beta',
Expand Down
Loading