@@ -2878,13 +2878,42 @@ def show_vm_nic(cmd, resource_group_name, vm_name, nic):
28782878
28792879 NicShow = import_aaz_by_profile (cmd .cli_ctx .cloud .profile , "network.nic" ).Show
28802880
2881- vm = get_vm (cmd , resource_group_name , vm_name )
2882- found = next (
2883- (n for n in vm .network_profile .network_interfaces if nic .lower () == n .id .lower ()), None
2884- # pylint: disable=no-member
2885- )
2881+ vm = get_vm_to_update_by_aaz (cmd , resource_group_name , vm_name ) or {}
2882+ nics = (vm .get ('networkProfile' ) or {}).get ('networkInterfaces' ) or []
2883+
2884+ nic_in = (nic or "" ).strip ()
2885+ nic_in_lower = nic_in .lower ()
2886+
2887+ def _safe_id (n ):
2888+ _id = (n or {}).get ('id' )
2889+ return _id .strip () if isinstance (_id , str ) else None
2890+
2891+ found = None
2892+ if "/subscriptions/" in nic_in_lower and "/networkinterfaces/" in nic_in_lower :
2893+ found = next (
2894+ (n for n in nics if (_safe_id (n ) or "" ).lower () == nic_in_lower ),
2895+ None
2896+ )
2897+
2898+ if not found :
2899+ for n in nics :
2900+ _id = _safe_id (n )
2901+ if not _id :
2902+ continue
2903+ try :
2904+ if parse_resource_id (_id ).get ('name' , '' ).lower () == nic_in_lower :
2905+ found = n
2906+ break
2907+ except Exception :
2908+ continue
2909+
28862910 if found :
2887- nic_name = parse_resource_id (found .id )['name' ]
2911+ found_id = _safe_id (found )
2912+ if not found_id :
2913+ raise ResourceNotFoundError (
2914+ f"NIC '{ nic } ' is attached to VM '{ vm_name } ' but NIC id is missing in VM network profile."
2915+ )
2916+ nic_name = parse_resource_id (found_id )['name' ]
28882917 return NicShow (cli_ctx = cmd .cli_ctx )(command_args = {
28892918 'name' : nic_name ,
28902919 'resource_group' : resource_group_name
@@ -2893,88 +2922,125 @@ def show_vm_nic(cmd, resource_group_name, vm_name, nic):
28932922
28942923
28952924def list_vm_nics (cmd , resource_group_name , vm_name ):
2896- vm = get_vm (cmd , resource_group_name , vm_name )
2897- return vm .network_profile .network_interfaces # pylint: disable=no-member
2925+ vm = get_vm_to_update_by_aaz (cmd , resource_group_name , vm_name ) or {}
2926+ nics = (vm .get ('networkProfile' ) or {}).get ('networkInterfaces' ) or []
2927+
2928+ normalized = []
2929+ for nic in nics :
2930+ nic = nic or {}
2931+ normalized .append ({
2932+ "id" : nic .get ("id" ),
2933+ "resourceGroup" : nic .get ("resourceGroup" ) or resource_group_name ,
2934+ "primary" : nic .get ("primary" ),
2935+ "deleteOption" : nic .get ("deleteOption" ),
2936+ })
2937+ return normalized
28982938
28992939
29002940def add_vm_nic (cmd , resource_group_name , vm_name , nics , primary_nic = None ):
2901- vm = get_vm_to_update (cmd , resource_group_name , vm_name )
2941+ from .operations .vm import convert_show_result_to_snake_case as to_snake_case
2942+
2943+ vm = to_snake_case (get_vm_to_update_by_aaz (cmd , resource_group_name , vm_name ) or {}) or {}
29022944 new_nics = _build_nic_list (cmd , nics )
29032945 existing_nics = _get_existing_nics (vm )
2904- return _update_vm_nics (cmd , vm , existing_nics + new_nics , primary_nic )
2946+
2947+ return _update_vm_nics (
2948+ cmd , vm , existing_nics + new_nics , primary_nic ,
2949+ resource_group_name = resource_group_name ,
2950+ vm_name = vm_name )
29052951
29062952
29072953def remove_vm_nic (cmd , resource_group_name , vm_name , nics , primary_nic = None ):
2954+ from .operations .vm import convert_show_result_to_snake_case as to_snake_case
29082955
2909- def to_delete (nic_id ):
2910- return [n for n in nics_to_delete if n .id .lower () == nic_id .lower ()]
2956+ vm = to_snake_case (get_vm_to_update_by_aaz (cmd , resource_group_name , vm_name ) or {}) or {}
29112957
2912- vm = get_vm_to_update (cmd , resource_group_name , vm_name )
29132958 nics_to_delete = _build_nic_list (cmd , nics )
29142959 existing_nics = _get_existing_nics (vm )
2915- survived = [x for x in existing_nics if not to_delete (x .id )]
2916- return _update_vm_nics (cmd , vm , survived , primary_nic )
2960+
2961+ delete_ids = {n ["id" ].lower () for n in nics_to_delete if n .get ("id" )}
2962+
2963+ survived = [x for x in existing_nics if (x .get ("id" ) or "" ).lower () not in delete_ids ]
2964+ if not survived :
2965+ # aligns with platform behavior
2966+ # (https://learn.microsoft.com/en-us/azure/virtual-network/virtual-network-network-interface-vm)
2967+ raise ValidationError ("A virtual machine must have at least one network interface. "
2968+ "You cannot detach the only NIC from a VM." )
2969+
2970+ return _update_vm_nics (
2971+ cmd , vm , survived , primary_nic ,
2972+ resource_group_name = resource_group_name ,
2973+ vm_name = vm_name )
29172974
29182975
29192976def set_vm_nic (cmd , resource_group_name , vm_name , nics , primary_nic = None ):
2920- vm = get_vm_to_update (cmd , resource_group_name , vm_name )
2921- nics = _build_nic_list (cmd , nics )
2922- return _update_vm_nics (cmd , vm , nics , primary_nic )
2977+ from .operations .vm import convert_show_result_to_snake_case as to_snake_case
2978+
2979+ vm = to_snake_case (get_vm_to_update_by_aaz (cmd , resource_group_name , vm_name ) or {}) or {}
2980+ nic_list = _build_nic_list (cmd , nics )
2981+
2982+ # VM must have at least one NIC
2983+ if not nic_list :
2984+ raise ValidationError (
2985+ "A virtual machine must have at least one network interface. "
2986+ "The '--nics' parameter cannot be empty."
2987+ )
2988+
2989+ return _update_vm_nics (
2990+ cmd , vm , nic_list , primary_nic ,
2991+ resource_group_name = resource_group_name ,
2992+ vm_name = vm_name ,
2993+ )
29232994
29242995
29252996def _build_nic_list (cmd , nic_ids ):
29262997 NicShow = import_aaz_by_profile (cmd .cli_ctx .cloud .profile , "network.nic" ).Show
2927-
2928- NetworkInterfaceReference = cmd .get_models ('NetworkInterfaceReference' )
29292998 nic_list = []
29302999 if nic_ids :
2931- # pylint: disable=no-member
29323000 for nic_id in nic_ids :
29333001 rg , name = _parse_rg_name (nic_id )
2934- nic = NicShow (cli_ctx = cmd .cli_ctx )(command_args = {
2935- 'name' : name ,
2936- 'resource_group' : rg
2937- })
2938- nic_list .append (NetworkInterfaceReference (id = nic ['id' ], primary = False ))
3002+ nic = NicShow (cli_ctx = cmd .cli_ctx )(command_args = {'name' : name , 'resource_group' : rg })
3003+ nic_list .append ({"id" : nic ["id" ], "primary" : False })
29393004 return nic_list
29403005
29413006
29423007def _get_existing_nics (vm ):
2943- network_profile = getattr (vm , 'network_profile' , None )
2944- nics = []
2945- if network_profile is not None :
2946- nics = network_profile .network_interfaces or []
2947- return nics
3008+ return (vm .get ("network_profile" ) or {}).get ("network_interfaces" ) or []
29483009
29493010
2950- def _update_vm_nics (cmd , vm , nics , primary_nic ):
2951- NetworkProfile = cmd .get_models ('NetworkProfile' )
2952-
3011+ def _update_vm_nics (cmd , vm , nics , primary_nic , resource_group_name , vm_name ):
29533012 if primary_nic :
29543013 try :
29553014 _ , primary_nic_name = _parse_rg_name (primary_nic )
29563015 except IndexError :
29573016 primary_nic_name = primary_nic
29583017
2959- matched = [n for n in nics if _parse_rg_name (n . id )[1 ].lower () == primary_nic_name .lower ()]
3018+ matched = [n for n in nics if _parse_rg_name (n [ "id" ] )[1 ].lower () == primary_nic_name .lower ()]
29603019 if not matched :
2961- raise CLIError ('Primary Nic {} is not found' . format ( primary_nic ) )
3020+ raise CLIError (f 'Primary Nic { primary_nic } is not found' )
29623021 if len (matched ) > 1 :
2963- raise CLIError ('Duplicate Nic entries with name {}' . format ( primary_nic ) )
3022+ raise CLIError (f 'Duplicate Nic entries with name { primary_nic } ' )
29643023 for n in nics :
2965- n . primary = False
2966- matched [0 ]. primary = True
3024+ n [ " primary" ] = False
3025+ matched [0 ][ " primary" ] = True
29673026 elif nics :
2968- if not [ n for n in nics if n . primary ] :
2969- nics [0 ]. primary = True
3027+ if not any ( n . get ( "primary" ) for n in nics ) :
3028+ nics [0 ][ " primary" ] = True
29703029
2971- network_profile = getattr (vm , 'network_profile' , None )
2972- if network_profile is None :
2973- vm .network_profile = NetworkProfile (network_interfaces = nics )
2974- else :
2975- network_profile .network_interfaces = nics
3030+ vm .setdefault ("network_profile" , {})
3031+ vm ["network_profile" ]["network_interfaces" ] = nics
3032+
3033+ vm .pop ("resources" , None )
3034+
3035+ vm ["resource_group" ] = resource_group_name
3036+ vm ["vm_name" ] = vm_name
3037+
3038+ from .operations .vm import VMCreate
3039+
3040+ poller = VMCreate (cli_ctx = cmd .cli_ctx )(command_args = vm )
3041+ result = LongRunningOperation (cmd .cli_ctx )(poller )
29763042
2977- return set_vm ( cmd , vm ). network_profile . network_interfaces
3043+ return ( result . get ( "networkProfile" ) or {}). get ( "networkInterfaces" ) or []
29783044# endregion
29793045
29803046
0 commit comments