Skip to content
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

Add support for testing image in shared gallery #1421

Merged
merged 1 commit into from
Jul 19, 2021
Merged
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
18 changes: 16 additions & 2 deletions lisa/sut_orchestrator/azure/arm_template.json
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@
"linuxConfiguration": "[if(empty(parameters('admin_key_data')), json('null'), lisa.getLinuxConfiguration(concat('/home/', parameters('admin_username'), '/.ssh/authorized_keys'), parameters('admin_key_data')))]"
},
"storageProfile": {
"imageReference": "[if(not(empty(parameters('nodes')[copyIndex('vmCopy')]['vhd'])), lisa.getOsDiskVhd(parameters('nodes')[copyIndex('vmCopy')]['name']), lisa.getOsDiskMarketplace(parameters('nodes')[copyIndex('vmCopy')]))]",
"imageReference": "[if(not(empty(parameters('nodes')[copyIndex('vmCopy')]['vhd'])), lisa.getOsDiskVhd(parameters('nodes')[copyIndex('vmCopy')]['name']), if(not(empty(parameters('nodes')[copyIndex('vmCopy')]['shared_gallery'])), lisa.getOsDiskSharedGallery(parameters('nodes')[copyIndex('vmCopy')]['shared_gallery']), lisa.getOsDiskMarketplace(parameters('nodes')[copyIndex('vmCopy')])))]",
"osDisk": {
"name": "[concat(parameters('nodes')[copyIndex('vmCopy')]['name'], '-osDisk')]",
"managedDisk": {
Expand Down Expand Up @@ -327,6 +327,20 @@
"value": "[parameters('node')['marketplace']]"
}
},
"getOsDiskSharedGallery": {
"parameters": [
{
"name": "node",
"type": "object"
}
],
"output": {
"type": "object",
"value": {
"id": "[resourceId(parameters('node')['subscription_id'], 'None', 'Microsoft.Compute/galleries/images/versions', parameters('node')['image_gallery'], parameters('node')['image_definition'], parameters('node')['image_version'])]"
}
}
},
"getOsDiskVhd": {
"parameters": [
{
Expand Down Expand Up @@ -371,4 +385,4 @@
}
}
]
}
}
88 changes: 88 additions & 0 deletions lisa/sut_orchestrator/azure/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,22 +60,40 @@ class AzureVmMarketplaceSchema:
version: str = "Latest"


@dataclass_json()
squirrelsc marked this conversation as resolved.
Show resolved Hide resolved
@dataclass
class SharedImageGallerySchema:
subscription_id: str = ""
image_gallery: str = ""
image_definition: str = ""
image_version: str = ""


@dataclass_json()
@dataclass
class AzureNodeSchema:
name: str = ""
vm_size: str = ""
location: str = ""
# Required by shared gallery images which are present in
# subscription different from where LISA is run
subscription_id: str = ""
marketplace_raw: Optional[Union[Dict[Any, Any], str]] = field(
default=None, metadata=schema.metadata(data_key="marketplace")
)
shared_gallery_raw: Optional[Union[Dict[Any, Any], str]] = field(
default=None, metadata=schema.metadata(data_key="shared_gallery")
)
vhd: str = ""
nic_count: int = 1

# for marketplace image, which need to accept terms
purchase_plan: Optional[AzureVmPurchasePlanSchema] = None

_marketplace: InitVar[Optional[AzureVmMarketplaceSchema]] = None

_shared_gallery: InitVar[Optional[SharedImageGallerySchema]] = None

@property
def marketplace(self) -> Optional[AzureVmMarketplaceSchema]:
# this is a safe guard and prevent mypy error on typing
Expand Down Expand Up @@ -132,10 +150,80 @@ def marketplace(self, value: Optional[AzureVmMarketplaceSchema]) -> None:
else:
self.marketplace_raw = value.to_dict() # type: ignore

