skypilot-nightly 1.0.0.dev20241023__py3-none-any.whl → 1.0.0.dev20241024__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
sky/__init__.py CHANGED
@@ -5,7 +5,7 @@ from typing import Optional
5
5
  import urllib.request
6
6
 
7
7
  # Replaced with the current commit when building the wheels.
8
- _SKYPILOT_COMMIT_SHA = 'f2991b144d4b15eac55dd7f759f361b6146033b3'
8
+ _SKYPILOT_COMMIT_SHA = 'cbf5c0022ad920edb4f41cfad65a2cf4909d5930'
9
9
 
10
10
 
11
11
  def _get_git_commit():
@@ -35,7 +35,7 @@ def _get_git_commit():
35
35
 
36
36
 
37
37
  __commit__ = _get_git_commit()
38
- __version__ = '1.0.0.dev20241023'
38
+ __version__ = '1.0.0.dev20241024'
39
39
  __root_dir__ = os.path.dirname(os.path.abspath(__file__))
40
40
 
41
41
 
@@ -128,6 +128,7 @@ GCP = clouds.GCP
128
128
  Lambda = clouds.Lambda
129
129
  SCP = clouds.SCP
130
130
  Kubernetes = clouds.Kubernetes
131
+ K8s = Kubernetes
131
132
  OCI = clouds.OCI
132
133
  Paperspace = clouds.Paperspace
133
134
  RunPod = clouds.RunPod
