Skip to content
9 changes: 9 additions & 0 deletions src/azure-cli/azure/cli/command_modules/vm/_help.py
Original file line number Diff line number Diff line change
Expand Up @@ -1443,6 +1443,15 @@
crafted: true
"""

helps['vm host group get-instance-view'] = """
type: command
short-summary: Get instance view of a dedicated host group.
examples:
- name: Get instance view of a dedicated host group
text: |
az vm host group get-instance-view --name MyDedicatedHostGroup --resource-group MyResourceGroup
"""

helps['vm host group update'] = """
type: command
short-summary: Update a dedicated host group.
Expand Down
7 changes: 7 additions & 0 deletions src/azure-cli/azure/cli/command_modules/vm/_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -476,6 +476,11 @@ def load_arguments(self, _):

with self.argument_context('vm host group') as c:
c.argument('host_group_name', name_arg_type, id_part='name', help="Name of the Dedicated Host Group")
c.argument('automatic_placement', arg_type=get_three_state_flag(), min_api='2020-06-01',
help='Specify whether virtual machines or virtual machine scale sets can be placed automatically '
'on the dedicated host group. Automatic placement means resources are allocated on dedicated '
'hosts, that are chosen by Azure, under the dedicated host group. The value is defaulted to '
'true when not provided.')

with self.argument_context('vm host group create') as c:
c.argument('platform_fault_domain_count', options_list=["--platform-fault-domain-count", "-c"], type=int,
Expand All @@ -502,6 +507,8 @@ def load_arguments(self, _):
c.argument('caching', help='Disk caching policy', arg_type=get_enum_type(CachingTypes))
for dest in scaleset_name_aliases:
c.argument(dest, vmss_name_type)
c.argument('host_group', min_api='2020-06-01',
help='Name or ID of dedicated host group that the virtual machine scale set resides in')

for scope in ['vmss deallocate', 'vmss delete-instances', 'vmss restart', 'vmss start', 'vmss stop', 'vmss show', 'vmss update-instances', 'vmss simulate-eviction']:
with self.argument_context(scope) as c:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ def build_vm_resource( # pylint: disable=too-many-locals, too-many-statements
disk_info=None, boot_diagnostics_storage_uri=None, ultra_ssd_enabled=None, proximity_placement_group=None,
computer_name=None, dedicated_host=None, priority=None, max_price=None, eviction_policy=None,
enable_agent=None, vmss=None, os_disk_encryption_set=None, data_disk_encryption_sets=None, specialized=None,
encryption_at_host=None):
encryption_at_host=None, dedicated_host_group=None):

os_caching = disk_info['os'].get('caching')

Expand Down Expand Up @@ -436,6 +436,9 @@ def _build_storage_profile():
if dedicated_host:
vm_properties['host'] = {'id': dedicated_host}

if dedicated_host_group:
vm_properties['hostGroup'] = {'id': dedicated_host_group}

if priority is not None:
vm_properties['priority'] = priority

Expand Down Expand Up @@ -679,7 +682,7 @@ def build_vmss_resource(cmd, name, naming_prefix, location, tags, overprovision,
terminate_notification_time=None, max_price=None, scale_in_policy=None,
os_disk_encryption_set=None, data_disk_encryption_sets=None,
data_disk_iops=None, data_disk_mbps=None, automatic_repairs_grace_period=None,
specialized=None, os_disk_size_gb=None, encryption_at_host=None):
specialized=None, os_disk_size_gb=None, encryption_at_host=None, host_group=None):

