11# SPDX-License-Identifier: GPL-3.0-or-later
22import logging
33from operator import attrgetter
4- from typing import Dict , List , Optional , Tuple
4+ from typing import Any , Dict , List , Optional , Tuple
55
66from deepdiff import DeepDiff
77
@@ -69,7 +69,22 @@ def __init__(
6969 super (AzurePublishingMetadata , self ).__init__ (** kwargs )
7070 self .__validate ()
7171 # Adjust the x86_64 architecture string for Azure
72- self .architecture = "x64" if self .architecture == "x86_64" else self .architecture
72+ arch = self .__convert_arch (self .architecture )
73+ self .architecture = arch
74+
75+ def __setattr__ (self , name : str , value : Any ) -> None :
76+ if name == "architecture" :
77+ arch = self .__convert_arch (value )
78+ value = arch
79+ return super ().__setattr__ (name , value )
80+
81+ @staticmethod
82+ def __convert_arch (arch : str ) -> str :
83+ converter = {
84+ "x86_64" : "x64" ,
85+ "aarch64" : "arm64" ,
86+ }
87+ return converter .get (arch , "" ) or arch
7388
7489 def __validate (self ):
7590 mandatory = [
@@ -91,9 +106,10 @@ def __validate(self):
91106def get_image_type_mapping (architecture : str , generation : str ) -> str :
92107 """Return the image type required by VMImageDefinition."""
93108 gen_map = {
94- "V1" : f"{ architecture } Gen1" ,
95109 "V2" : f"{ architecture } Gen2" ,
96110 }
111+ if architecture == "x64" :
112+ gen_map .update ({"V1" : f"{ architecture } Gen1" })
97113 return gen_map .get (generation , "" )
98114
99115
@@ -185,6 +201,17 @@ def is_azure_job_not_complete(job_details: ConfigureStatus) -> bool:
185201 return False
186202
187203
204+ def is_legacy_gen_supported (metadata : AzurePublishingMetadata ) -> bool :
205+ """Return True when the legagy V1 SKU is supported, False otherwise.
206+
207+ Args:
208+ metadata: The incoming publishing metadata.
209+ Returns:
210+ bool: True when V1 is supported, False otherwise.
211+ """
212+ return metadata .architecture == "x64" and metadata .support_legacy
213+
214+
188215def prepare_vm_images (
189216 metadata : AzurePublishingMetadata ,
190217 gen1 : Optional [VMImageDefinition ],
@@ -226,7 +253,7 @@ def prepare_vm_images(
226253 if metadata .generation == "V2" :
227254 # In this case we need to set a V2 SAS URI
228255 gen2_new = VMImageDefinition .from_json (json_gen2 )
229- if metadata . support_legacy : # and in this case a V1 as well
256+ if is_legacy_gen_supported ( metadata ) : # and in this case a V1 as well
230257 gen1_new = VMImageDefinition .from_json (json_gen1 )
231258 return [gen2_new , gen1_new ]
232259 return [gen2_new ]
@@ -235,13 +262,25 @@ def prepare_vm_images(
235262 return [VMImageDefinition .from_json (json_gen1 )]
236263
237264
265+ def _len_vm_images (disk_versions : List [DiskVersion ]) -> int :
266+ count = 0
267+ for disk_version in disk_versions :
268+ count = count + len (disk_version .vm_images )
269+ return count
270+
271+
238272def _build_skus (
239273 disk_versions : List [DiskVersion ],
240274 default_gen : str ,
241275 alt_gen : str ,
242276 plan_name : str ,
243277 security_type : Optional [List [str ]] = None ,
244278) -> List [VMISku ]:
279+ def get_skuid (arch ):
280+ if arch == "x64" :
281+ return plan_name
282+ return f"{ plan_name } -{ arch .lower ()} "
283+
245284 sku_mapping : Dict [str , str ] = {}
246285 # Update the SKUs for each image in DiskVersions if needed
247286 for disk_version in disk_versions :
@@ -254,10 +293,11 @@ def _build_skus(
254293 new_img_alt_type = get_image_type_mapping (arch , alt_gen )
255294
256295 # we just want to add SKU whenever it's not set
296+ skuid = get_skuid (arch )
257297 if vmid .image_type == new_img_type :
258- sku_mapping .setdefault (new_img_type , plan_name )
298+ sku_mapping .setdefault (new_img_type , skuid )
259299 elif vmid .image_type == new_img_alt_type :
260- sku_mapping .setdefault (new_img_alt_type , f"{ plan_name } -gen{ alt_gen [1 :]} " )
300+ sku_mapping .setdefault (new_img_alt_type , f"{ skuid } -gen{ alt_gen [1 :]} " )
261301
262302 # Return the expected SKUs list
263303 res = [
@@ -267,6 +307,15 @@ def _build_skus(
267307 return sorted (res , key = attrgetter ("id" ))
268308
269309
310+ def _get_security_type (old_skus : List [VMISku ]) -> Optional [List [str ]]:
311+ # The security type may exist only for x64 Gen2, so it iterates over all gens to find it
312+ # Get the security type for all gens
313+ for osku in old_skus :
314+ if osku .security_type is not None :
315+ return osku .security_type
316+ return None
317+
318+
270319def update_skus (
271320 disk_versions : List [DiskVersion ],
272321 generation : str ,
@@ -295,21 +344,18 @@ def update_skus(
295344 disk_versions , default_gen = generation , alt_gen = alt_gen , plan_name = plan_name
296345 )
297346
298- # If we have SKUs for both genenerations we don't need to update them as they're already
347+ # If we have SKUs for each image we don't need to update them as they're already
299348 # properly set.
300- if len (old_skus ) == 2 :
349+ if len (old_skus ) == _len_vm_images ( disk_versions ) :
301350 return old_skus
302351
303352 # Update SKUs to create the alternate gen.
304- # The security type may exist only for Gen2, so it iterates over all gens to find it
305- security_type = None
306- # The alternate plan name ends with the suffix "-genX" and we can't change that once
353+ security_type = _get_security_type ( old_skus )
354+
355+ # The alternate plan for x64 name ends with the suffix "-genX" and we can't change that once
307356 # the offer is live, otherwise it will raise "BadRequest" with the message:
308357 # "The property 'PlanId' is locked by a previous submission".
309358 osku = old_skus [0 ]
310- # Get the security type for all gens
311- if osku .security_type is not None :
312- security_type = osku .security_type
313359
314360 # Default Gen2 cases
315361 if osku .image_type .endswith ("Gen1" ) and osku .id .endswith ("gen1" ):
@@ -354,7 +400,7 @@ def create_disk_version_from_scratch(
354400 "source" : source .to_json (),
355401 }
356402 ]
357- if metadata . support_legacy :
403+ if is_legacy_gen_supported ( metadata ) :
358404 vm_images .append (
359405 {
360406 "imageType" : get_image_type_mapping (metadata .architecture , "V1" ),
@@ -463,7 +509,7 @@ def create_vm_image_definitions(
463509 source = source .to_json (),
464510 )
465511 )
466- if metadata . support_legacy : # Only True when metadata.generation == V2
512+ if is_legacy_gen_supported ( metadata ):
467513 vm_images .append (
468514 VMImageDefinition (
469515 image_type = get_image_type_mapping (metadata .architecture , "V1" ),
0 commit comments