@@ -143,6 +144,7 @@ __all__ = [
143
144
  'GCP',
144
145
  'IBM',
145
146
  'Kubernetes',
147
+ 'K8s',
146
148
  'Lambda',
147
149
  'OCI',
148
150
  'Paperspace',
sky/adaptors/azure.py CHANGED
@@ -69,6 +69,17 @@ def exceptions():
69
69
  return azure_exceptions
70
70
 
71
71
 
72
+ @functools.lru_cache()
73
+ @common.load_lazy_modules(modules=_LAZY_MODULES)
74
+ def azure_mgmt_models(name: str):
75
+ if name == 'compute':
76
+ from azure.mgmt.compute import models
77
+ return models
78
+ elif name == 'network':
79
+ from azure.mgmt.network import models
80
+ return models
81
+
82
+
72
83
  # We should keep the order of the decorators having 'lru_cache' followed
73
84
  # by 'load_lazy_modules' as we need to make sure a caller can call
74
85
  # 'get_client.cache_clear', which is a function provided by 'lru_cache'
sky/cli.py CHANGED
@@ -339,7 +339,6 @@ def _get_shell_complete_args(complete_fn):
339
339
 
340
340
 
341
341
  _RELOAD_ZSH_CMD = 'source ~/.zshrc'
342
- _RELOAD_FISH_CMD = 'source ~/.config/fish/config.fish'
343
342
  _RELOAD_BASH_CMD = 'source ~/.bashrc'
344
343
 
345
344
 
@@ -378,7 +377,9 @@ def _install_shell_completion(ctx: click.Context, param: click.Parameter,
378
377
  cmd = '_SKY_COMPLETE=fish_source sky > \
379
378
  ~/.config/fish/completions/sky.fish'
380
379
 
381
- reload_cmd = _RELOAD_FISH_CMD
380
+ # Fish does not need to be reloaded and will automatically pick up
381
+ # completions.
382
+ reload_cmd = None
382
383
 
383
384
  elif value == 'zsh':
384
385
  install_cmd = f'_SKY_COMPLETE=zsh_source sky > \
@@ -398,9 +399,10 @@ def _install_shell_completion(ctx: click.Context, param: click.Parameter,
398
399
  check=True,
399
400
  executable=shutil.which('bash'))
400
401
  click.secho(f'Shell completion installed for {value}', fg='green')
401
- click.echo(
402
- 'Completion will take effect once you restart the terminal: ' +
403
- click.style(f'{reload_cmd}', bold=True))
402
+ if reload_cmd is not None:
403
+ click.echo(
404
+ 'Completion will take effect once you restart the terminal: ' +
405
+ click.style(f'{reload_cmd}', bold=True))
404
406
  except subprocess.CalledProcessError as e:
405
407
  click.secho(f'> Installation failed with code {e.returncode}', fg='red')
406
408
  ctx.exit()
@@ -431,7 +433,9 @@ def _uninstall_shell_completion(ctx: click.Context, param: click.Parameter,
431
433
 
432
434
  elif value == 'fish':
433
435
  cmd = 'rm -f ~/.config/fish/completions/sky.fish'
434
- reload_cmd = _RELOAD_FISH_CMD
436
+ # Fish does not need to be reloaded and will automatically pick up
437
+ # completions.
438
+ reload_cmd = None
435
439
 
436
440
  elif value == 'zsh':
437
441
  cmd = 'sed -i"" -e "/# For SkyPilot shell completion/d" ~/.zshrc && \
@@ -447,8 +451,10 @@ def _uninstall_shell_completion(ctx: click.Context, param: click.Parameter,
447
451
  try:
448
452
  subprocess.run(cmd, shell=True, check=True)
449
453
  click.secho(f'Shell completion uninstalled for {value}', fg='green')
450
- click.echo('Changes will take effect once you restart the terminal: ' +
451
- click.style(f'{reload_cmd}', bold=True))
454
+ if reload_cmd is not None:
455
+ click.echo(
456
+ 'Changes will take effect once you restart the terminal: ' +
457
+ click.style(f'{reload_cmd}', bold=True))
452
458
  except subprocess.CalledProcessError as e:
453
459
  click.secho(f'> Uninstallation failed with code {e.returncode}',
454
460
  fg='red')
@@ -3056,7 +3062,8 @@ def show_gpus(
3056
3062
 
3057
3063
  # This will validate 'cloud' and raise if not found.
3058
3064
  cloud_obj = sky_clouds.CLOUD_REGISTRY.from_str(cloud)
3059
- service_catalog.validate_region_zone(region, None, clouds=cloud)
3065
+ cloud_name = cloud_obj.canonical_name() if cloud_obj is not None else None
3066
+ service_catalog.validate_region_zone(region, None, clouds=cloud_name)
3060
3067
  show_all = all
3061
3068
  if show_all and accelerator_str is not None:
3062
3069
  raise click.UsageError('--all is only allowed without a GPU name.')
@@ -3142,8 +3149,8 @@ def show_gpus(
3142
3149
  # Optimization - do not poll for Kubernetes API for fetching
3143
3150
  # common GPUs because that will be fetched later for the table after
3144
3151
  # common GPUs.
3145
- clouds_to_list = cloud
3146
- if cloud is None:
3152
+ clouds_to_list = cloud_name
3153
+ if cloud_name is None:
3147
3154
  clouds_to_list = [
3148
3155
  c for c in service_catalog.ALL_CLOUDS if c != 'kubernetes'
3149
3156
  ]
@@ -3153,7 +3160,8 @@ def show_gpus(
3153
3160
  # Collect k8s related messages in k8s_messages and print them at end
3154
3161
  print_section_titles = False
3155
3162
  # If cloud is kubernetes, we want to show real-time capacity
3156
- if kubernetes_is_enabled and (cloud is None or cloud_is_kubernetes):
3163
+ if kubernetes_is_enabled and (cloud_name is None or
3164
+ cloud_is_kubernetes):
3157
3165
  if region:
3158
3166
  context = region
3159
3167
  else:
@@ -3263,8 +3271,8 @@ def show_gpus(
3263
3271
  name, quantity = accelerator_str, None
3264
3272
 
3265
3273
  print_section_titles = False
3266
- if (kubernetes_is_enabled and (cloud is None or cloud_is_kubernetes) and
3267
- not show_all):
3274
+ if (kubernetes_is_enabled and
3275
+ (cloud_name is None or cloud_is_kubernetes) and not show_all):
3268
3276
  # Print section title if not showing all and instead a specific
3269
3277
  # accelerator is requested
3270
3278
  print_section_titles = True
@@ -3336,7 +3344,7 @@ def show_gpus(
3336
3344
  if len(result) == 0:
3337
3345
  quantity_str = (f' with requested quantity {quantity}'
3338
3346
  if quantity else '')
3339
- cloud_str = f' on {cloud_obj}.' if cloud else ' in cloud catalogs.'
3347
+ cloud_str = f' on {cloud_obj}.' if cloud_name else ' in cloud catalogs.'
3340
3348
  yield f'Resources \'{name}\'{quantity_str} not found{cloud_str} '
3341
3349
  yield 'To show available accelerators, run: sky show-gpus --all'
3342
3350
  return
sky/clouds/cloud.py CHANGED
@@ -819,6 +819,10 @@ class Cloud:
819
819
 
820
820
  # === End of image related methods ===
821
821
 
822
+ @classmethod
823
+ def canonical_name(cls) -> str:
824
+ return cls.__name__.lower()
825
+
822
826
  def __repr__(self):
823
827
  return self._REPR
824
828
 
@@ -1,7 +1,7 @@
1
1
  """Clouds need to be registered in CLOUD_REGISTRY to be discovered"""
2
2
 
3
3
  import typing
4
- from typing import Optional, Type
4
+ from typing import Callable, Dict, List, Optional, overload, Type, Union
5
5
 
6
6
  from sky.utils import ux_utils
7
7
 
@@ -12,20 +12,65 @@ if typing.TYPE_CHECKING:
12
12
  class _CloudRegistry(dict):
13
13
  """Registry of clouds."""
14
14
 
15
+ def __init__(self) -> None:
16
+ super().__init__()
17
+ self.aliases: Dict[str, str] = {}
18
+
15
19
  def from_str(self, name: Optional[str]) -> Optional['cloud.Cloud']:
20
+ """Returns the cloud instance from the canonical name or alias."""
16
21
  if name is None:
17
22
  return None
18
- if name.lower() not in self:
19
- with ux_utils.print_exception_no_traceback():
20
- raise ValueError(f'Cloud {name!r} is not a valid cloud among '
21
- f'{list(self.keys())}')
22
- return self.get(name.lower())
23
23
 
24
+ search_name = name.lower()
25
+
26
+ if search_name in self:
27
+ return self[search_name]
28
+
29
+ if search_name in self.aliases:
30
+ return self[self.aliases[search_name]]
31
+
32
+ with ux_utils.print_exception_no_traceback():
33
+ raise ValueError(f'Cloud {name!r} is not a valid cloud among '
34
+ f'{[*self.keys(), *self.aliases.keys()]}')
35
+
36
+ @overload
24
37
  def register(self, cloud_cls: Type['cloud.Cloud']) -> Type['cloud.Cloud']:
25
- name = cloud_cls.__name__.lower()
26
- assert name not in self, f'{name} already registered'
27
- self[name] = cloud_cls()
28
- return cloud_cls
38
+ ...
39
+
40
+ @overload
41
+ def register(
42
+ self,
43
+ cloud_cls: None = None,
44
+ aliases: Optional[List[str]] = None,
45
+ ) -> Callable[[Type['cloud.Cloud']], Type['cloud.Cloud']]:
46
+ ...
47
+
48
+ def register(
49
+ self,
50
+ cloud_cls: Optional[Type['cloud.Cloud']] = None,
51
+ aliases: Optional[List[str]] = None,
52
+ ) -> Union[Type['cloud.Cloud'], Callable[[Type['cloud.Cloud']],
53
+ Type['cloud.Cloud']]]:
54
+
55
+ def _register(cloud_cls: Type['cloud.Cloud']) -> Type['cloud.Cloud']:
56
+ name = cloud_cls.canonical_name()
57
+ assert name not in self, f'{name} already registered'
58
+ self[name] = cloud_cls()
59
+
60
+ for alias in aliases or []:
61
+ alias = alias.lower()
62
+ assert alias not in self.aliases, (
63
+ f'alias {alias} already registered')
64
+ self.aliases[alias] = name
65
+
66
+ return cloud_cls
67
+
68
+ if cloud_cls is not None:
69
+ # invocation without parens (e.g. just `@register`)
70
+ return _register(cloud_cls)
71
+
72
+ # Invocation with parens (e.g. `@register(aliases=['alias'])`)
73
+ return _register
29
74
 
30
75
 
31
76
  CLOUD_REGISTRY: _CloudRegistry = _CloudRegistry()
sky/clouds/kubernetes.py CHANGED
@@ -33,7 +33,7 @@ CREDENTIAL_PATH = os.environ.get('KUBECONFIG', DEFAULT_KUBECONFIG_PATH)
33
33
  _SKYPILOT_SYSTEM_NAMESPACE = 'skypilot-system'
34
34
 
35
35
 
36
- @clouds.CLOUD_REGISTRY.register
36
+ @clouds.CLOUD_REGISTRY.register(aliases=['k8s'])
37
37
  class Kubernetes(clouds.Cloud):
38
38
  """Kubernetes."""
39
39
 
@@ -46,6 +46,7 @@ def bootstrap_instances(
46
46
  region: str, cluster_name_on_cloud: str,
47
47
  config: common.ProvisionConfig) -> common.ProvisionConfig:
48
48
  """See sky/provision/__init__.py"""
49
+ # TODO: use new azure sdk instead of ARM deployment.
49
50
  del region # unused
50
51
  provider_config = config.provider_config
51
52
  subscription_id = provider_config.get('subscription_id')
@@ -2,10 +2,8 @@
2
2
  import base64
3
3
  import copy
4
4
  import enum
5
- import json
6
5
  import logging
7
6
  from multiprocessing import pool
8
- import pathlib
9
7
  import time
10
8
  import typing
11
9
  from typing import Any, Callable, Dict, List, Optional, Tuple
@@ -23,7 +21,9 @@ from sky.utils import ux_utils
23
21
 
24
22
  if typing.TYPE_CHECKING:
25
23
  from azure.mgmt import compute as azure_compute
26
- from azure.mgmt import resource as azure_resource
24
+ from azure.mgmt import network as azure_network
25
+ from azure.mgmt.compute import models as azure_compute_models
26
+ from azure.mgmt.network import models as azure_network_models
27
27
 
28
28
  logger = sky_logging.init_logger(__name__)
29
29
 
@@ -184,14 +184,150 @@ def _get_head_instance_id(instances: List) -> Optional[str]:
184
184
  return head_instance_id
185
185
 
186
186
 
187
- def _create_instances(
188
- compute_client: 'azure_compute.ComputeManagementClient',
189
- resource_client: 'azure_resource.ResourceManagementClient',
190
- cluster_name_on_cloud: str, resource_group: str,
191
- provider_config: Dict[str, Any], node_config: Dict[str, Any],
192
- tags: Dict[str, str], count: int) -> List:
187
+ def _create_network_interface(
188
+ network_client: 'azure_network.NetworkManagementClient', vm_name: str,
189
+ provider_config: Dict[str,
190
+ Any]) -> 'azure_network_models.NetworkInterface':
191
+ network = azure.azure_mgmt_models('network')
192
+ compute = azure.azure_mgmt_models('compute')
193
+ logger.info(f'Start creating network interface for {vm_name}...')
194
+ if provider_config.get('use_internal_ips', False):
195
+ name = f'{vm_name}-nic-private'
196
+ ip_config = network.IPConfiguration(
197
+ name=f'ip-config-private-{vm_name}',
198
+ subnet=compute.SubResource(id=provider_config['subnet']),
199
+ private_ip_allocation_method=network.IPAllocationMethod.DYNAMIC)
200
+ else:
201
+ name = f'{vm_name}-nic-public'
202
+ public_ip_address = network.PublicIPAddress(
203
+ location=provider_config['location'],
204
+ public_ip_allocation_method='Static',
205
+ public_ip_address_version='IPv4',
206
+ sku=network.PublicIPAddressSku(name='Basic', tier='Regional'))
207
+ ip_poller = network_client.public_ip_addresses.begin_create_or_update(
208
+ resource_group_name=provider_config['resource_group'],
209
+ public_ip_address_name=f'{vm_name}-ip',
210
+ parameters=public_ip_address)
211
+ logger.info(f'Created public IP address {ip_poller.result().name} '
212
+ f'with address {ip_poller.result().ip_address}.')
213
+ ip_config = network.IPConfiguration(
214
+ name=f'ip-config-public-{vm_name}',
215
+ subnet=compute.SubResource(id=provider_config['subnet']),
216
+ private_ip_allocation_method=network.IPAllocationMethod.DYNAMIC,
217
+ public_ip_address=network.PublicIPAddress(id=ip_poller.result().id))
218
+
219
+ ni_poller = network_client.network_interfaces.begin_create_or_update(
220
+ resource_group_name=provider_config['resource_group'],
221
+ network_interface_name=name,
222
+ parameters=network.NetworkInterface(
223
+ location=provider_config['location'],
224
+ ip_configurations=[ip_config],
225
+ network_security_group=network.NetworkSecurityGroup(
226
+ id=provider_config['nsg'])))
227
+ logger.info(f'Created network interface {ni_poller.result().name}.')
228
+ return ni_poller.result()
229
+
230
+
231
+ def _create_vm(
232
+ compute_client: 'azure_compute.ComputeManagementClient', vm_name: str,
233
+ node_tags: Dict[str, str], provider_config: Dict[str, Any],
234
+ node_config: Dict[str, Any],
235
+ network_interface_id: str) -> 'azure_compute_models.VirtualMachine':
236
+ compute = azure.azure_mgmt_models('compute')
237
+ logger.info(f'Start creating VM {vm_name}...')
238
+ hardware_profile = compute.HardwareProfile(
239
+ vm_size=node_config['azure_arm_parameters']['vmSize'])
240
+ network_profile = compute.NetworkProfile(network_interfaces=[
241
+ compute.NetworkInterfaceReference(id=network_interface_id, primary=True)
242
+ ])
243
+ public_key = node_config['azure_arm_parameters']['publicKey']
244
+ username = node_config['azure_arm_parameters']['adminUsername']
245
+ os_linux_custom_data = base64.b64encode(
246
+ node_config['azure_arm_parameters']['cloudInitSetupCommands'].encode(
247
+ 'utf-8')).decode('utf-8')
248
+ os_profile = compute.OSProfile(
249
+ admin_username=username,
250
+ computer_name=vm_name,
251
+ admin_password=public_key,
252
+ linux_configuration=compute.LinuxConfiguration(
253
+ disable_password_authentication=True,
254
+ ssh=compute.SshConfiguration(public_keys=[
255
+ compute.SshPublicKey(
256
+ path=f'/home/{username}/.ssh/authorized_keys',
257
+ key_data=public_key)
258
+ ])),
259
+ custom_data=os_linux_custom_data)
260
+ community_image_id = node_config['azure_arm_parameters'].get(
261
+ 'communityGalleryImageId', None)
262
+ if community_image_id is not None:
263
+ # Prioritize using community gallery image if specified.
264
+ image_reference = compute.ImageReference(
265
+ community_gallery_image_id=community_image_id)
266
+ logger.info(
267
+ f'Used community_image_id: {community_image_id} for VM {vm_name}.')
268
+ else:
269
+ image_reference = compute.ImageReference(
270
+ publisher=node_config['azure_arm_parameters']['imagePublisher'],
271
+ offer=node_config['azure_arm_parameters']['imageOffer'],
272
+ sku=node_config['azure_arm_parameters']['imageSku'],
273
+ version=node_config['azure_arm_parameters']['imageVersion'])
274
+ storage_profile = compute.StorageProfile(
275
+ image_reference=image_reference,
276
+ os_disk=compute.OSDisk(
277
+ create_option=compute.DiskCreateOptionTypes.FROM_IMAGE,
278
+ managed_disk=compute.ManagedDiskParameters(
279
+ storage_account_type=node_config['azure_arm_parameters']
280
+ ['osDiskTier']),
281
+ disk_size_gb=node_config['azure_arm_parameters']['osDiskSizeGB']))
282
+ vm_instance = compute.VirtualMachine(
283
+ location=provider_config['location'],
284
+ tags=node_tags,
285
+ hardware_profile=hardware_profile,
286
+ os_profile=os_profile,
287
+ storage_profile=storage_profile,
288
+ network_profile=network_profile,
289
+ identity=compute.VirtualMachineIdentity(
290
+ type='UserAssigned',
291
+ user_assigned_identities={provider_config['msi']: {}}))
292
+ vm_poller = compute_client.virtual_machines.begin_create_or_update(
293
+ resource_group_name=provider_config['resource_group'],
294
+ vm_name=vm_name,
295
+ parameters=vm_instance,
296
+ )
297
+ # poller.result() will block on async operation until it's done.
298
+ logger.info(f'Created VM {vm_poller.result().name}.')
299
+ # Configure driver extension for A10 GPUs. A10 GPUs requires a
300
+ # special type of drivers which is available at Microsoft HPC
301
+ # extension. Reference:
302
+ # https://forums.developer.nvidia.com/t/ubuntu-22-04-installation-driver-error-nvidia-a10/285195/2
303
+ # This can take more than 20mins for setting up the A10 GPUs
304
+ if node_config.get('need_nvidia_driver_extension', False):
305
+ ext_poller = compute_client.virtual_machine_extensions.\
306
+ begin_create_or_update(
307
+ resource_group_name=provider_config['resource_group'],
308
+ vm_name=vm_name,
309
+ vm_extension_name='NvidiaGpuDriverLinux',
310
+ extension_parameters=compute.VirtualMachineExtension(
311
+ location=provider_config['location'],
312
+ publisher='Microsoft.HpcCompute',
313
+ type_properties_type='NvidiaGpuDriverLinux',
314
+ type_handler_version='1.9',
315
+ auto_upgrade_minor_version=True,
316
+ settings='{}'))
317
+ logger.info(
318
+ f'Created VM extension {ext_poller.result().name} for VM {vm_name}.'
319
+ )
320
+ return vm_poller.result()
321
+
322
+
323
+ def _create_instances(compute_client: 'azure_compute.ComputeManagementClient',
324
+ network_client: 'azure_network.NetworkManagementClient',
325
+ cluster_name_on_cloud: str, resource_group: str,
326
+ provider_config: Dict[str, Any], node_config: Dict[str,
327
+ Any],
328
+ tags: Dict[str, str], count: int) -> List:
193
329
  vm_id = uuid4().hex[:UNIQUE_ID_LEN]
194
- tags = {
330
+ all_tags = {
195
331
  constants.TAG_RAY_CLUSTER_NAME: cluster_name_on_cloud,
196
332
  constants.TAG_SKYPILOT_CLUSTER_NAME: cluster_name_on_cloud,
197
333
  **constants.WORKER_NODE_TAGS,
@@ -199,83 +335,19 @@ def _create_instances(
199
335
  **tags,
200
336
  }
201
337
  node_tags = node_config['tags'].copy()
202
- node_tags.update(tags)
203
-
204
- # load the template file
205
- current_path = pathlib.Path(__file__).parent
206
- template_path = current_path.joinpath('azure-vm-template.json')
207
- with open(template_path, 'r', encoding='utf-8') as template_fp:
208
- template = json.load(template_fp)
209
-
210
- vm_name = f'{cluster_name_on_cloud}-{vm_id}'
211
- use_internal_ips = provider_config.get('use_internal_ips', False)
338
+ node_tags.update(all_tags)
212
339
 
213
- template_params = node_config['azure_arm_parameters'].copy()
214
- # We don't include 'head' or 'worker' in the VM name as on Azure the VM
215
- # name is immutable and we may change the node type for existing VM in the
216
- # multi-node cluster, due to manual termination of the head node.
217
- template_params['vmName'] = vm_name
218
- template_params['provisionPublicIp'] = not use_internal_ips
219
- template_params['vmTags'] = node_tags
220
- template_params['vmCount'] = count
221
- template_params['msi'] = provider_config['msi']
222
- template_params['nsg'] = provider_config['nsg']
223
- template_params['subnet'] = provider_config['subnet']
224
- # In Azure, cloud-init script must be encoded in base64. For more
225
- # information, see:
226
- # https://learn.microsoft.com/en-us/azure/virtual-machines/custom-data
227
- template_params['cloudInitSetupCommands'] = (base64.b64encode(
228
- template_params['cloudInitSetupCommands'].encode('utf-8')).decode(
229
- 'utf-8'))
340
+ # Create VM instances in parallel.
341
+ def create_single_instance(vm_i):
342
+ vm_name = f'{cluster_name_on_cloud}-{vm_id}-{vm_i}'
343
+ network_interface = _create_network_interface(network_client, vm_name,
344
+ provider_config)
345
+ _create_vm(compute_client, vm_name, node_tags, provider_config,
346
+ node_config, network_interface.id)
230
347
 
231
- if node_config.get('need_nvidia_driver_extension', False):
232
- # pylint: disable=line-too-long
233
- # Configure driver extension for A10 GPUs. A10 GPUs requires a
234
- # special type of drivers which is available at Microsoft HPC
235
- # extension. Reference: https://forums.developer.nvidia.com/t/ubuntu-22-04-installation-driver-error-nvidia-a10/285195/2
236
- for r in template['resources']:
237
- if r['type'] == 'Microsoft.Compute/virtualMachines':
238
- # Add a nested extension resource for A10 GPUs
239
- r['resources'] = [
240
- {
241
- 'type': 'extensions',
242
- 'apiVersion': '2015-06-15',
243
- 'location': '[variables(\'location\')]',
244
- 'dependsOn': [
245
- '[concat(\'Microsoft.Compute/virtualMachines/\', parameters(\'vmName\'), copyIndex())]'
246
- ],
247
- 'name': 'NvidiaGpuDriverLinux',
248
- 'properties': {
249
- 'publisher': 'Microsoft.HpcCompute',
250
- 'type': 'NvidiaGpuDriverLinux',
251
- 'typeHandlerVersion': '1.9',
252
- 'autoUpgradeMinorVersion': True,
253
- 'settings': {},
254
- },
255
- },
256
- ]
257
- break
258
-
259
- parameters = {
260
- 'properties': {
261
- 'mode': azure.deployment_mode().incremental,
262
- 'template': template,
263
- 'parameters': {
264
- key: {
265
- 'value': value
266
- } for key, value in template_params.items()
267
- },
268
- }
269
- }
270
-
271
- create_or_update = _get_azure_sdk_function(
272
- client=resource_client.deployments, function_name='create_or_update')
273
- create_or_update(
274
- resource_group_name=resource_group,
275
- deployment_name=vm_name,
276
- parameters=parameters,
277
- ).wait()
348
+ subprocess_utils.run_in_parallel(create_single_instance, range(count))
278
349
 
350
+ # Update disk performance tier
279
351
  performance_tier = node_config.get('disk_performance_tier', None)
280
352
  if performance_tier is not None:
281
353
  disks = compute_client.disks.list_by_resource_group(resource_group)
@@ -286,12 +358,14 @@ def _create_instances(
286
358
  f'az disk update -n {name} -g {resource_group} '
287
359
  f'--set tier={performance_tier}')
288
360
 
361
+ # Validation
289
362
  filters = {
290
363
  constants.TAG_RAY_CLUSTER_NAME: cluster_name_on_cloud,
291
364
  _TAG_SKYPILOT_VM_ID: vm_id
292
365
  }
293
366
  instances = _filter_instances(compute_client, resource_group, filters)
294
367
  assert len(instances) == count, (len(instances), count)
368
+
295
369
  return instances
296
370
 
297
371
 
@@ -303,7 +377,7 @@ def run_instances(region: str, cluster_name_on_cloud: str,
303
377
  resource_group = provider_config['resource_group']
304
378
  subscription_id = provider_config['subscription_id']
305
379
  compute_client = azure.get_client('compute', subscription_id)
306
-
380
+ network_client = azure.get_client('network', subscription_id)
307
381
  instances_to_resume = []
308
382
  resumed_instance_ids: List[str] = []
309
383
  created_instance_ids: List[str] = []
@@ -439,12 +513,11 @@ def run_instances(region: str, cluster_name_on_cloud: str,
439
513
  to_start_count -= len(resumed_instance_ids)
440
514
 
441
515
  if to_start_count > 0:
442
- resource_client = azure.get_client('resource', subscription_id)
443
516
  logger.debug(f'run_instances: Creating {to_start_count} instances.')
444
517
  try:
445
518
  created_instances = _create_instances(
446
519
  compute_client=compute_client,
447
- resource_client=resource_client,
520
+ network_client=network_client,
448
521
  cluster_name_on_cloud=cluster_name_on_cloud,
449
522
  resource_group=resource_group,
450
523
  provider_config=provider_config,
@@ -67,6 +67,8 @@ available_node_types:
67
67
  imageOffer: {{image_offer}}
68
68
  imageSku: "{{image_sku}}"
69
69
  imageVersion: {{image_version}}
70
+ # Community Gallery Image ID
71
+ communityGalleryImageId: {{community_gallery_image_id}}
70
72
  osDiskSizeGB: {{disk_size}}
71
73
  osDiskTier: {{disk_tier}}
72
74
  {%- if use_spot %}
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: skypilot-nightly
3
- Version: 1.0.0.dev20241023
3
+ Version: 1.0.0.dev20241024
4
4
  Summary: SkyPilot: An intercloud broker for the clouds
5
5
  Author: SkyPilot Team
6
6
  License: Apache 2.0
@@ -1,8 +1,8 @@
1
- sky/__init__.py,sha256=GIJDzXwASAEaGbwO52D-mvm5JVbXxjMbdt9_OZ0Wsv4,5854
1
+ sky/__init__.py,sha256=6pKM5lRNTckGEImvaBniSM_EuAzDT5xbSHqP8AhenhU,5882
2
2
  sky/admin_policy.py,sha256=hPo02f_A32gCqhUueF0QYy1fMSSKqRwYEg_9FxScN_s,3248
3
3
  sky/authentication.py,sha256=pAdCT60OxxiXI9KXDyP2lQ9u9vMc6aMtq5Xi2h_hbdw,20984
4
4
  sky/check.py,sha256=jLMIIJrseaZj1_o5WkbaD9XdyXIlCaT6pyAaIFdhdmA,9079
5
- sky/cli.py,sha256=XcQeVtH5J7xcARGagYicmTUfd2145jN2nvnZaZXtZlI,209981
5
+ sky/cli.py,sha256=PdqIKhGs6P2lHEShX2-iSwAtbpS5TTFKWNKCRl2i6kw,210345
6
6
  sky/cloud_stores.py,sha256=RjFgmRhUh1Kk__f6g3KxzLp9s7dA0pFK4W1AukEuUaw,21153
7
7
  sky/core.py,sha256=DW9OGE2kS2CmsvQ1grrpRnNFS3woMGWSHu5GE99e-I4,38190
8
8
  sky/dag.py,sha256=WLFWr5hfrwjd31uYlNvI-zWUk7tLaT_gzJn4LzbVtkE,2780
@@ -17,7 +17,7 @@ sky/status_lib.py,sha256=J7Jb4_Dz0v2T64ttOdyUgpokvl4S0sBJrMfH7Fvo51A,1457
17
17
  sky/task.py,sha256=KDsTBIxYpkCOPHv3_ei5H3LDMiGHvDeS9_2HeL6yyLA,49766
18
18
  sky/adaptors/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
19
19
  sky/adaptors/aws.py,sha256=jz3E8YyeGscgLZvFE6A1SkxpH6o_inZ-0NiXdRnxSGA,6863
20
- sky/adaptors/azure.py,sha256=edWy5YgW6dAUl8pPWvSJ8x5mRgCew1KmDpntTw65vHo,21464
20
+ sky/adaptors/azure.py,sha256=n4PXHGJ8ambcbzYzWifj9BsoShUhg62pF6udmUw45S8,21762
21
21
  sky/adaptors/cloudflare.py,sha256=0JA41HeZeYoqcJoEyol01caYgt8UrlpcZJJ6ToU-Fg8,7594
22
22
  sky/adaptors/common.py,sha256=VhgAFPx-GmhXoob8B1YvqGC2BXs2HwtqoA8oFMaqkbc,2551
23
23
  sky/adaptors/cudo.py,sha256=WGvIQrlzJkGDe02Ve7pygA56tHwUc4kwS3XHW8kMFAA,239
@@ -42,13 +42,13 @@ sky/benchmark/benchmark_utils.py,sha256=eb-i6zYoo-Zkod-T9qtCu1FcYLw--Yyos1SyibUP
42
42
  sky/clouds/__init__.py,sha256=WuNIJEnZmBO72tU5awgaaL3rdvFRSkgaYNNeuY68dXo,1356
43
43
  sky/clouds/aws.py,sha256=XJVbOSkVVUHp9HbHDp0rFdHX113JHbY-3sgokGdNJVE,49527
44
44
  sky/clouds/azure.py,sha256=jTgynKU5tuOyBe97n2I7_k9P0Sw0QFU-6wLDLFwQhfM,28634
45
- sky/clouds/cloud.py,sha256=PPk-Cbf1YbJT8bswcQLtPBtko02OWrRGJKkLzDpytTI,34858
46
- sky/clouds/cloud_registry.py,sha256=4yQMv-iBSgyN5aNL4Qxbn0JVE-dkVoEUIgj7S1z9S_Q,955
45
+ sky/clouds/cloud.py,sha256=BBu1G-gkmylffldL50cvJ2DkDJ8vjVPziOPUAsvgJ2o,34948
46
+ sky/clouds/cloud_registry.py,sha256=oLoYFjm_SDTgdHokY7b6A5Utq80HXRQNxV0fLjDdVsQ,2361
47
47
  sky/clouds/cudo.py,sha256=H4VyMo5wWGAv2MXZ3xsbWjlZA_cZYnt4ecNlTOOao8Y,13147
48
48
  sky/clouds/fluidstack.py,sha256=iOmoOx52yTrHKMzwBDaxFJCfNo79M61d5tj-Np24Lyc,12436
49
49
  sky/clouds/gcp.py,sha256=m_dH04HqgU-DdW4R9wrSr66IpPt9JMKHEvHEGGFpeRo,54655
50
50
  sky/clouds/ibm.py,sha256=M8QdjeSFlwssfoY2aOodxG4q5R3eT9K-4lTPDHYvEYI,21476
51
- sky/clouds/kubernetes.py,sha256=aWoXWR-S4puZHzuUHroLKxLdTpkqU7j75dQlXECnsmE,28679
51
+ sky/clouds/kubernetes.py,sha256=j3imm_sbtyyZXvJ6qbqZmXok2C9OQIcGpyulljbTSJ4,28696
52
52
  sky/clouds/lambda_cloud.py,sha256=11dKUSunHUgaPZ1t8O85X29_NJ-o26sCt5DjwAPFgl4,12697
53
53
  sky/clouds/oci.py,sha256=ecVgcbCVJwDLtaYXs-yGDzwPYRr23KvjnzFOXwaY2O0,26914
54
54
  sky/clouds/paperspace.py,sha256=lmUZPYAblaqiBmGQwCunccMiTF_dVA1o3vqY9Q_Nc28,10921
@@ -116,9 +116,8 @@ sky/provision/aws/instance.py,sha256=eCslJ2XfJo_pkQMnKFQqhGnUIRvwKiT12oxBY5-klss
116
116
  sky/provision/aws/utils.py,sha256=m49pS-SHGW7Au3bhDeTPsL8N5iRzbwOXzyEWRCc1Vho,3238
117
117
  sky/provision/azure/__init__.py,sha256=87cgk1_Ws7n9rqaDDPv-HpfrkVeSQMdFQnhnXwyx9g4,548
118
118
  sky/provision/azure/azure-config-template.json,sha256=dwTO-DG70UtBifN59NzsJwPZHZ4uCs7_oLooHgXG_N8,4349
119
- sky/provision/azure/azure-vm-template.json,sha256=k0A4xclQ-xQbAdcjo516sZqMDsU-n8_jeRuPxtGKBFI,10901
120
- sky/provision/azure/config.py,sha256=qNUNcX1HboosuZASEVgJ_K-g7CNNWExodWXFIsoq5V8,7288
121
- sky/provision/azure/instance.py,sha256=3xHRkWcElAgaOuOzcBdwfnLni8zD8KwNgYmj3A7gljA,33244
119
+ sky/provision/azure/config.py,sha256=-VUYxmwLZKHzxNkRmE0q8ZkZ_0iq-gi0q8XPvRD_Y0U,7345
120
+ sky/provision/azure/instance.py,sha256=pDdGScePohZHTRLEtr92k6vO9LIyd-RBCKOkZ5oDV58,37463
122
121
  sky/provision/cudo/__init__.py,sha256=KAEl26MVPsk7IoP9Gg-MOJJRIV6-X9B0fbyHdyJWdLo,741
123
122
  sky/provision/cudo/config.py,sha256=RYOVkV0MoUqVBJRZiKhBZhjFygeyFs7eUdVMdPg1vds,327
124
123
  sky/provision/cudo/cudo_machine_type.py,sha256=_VNXWPELmlFXbtdcnPvkuLuyE9CZ923BUCdiac-ClDY,696
@@ -219,7 +218,7 @@ sky/skylet/ray_patches/resource_demand_scheduler.py.patch,sha256=AVV-Hw-Rxw16aFm
219
218
  sky/skylet/ray_patches/updater.py.patch,sha256=ZNMGVYICPBB44jLbEx2KvCgIY7BWYdDv3-2b2HJWmAQ,289
220
219
  sky/skylet/ray_patches/worker.py.patch,sha256=_OBhibdr3xOy5Qje6Tt8D1eQVm_msi50TJbCJmOTxVU,565
221
220
  sky/templates/aws-ray.yml.j2,sha256=K0rAuyf1XC_GPFp1BR9df42-Be12A6T2UF0BllVSpYg,8005
222
- sky/templates/azure-ray.yml.j2,sha256=RtYAcAmFQd6TB3j-pbxi7ekjWhznqFhJtzdkqH_nXqM,6135
221
+ sky/templates/azure-ray.yml.j2,sha256=zjASvx-Y0ZNEvCg9hsBhp3mt0Je5fvUv6XYUAYdrNqI,6245
223
222
  sky/templates/cudo-ray.yml.j2,sha256=SEHVY57iBauCOE2HYJtYVFEKlriAkdwQu_p86a1n_bA,3548
224
223
  sky/templates/fluidstack-ray.yml.j2,sha256=t8TCULgiErCZdtFmBZVsA8ZdcqR7ccwsmQhuDFTBEAU,3541
225
224
  sky/templates/gcp-ray.yml.j2,sha256=y95B-Nk6hFxm6vEIaxI1wFzAIcy_GcKC3XMYo9m-ThI,9662
@@ -274,9 +273,9 @@ sky/utils/kubernetes/k8s_gpu_labeler_job.yaml,sha256=k0TBoQ4zgf79-sVkixKSGYFHQ7Z
274
273
  sky/utils/kubernetes/k8s_gpu_labeler_setup.yaml,sha256=VLKT2KKimZu1GDg_4AIlIt488oMQvhRZWwsj9vBbPUg,3812
275
274
  sky/utils/kubernetes/rsync_helper.sh,sha256=hyYDaYSNxYaNvzUQBzC8AidB7nDeojizjkzc_CTxycY,1077
276
275
  sky/utils/kubernetes/ssh_jump_lifecycle_manager.py,sha256=RFLJ3k7MR5UN4SKHykQ0lV9SgXumoULpKYIAt1vh-HU,6560
277
- skypilot_nightly-1.0.0.dev20241023.dist-info/LICENSE,sha256=emRJAvE7ngL6x0RhQvlns5wJzGI3NEQ_WMjNmd9TZc4,12170
278
- skypilot_nightly-1.0.0.dev20241023.dist-info/METADATA,sha256=6-0lKUe3hPKV5QaL0oSkB1tfG8-_YiqTr9B65uAplTw,19540
279
- skypilot_nightly-1.0.0.dev20241023.dist-info/WHEEL,sha256=OVMc5UfuAQiSplgO0_WdW7vXVGAt9Hdd6qtN4HotdyA,91
280
- skypilot_nightly-1.0.0.dev20241023.dist-info/entry_points.txt,sha256=StA6HYpuHj-Y61L2Ze-hK2IcLWgLZcML5gJu8cs6nU4,36
281
- skypilot_nightly-1.0.0.dev20241023.dist-info/top_level.txt,sha256=qA8QuiNNb6Y1OF-pCUtPEr6sLEwy2xJX06Bd_CrtrHY,4
282
- skypilot_nightly-1.0.0.dev20241023.dist-info/RECORD,,
276
+ skypilot_nightly-1.0.0.dev20241024.dist-info/LICENSE,sha256=emRJAvE7ngL6x0RhQvlns5wJzGI3NEQ_WMjNmd9TZc4,12170
277
+ skypilot_nightly-1.0.0.dev20241024.dist-info/METADATA,sha256=R0zBIXcaURnFidv6hVzwuO_p5xUp-L8ZB5_l9-NG0yc,19540
278
+ skypilot_nightly-1.0.0.dev20241024.dist-info/WHEEL,sha256=OVMc5UfuAQiSplgO0_WdW7vXVGAt9Hdd6qtN4HotdyA,91
279
+ skypilot_nightly-1.0.0.dev20241024.dist-info/entry_points.txt,sha256=StA6HYpuHj-Y61L2Ze-hK2IcLWgLZcML5gJu8cs6nU4,36
280
+ skypilot_nightly-1.0.0.dev20241024.dist-info/top_level.txt,sha256=qA8QuiNNb6Y1OF-pCUtPEr6sLEwy2xJX06Bd_CrtrHY,4
281
+ skypilot_nightly-1.0.0.dev20241024.dist-info/RECORD,,
@@ -1,301 +0,0 @@
1
- {
2
- "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
3
- "contentVersion": "1.0.0.0",
4
- "parameters": {
5
- "vmName": {
6
- "type": "string",
7
- "metadata": {
8
- "description": "The name of you Virtual Machine."
9
- }
10
- },
11
- "adminUsername": {
12
- "type": "string",
13
- "metadata": {
14
- "description": "Username for the Virtual Machine."
15
- }
16
- },
17
- "publicKey": {
18
- "type": "securestring",
19
- "metadata": {
20
- "description": "SSH Key for the Virtual Machine"
21
- }
22
- },
23
- "imagePublisher": {
24
- "type": "string",
25
- "metadata": {
26
- "description": "The publisher of the VM image"
27
- }
28
- },
29
- "imageOffer": {
30
- "type": "string",
31
- "metadata": {
32
- "description": "The offer of the VM image"
33
- }
34
- },
35
- "imageSku": {
36
- "type": "string",
37
- "metadata": {
38
- "description": "The sku of the VM image"
39
- }
40
- },
41
- "imageVersion": {
42
- "type": "string",
43
- "metadata": {
44
- "description": "The version of the VM image"
45
- }
46
- },
47
- "vmSize": {
48
- "type": "string",
49
- "metadata": {
50
- "description": "The size of the VM"
51
- }
52
- },
53
- "vmTags": {
54
- "type": "object",
55
- "metadata": {
56
- "description": "Tags for the VM"
57
- }
58
- },
59
- "vmCount": {
60
- "type": "int",
61
- "metadata": {
62
- "description": "Number of VMs to deploy"
63
- }
64
- },
65
- "provisionPublicIp": {
66
- "type": "bool",
67
- "defaultValue": true,
68
- "metadata": {
69
- "description": "If true creates a public ip"
70
- }
71
- },
72
- "priority": {
73
- "type": "string",
74
- "defaultValue": "Regular",
75
- "metadata": {
76
- "description": "Specifies the priority for the virtual machine."
77
- }
78
- },
79
- "billingProfile": {
80
- "type": "object",
81
- "defaultValue": {},
82
- "metadata": {
83
- "description": "Specifies the maximum price to pay for Azure Spot VM."
84
- }
85
- },
86
- "osDiskSizeGB": {
87
- "type": "int",
88
- "metadata": {
89
- "description": "OS disk size in GBs."
90
- }
91
- },
92
- "msi": {
93
- "type": "string",
94
- "metadata": {
95
- "description": "Managed service identity resource id."
96
- }
97
- },
98
- "nsg": {
99
- "type": "string",
100
- "metadata": {
101
- "description": "Network security group resource id."
102
- }
103
- },
104
- "subnet": {
105
- "type": "string",
106
- "metadata": {
107
- "descriptions": "Subnet resource id."
108
- }
109
- },
110
- "osDiskTier": {
111
- "type": "string",
112
- "allowedValues": [
113
- "Premium_LRS",
114
- "StandardSSD_LRS",
115
- "Standard_LRS"
116
- ],
117
- "metadata": {
118
- "description": "OS disk tier."
119
- }
120
- },
121
- "cloudInitSetupCommands": {
122
- "type": "string",
123
- "metadata": {
124
- "description": "Base64 encoded cloud-init setup commands."
125
- }
126
- }
127
- },
128
- "variables": {
129
- "location": "[resourceGroup().location]",
130
- "networkInterfaceNamePrivate": "[concat(parameters('vmName'), '-nic')]",
131
- "networkInterfaceNamePublic": "[concat(parameters('vmName'), '-nic-public')]",
132
- "networkInterfaceName": "[if(parameters('provisionPublicIp'), variables('networkInterfaceNamePublic'), variables('networkInterfaceNamePrivate'))]",
133
- "networkIpConfig": "[guid(resourceGroup().id, parameters('vmName'))]",
134
- "publicIpAddressName": "[concat(parameters('vmName'), '-ip')]"
135
- },
136
- "resources": [
137
- {
138
- "type": "Microsoft.Network/networkInterfaces",
139
- "apiVersion": "2020-06-01",
140
- "name": "[concat(variables('networkInterfaceNamePublic'), copyIndex())]",
141
- "location": "[variables('location')]",
142
- "dependsOn": [
143
- "[resourceId('Microsoft.Network/publicIpAddresses/', concat(variables('publicIpAddressName'), copyIndex()))]"
144
- ],
145
- "copy": {
146
- "name": "NICPublicCopy",
147
- "count": "[parameters('vmCount')]"
148
- },
149
- "properties": {
150
- "ipConfigurations": [
151
- {
152
- "name": "[variables('networkIpConfig')]",
153
- "properties": {
154
- "subnet": {
155
- "id": "[parameters('subnet')]"
156
- },
157
- "privateIPAllocationMethod": "Dynamic",
158
- "publicIpAddress": {
159
- "id": "[resourceId('Microsoft.Network/publicIPAddresses', concat(variables('publicIPAddressName'), copyIndex()))]"
160
- }
161
- }
162
- }
163
- ],
164
- "networkSecurityGroup": {
165
- "id": "[parameters('nsg')]"
166
- }
167
- },
168
- "condition": "[parameters('provisionPublicIp')]"
169
- },
170
- {
171
- "type": "Microsoft.Network/networkInterfaces",
172
- "apiVersion": "2020-06-01",
173
- "name": "[concat(variables('networkInterfaceNamePrivate'), copyIndex())]",
174
- "location": "[variables('location')]",
175
- "copy": {
176
- "name": "NICPrivateCopy",
177
- "count": "[parameters('vmCount')]"
178
- },
179
- "properties": {
180
- "ipConfigurations": [
181
- {
182
- "name": "[variables('networkIpConfig')]",
183
- "properties": {
184
- "subnet": {
185
- "id": "[parameters('subnet')]"
186
- },
187
- "privateIPAllocationMethod": "Dynamic"
188
- }
189
- }
190
- ],
191
- "networkSecurityGroup": {
192
- "id": "[parameters('nsg')]"
193
- }
194
- },
195
- "condition": "[not(parameters('provisionPublicIp'))]"
196
- },
197
- {
198
- "type": "Microsoft.Network/publicIpAddresses",
199
- "apiVersion": "2019-02-01",
200
- "name": "[concat(variables('publicIpAddressName'), copyIndex())]",
201
- "location": "[variables('location')]",
202
- "properties": {
203
- "publicIpAllocationMethod": "Static",
204
- "publicIPAddressVersion": "IPv4"
205
- },
206
- "copy": {
207
- "name": "PublicIpCopy",
208
- "count": "[parameters('vmCount')]"
209
- },
210
- "sku": {
211
- "name": "Basic",
212
- "tier": "Regional"
213
- },
214
- "condition": "[parameters('provisionPublicIp')]"
215
- },
216
- {
217
- "type": "Microsoft.Compute/virtualMachines",
218
- "apiVersion": "2019-03-01",
219
- "name": "[concat(parameters('vmName'), copyIndex())]",
220
- "location": "[variables('location')]",
221
- "dependsOn": [
222
- "[resourceId('Microsoft.Network/networkInterfaces/', concat(variables('networkInterfaceName'), copyIndex()))]"
223
- ],
224
- "copy": {
225
- "name": "VmCopy",
226
- "count": "[parameters('vmCount')]"
227
- },
228
- "tags": "[parameters('vmTags')]",
229
- "properties": {
230
- "hardwareProfile": {
231
- "vmSize": "[parameters('vmSize')]"
232
- },
233
- "storageProfile": {
234
- "osDisk": {
235
- "createOption": "fromImage",
236
- "managedDisk": {
237
- "storageAccountType": "[parameters('osDiskTier')]"
238
- },
239
- "diskSizeGB": "[parameters('osDiskSizeGB')]"
240
- },
241
- "imageReference": {
242
- "publisher": "[parameters('imagePublisher')]",
243
- "offer": "[parameters('imageOffer')]",
244
- "sku": "[parameters('imageSku')]",
245
- "version": "[parameters('imageVersion')]"
246
- }
247
- },
248
- "networkProfile": {
249
- "networkInterfaces": [
250
- {
251
- "id": "[resourceId('Microsoft.Network/networkInterfaces', concat(variables('networkInterfaceName'), copyIndex()))]"
252
- }
253
- ]
254
- },
255
- "osProfile": {
256
- "computerName": "[concat(parameters('vmName'), copyIndex())]",
257
- "adminUsername": "[parameters('adminUsername')]",
258
- "adminPassword": "[parameters('publicKey')]",
259
- "linuxConfiguration": {
260
- "disablePasswordAuthentication": true,
261
- "ssh": {
262
- "publicKeys": [
263
- {
264
- "path": "[concat('/home/', parameters('adminUsername'), '/.ssh/authorized_keys')]",
265
- "keyData": "[parameters('publicKey')]"
266
- }
267
- ]
268
- }
269
- },
270
- "customData": "[parameters('cloudInitSetupCommands')]"
271
- },
272
- "priority": "[parameters('priority')]",
273
- "billingProfile": "[parameters('billingProfile')]"
274
- },
275
- "identity": {
276
- "type": "UserAssigned",
277
- "userAssignedIdentities": {
278
- "[parameters('msi')]": {
279
- }
280
- }
281
- }
282
- }
283
- ],
284
- "outputs": {
285
- "publicIp": {
286
- "type": "array",
287
- "copy": {
288
- "count": "[parameters('vmCount')]",
289
- "input": "[reference(concat(variables('publicIpAddressName'), copyIndex())).ipAddress]"
290
- },
291
- "condition": "[parameters('provisionPublicIp')]"
292
- },
293
- "privateIp": {
294
- "type": "array",
295
- "copy": {
296
- "count": "[parameters('vmCount')]",
297
- "input": "[reference(concat(variables('networkInterfaceName'), copyIndex())).ipConfigurations[0].properties.privateIPAddress]"
298
- }
299
- }
300
- }
301
- }