# Build IP configuration
ip_configuration = {
Expand Down Expand Up @@ -905,6 +908,9 @@ def build_vmss_resource(cmd, name, naming_prefix, location, tags, overprovision,
if encryption_at_host:
vmss_properties['virtualMachineProfile']['securityProfile'] = {'encryptionAtHost': encryption_at_host}

if host_group:
vmss_properties['hostGroup'] = {'id': host_group}

vmss = {
'type': 'Microsoft.Compute/virtualMachineScaleSets',
'name': name,
Expand Down
70 changes: 38 additions & 32 deletions src/azure-cli/azure/cli/command_modules/vm/_validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -599,43 +599,37 @@ def _validate_vm_create_vmss(cmd, namespace):


def _validate_vm_create_dedicated_host(cmd, namespace):
"""
"host": {
"$ref": "#/definitions/SubResource",
"description": "Specifies information about the dedicated host that the virtual machine resides in.
<br><br>Minimum api-version: 2018-10-01."
},
"hostGroup": {
"$ref": "#/definitions/SubResource",
"description": "Specifies information about the dedicated host group that the virtual machine resides in.
<br><br>Minimum api-version: 2020-06-01. <br><br>NOTE: User cannot specify both host and hostGroup properties."
}

:param cmd:
:param namespace:
:return:
"""
from msrestazure.tools import resource_id, is_valid_resource_id
from azure.cli.core.commands.client_factory import get_subscription_id

# handle incorrect usage
if namespace.dedicated_host_group and namespace.dedicated_host is None:
raise CLIError("incorrect usage: --host ID | --host-group NAME --host NAME")

# if this is a valid dedicated host resource id return
if is_valid_resource_id(namespace.dedicated_host):
if namespace.dedicated_host_group is not None:
logger.warning("Ignoring `--host-group` as `--host` is a valid resource id.")
return

# otherwise this should just be a dedicated host name. If host group provided, build resource id
if namespace.dedicated_host:
if namespace.dedicated_host_group is None:
raise CLIError("incorrect usage: --host ID | --host-group NAME --host NAME")

host_name = namespace.dedicated_host
rg = namespace.resource_group_name
host_group_name = namespace.dedicated_host_group

if not check_existence(cmd.cli_ctx, host_name, rg, 'Microsoft.Compute', 'hosts',
parent_name=host_group_name, parent_type='hostGroups'):
raise CLIError("The dedicated host '{}' in host group '{}' and resource group '{}' does not exist."
.format(host_name, host_group_name, rg))
if namespace.dedicated_host and namespace.dedicated_host_group:
raise CLIError('usage error: User cannot specify both --host and --host-group properties.')

namespace.dedicated_host = resource_id(
subscription=get_subscription_id(cmd.cli_ctx),
resource_group=rg,
namespace='Microsoft.Compute',
type='hostGroups',
name=host_group_name,
child_type_1="hosts",
child_name_1=host_name)
if namespace.dedicated_host and not is_valid_resource_id(namespace.dedicated_host):
raise CLIError('usage error: --host is not a valid resource ID.')

logger.info("Built dedicated host ID '%s' from host name and host group.", namespace.dedicated_host)
if namespace.dedicated_host_group:
if not is_valid_resource_id(namespace.dedicated_host_group):
namespace.dedicated_host_group = resource_id(
subscription=get_subscription_id(cmd.cli_ctx), resource_group=namespace.resource_group_name,
namespace='Microsoft.Compute', type='hostGroups', name=namespace.dedicated_host_group
)


def _validate_vm_vmss_create_vnet(cmd, namespace, for_scale_set=False):
Expand Down Expand Up @@ -1411,6 +1405,7 @@ def process_vmss_create_namespace(cmd, namespace):
_validate_proximity_placement_group(cmd, namespace)
_validate_vmss_terminate_notification(cmd, namespace)
_validate_vmss_create_automatic_repairs(cmd, namespace)
_validate_vmss_create_host_group(cmd, namespace)

if namespace.secrets:
_validate_secrets(namespace.secrets, namespace.os_type)
Expand Down Expand Up @@ -1711,3 +1706,14 @@ def _validate_vmss_automatic_repairs(cmd, namespace): # pylint: disable=unused-
"""
if namespace.automatic_repairs_grace_period is not None:
namespace.automatic_repairs_grace_period = 'PT' + namespace.automatic_repairs_grace_period + 'M'


def _validate_vmss_create_host_group(cmd, namespace):
from msrestazure.tools import resource_id, is_valid_resource_id
from azure.cli.core.commands.client_factory import get_subscription_id
if namespace.host_group:
if not is_valid_resource_id(namespace.host_group):
namespace.host_group = resource_id(
subscription=get_subscription_id(cmd.cli_ctx), resource_group=namespace.resource_group_name,
namespace='Microsoft.Compute', type='hostGroups', name=namespace.host_group
)
1 change: 1 addition & 0 deletions src/azure-cli/azure/cli/command_modules/vm/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,7 @@ def load_command_table(self, _):
with self.command_group('vm host group', compute_dedicated_host_groups_sdk, client_factory=cf_dedicated_host_groups,
min_api='2019-03-01') as g:
g.show_command('show', 'get')
g.custom_command('get-instance-view', 'get_dedicated_host_group_instance_view', min_api='2020-06-01')
g.custom_command('create', 'create_dedicated_host_group')
g.custom_command('list', 'list_dedicated_host_groups')
g.generic_update_command('update')
Expand Down
16 changes: 11 additions & 5 deletions src/azure-cli/azure/cli/command_modules/vm/custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -822,7 +822,7 @@ def create_vm(cmd, vm_name, resource_group_name, image=None, size='Standard_DS1_
dedicated_host=dedicated_host, priority=priority, max_price=max_price, eviction_policy=eviction_policy,
enable_agent=enable_agent, vmss=vmss, os_disk_encryption_set=os_disk_encryption_set,
data_disk_encryption_sets=data_disk_encryption_sets, specialized=specialized,
encryption_at_host=encryption_at_host)
encryption_at_host=encryption_at_host, dedicated_host_group=dedicated_host_group)

vm_resource['dependsOn'] = vm_dependencies

Expand Down Expand Up @@ -2240,7 +2240,8 @@ def create_vmss(cmd, vmss_name, resource_group_name, image=None,
proximity_placement_group=None, aux_subscriptions=None, terminate_notification_time=None,
max_price=None, computer_name_prefix=None, orchestration_mode='ScaleSetVM', scale_in_policy=None,
os_disk_encryption_set=None, data_disk_encryption_sets=None, data_disk_iops=None, data_disk_mbps=None,
automatic_repairs_grace_period=None, specialized=None, os_disk_size_gb=None, encryption_at_host=None):
automatic_repairs_grace_period=None, specialized=None, os_disk_size_gb=None, encryption_at_host=None,
host_group=None):
from azure.cli.core.commands.client_factory import get_subscription_id
from azure.cli.core.util import random_string, hash_string
from azure.cli.core.commands.arm import ArmTemplateBuilder
Expand Down Expand Up @@ -2474,7 +2475,8 @@ def _get_public_ip_address_allocation(value, sku):
scale_in_policy=scale_in_policy, os_disk_encryption_set=os_disk_encryption_set,
data_disk_encryption_sets=data_disk_encryption_sets, data_disk_iops=data_disk_iops,
data_disk_mbps=data_disk_mbps, automatic_repairs_grace_period=automatic_repairs_grace_period,
specialized=specialized, os_disk_size_gb=os_disk_size_gb, encryption_at_host=encryption_at_host)
specialized=specialized, os_disk_size_gb=os_disk_size_gb, encryption_at_host=encryption_at_host,
host_group=host_group)

vmss_resource['dependsOn'] = vmss_dependencies

Expand Down Expand Up @@ -3227,12 +3229,12 @@ def list_proximity_placement_groups(client, resource_group_name=None):

# region dedicated host
def create_dedicated_host_group(cmd, client, host_group_name, resource_group_name, platform_fault_domain_count=None,
location=None, zones=None, tags=None):
automatic_placement=None, location=None, zones=None, tags=None):
DedicatedHostGroup = cmd.get_models('DedicatedHostGroup')
location = location or _get_resource_group_location(cmd.cli_ctx, resource_group_name)

host_group_params = DedicatedHostGroup(location=location, platform_fault_domain_count=platform_fault_domain_count,
zones=zones, tags=tags)
support_automatic_placement=automatic_placement, zones=zones, tags=tags)

return client.create_or_update(resource_group_name, host_group_name, parameters=host_group_params)

Expand All @@ -3243,6 +3245,10 @@ def list_dedicated_host_groups(cmd, client, resource_group_name=None):
return client.list_by_subscription()


def get_dedicated_host_group_instance_view(client, host_group_name, resource_group_name):
return client.get(resource_group_name, host_group_name, expand="instanceView")


def create_dedicated_host(cmd, client, host_group_name, host_name, resource_group_name, sku, platform_fault_domain=None,
auto_replace_on_failure=None, license_type=None, location=None, tags=None):
DedicatedHostType = cmd.get_models('DedicatedHost')
Expand Down
Loading