@property
def shared_gallery(self) -> Optional[SharedImageGallerySchema]:
# this is a safe guard and prevent mypy error on typing
if not hasattr(self, "_shared_gallery"):
self._shared_gallery: Optional[SharedImageGallerySchema] = None
shared_gallery: Optional[SharedImageGallerySchema] = self._shared_gallery
if shared_gallery:
return shared_gallery
if isinstance(self.shared_gallery_raw, dict):
# Users decide the cases of image names,
# the inconsistent cases cause the mismatched error in notifiers.
# The lower() normalizes the image names,
# it has no impact on deployment.
self.shared_gallery_raw = dict(
(k, v.lower()) for k, v in self.shared_gallery_raw.items()
)
shared_gallery = SharedImageGallerySchema.schema().load( # type: ignore
self.shared_gallery_raw
)
if not shared_gallery.subscription_id: # type: ignore
shared_gallery.subscription_id = self.subscription_id # type: ignore
# this step makes shared_gallery_raw is validated, and
# filter out any unwanted content.
self.shared_gallery_raw = shared_gallery.to_dict() # type: ignore
elif self.shared_gallery_raw:
assert isinstance(
self.shared_gallery_raw, str
), f"actual: {type(self.shared_gallery_raw)}"
# Users decide the cases of image names,
# the inconsistent cases cause the mismatched error in notifiers.
# The lower() normalizes the image names,
# it has no impact on deployment.
shared_gallery_strings = re.split(
r"[/]+", self.shared_gallery_raw.strip().lower()
)
if len(shared_gallery_strings) == 4:
shared_gallery = SharedImageGallerySchema(*shared_gallery_strings)
# shared_gallery_raw is used
self.shared_gallery_raw = shared_gallery.to_dict() # type: ignore
elif len(shared_gallery_strings) == 3:
shared_gallery = SharedImageGallerySchema(
self.subscription_id, *shared_gallery_strings
)
# shared_gallery_raw is used
self.shared_gallery_raw = shared_gallery.to_dict() # type: ignore
else:
raise LisaException(
f"Invalid value for the provided shared gallery "
f"parameter: '{self.shared_gallery_raw}'."
f"The shared gallery parameter should be in the format: "
f"'<subscription_id>/<image_gallery>/<image_definition>"
f"/<image_version>' or '<image_gallery>/<image_definition>"
f"/<image_version>'"
)
self._shared_gallery = shared_gallery
return shared_gallery

@shared_gallery.setter
def shared_gallery(self, value: Optional[SharedImageGallerySchema]) -> None:
self._shared_gallery = value
if value is None:
self.shared_gallery_raw = None
else:
self.shared_gallery_raw = value.to_dict() # type: ignore

def get_image_name(self) -> str:
result = ""
if self.vhd:
result = self.vhd
elif self.shared_gallery:
assert isinstance(
self.shared_gallery_raw, dict
), f"actual type: {type(self.shared_gallery_raw)}"
result = " ".join([x for x in self.shared_gallery_raw.values()])
elif self.marketplace:
assert isinstance(
self.marketplace_raw, dict
Expand Down
11 changes: 10 additions & 1 deletion lisa/sut_orchestrator/azure/platform_.py
Original file line number Diff line number Diff line change
Expand Up @@ -839,6 +839,9 @@ def _create_deployment_parameters(
azure_node_runbook = node_space.get_extended_runbook(
AzureNodeSchema, type_name=AZURE
)
# Subscription Id is used by Shared Gallery images located
# in subscription different from where LISA is run
azure_node_runbook.subscription_id = self.subscription_id
squirrelsc marked this conversation as resolved.
Show resolved Hide resolved

# init node
node = environment.nodes.from_requirement(
Expand All @@ -859,7 +862,13 @@ def _create_deployment_parameters(
if azure_node_runbook.vhd:
# vhd is higher priority
azure_node_runbook.marketplace = None
elif not azure_node_runbook.marketplace:
azure_node_runbook.shared_gallery = None
elif azure_node_runbook.shared_gallery:
azure_node_runbook.marketplace = None
elif azure_node_runbook.marketplace:
# marketplace value is already set in runbook
pass
else:
# set to default marketplace, if nothing specified
azure_node_runbook.marketplace = AzureVmMarketplaceSchema()

Expand Down