aws-parallelcluster 3.14.2__tar.gz → 3.15.1__tar.gz

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.
Files changed (244) hide show
  1. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/PKG-INFO +3 -3
  2. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/setup.py +3 -3
  3. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/aws_parallelcluster.egg-info/PKG-INFO +3 -3
  4. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/aws_parallelcluster.egg-info/SOURCES.txt +0 -1
  5. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/aws_parallelcluster.egg-info/requires.txt +2 -2
  6. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/api/openapi/openapi.yaml +1 -1
  7. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/aws/aws_resources.py +16 -2
  8. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/aws/ec2.py +31 -2
  9. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/aws/s3.py +11 -3
  10. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/cli/commands/configure/easyconfig.py +3 -3
  11. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/cli/commands/ssh.py +2 -4
  12. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/cli/model.py +1 -7
  13. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/config/cluster_config.py +50 -25
  14. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/config/update_policy.py +74 -0
  15. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/constants.py +38 -2
  16. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/models/s3_bucket.py +6 -3
  17. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/resources/compute_node/user_data.sh +6 -1
  18. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/resources/head_node/user_data.sh +6 -1
  19. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/resources/imagebuilder/parallelcluster.yaml +7 -2
  20. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/resources/imagebuilder/parallelcluster_test.yaml +1 -1
  21. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/resources/login_node/user_data.sh +6 -1
  22. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/schemas/cluster_schema.py +43 -8
  23. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/schemas/common_schema.py +3 -10
  24. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/templates/cluster_stack.py +90 -31
  25. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/templates/cw_dashboard_builder.py +19 -2
  26. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/templates/login_nodes_stack.py +0 -1
  27. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/templates/queues_stack.py +106 -11
  28. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/utils.py +76 -0
  29. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/validators/cluster_validators.py +9 -4
  30. aws_parallelcluster-3.15.1/src/pcluster/validators/dev_settings_validators.py +158 -0
  31. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/validators/ec2_validators.py +14 -34
  32. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/validators/instances_validators.py +74 -0
  33. aws_parallelcluster-3.14.2/src/pcluster/validators/dev_settings_validators.py +0 -62
  34. aws_parallelcluster-3.14.2/src/pcluster/validators/login_nodes_validators.py +0 -30
  35. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/MANIFEST.in +0 -0
  36. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/README +0 -0
  37. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/setup.cfg +0 -0
  38. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/aws_parallelcluster.egg-info/dependency_links.txt +0 -0
  39. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/aws_parallelcluster.egg-info/entry_points.txt +0 -0
  40. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/aws_parallelcluster.egg-info/not-zip-safe +0 -0
  41. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/aws_parallelcluster.egg-info/top_level.txt +0 -0
  42. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/__init__.py +0 -0
  43. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/api/__init__.py +0 -0
  44. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/api/awslambda/__init__.py +0 -0
  45. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/api/awslambda/entrypoint.py +0 -0
  46. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/api/awslambda/serverless_wsgi.py +0 -0
  47. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/api/controllers/__init__.py +0 -0
  48. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/api/controllers/cluster_compute_fleet_controller.py +0 -0
  49. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/api/controllers/cluster_instances_controller.py +0 -0
  50. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/api/controllers/cluster_logs_controller.py +0 -0
  51. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/api/controllers/cluster_operations_controller.py +0 -0
  52. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/api/controllers/common.py +0 -0
  53. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/api/controllers/image_logs_controller.py +0 -0
  54. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/api/controllers/image_operations_controller.py +0 -0
  55. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/api/converters.py +0 -0
  56. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/api/encoder.py +0 -0
  57. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/api/errors.py +0 -0
  58. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/api/flask_app.py +0 -0
  59. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/api/models/__init__.py +0 -0
  60. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/api/models/ami_info.py +0 -0
  61. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/api/models/bad_request_exception_response_content.py +0 -0
  62. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/api/models/base_model_.py +0 -0
  63. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/api/models/build_image_bad_request_exception_response_content.py +0 -0
  64. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/api/models/build_image_request_content.py +0 -0
  65. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/api/models/build_image_response_content.py +0 -0
  66. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/api/models/change.py +0 -0
  67. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/api/models/cloud_formation_resource_status.py +0 -0
  68. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/api/models/cloud_formation_stack_status.py +0 -0
  69. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/api/models/cluster_configuration_structure.py +0 -0
  70. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/api/models/cluster_info_summary.py +0 -0
  71. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/api/models/cluster_instance.py +0 -0
  72. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/api/models/cluster_status.py +0 -0
  73. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/api/models/cluster_status_filtering_option.py +0 -0
  74. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/api/models/compute_fleet_status.py +0 -0
  75. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/api/models/config_validation_message.py +0 -0
  76. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/api/models/conflict_exception_response_content.py +0 -0
  77. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/api/models/create_cluster_bad_request_exception_response_content.py +0 -0
  78. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/api/models/create_cluster_request_content.py +0 -0
  79. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/api/models/create_cluster_response_content.py +0 -0
  80. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/api/models/delete_cluster_response_content.py +0 -0
  81. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/api/models/delete_image_response_content.py +0 -0
  82. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/api/models/describe_cluster_instances_response_content.py +0 -0
  83. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/api/models/describe_cluster_response_content.py +0 -0
  84. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/api/models/describe_compute_fleet_response_content.py +0 -0
  85. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/api/models/describe_image_response_content.py +0 -0
  86. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/api/models/dryrun_operation_exception_response_content.py +0 -0
  87. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/api/models/ec2_ami_info.py +0 -0
  88. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/api/models/ec2_ami_info_summary.py +0 -0
  89. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/api/models/ec2_ami_state.py +0 -0
  90. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/api/models/ec2_instance.py +0 -0
  91. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/api/models/failure.py +0 -0
  92. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/api/models/get_cluster_log_events_response_content.py +0 -0
  93. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/api/models/get_cluster_stack_events_response_content.py +0 -0
  94. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/api/models/get_image_log_events_response_content.py +0 -0
  95. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/api/models/get_image_stack_events_response_content.py +0 -0
  96. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/api/models/image_build_status.py +0 -0
  97. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/api/models/image_builder_image_status.py +0 -0
  98. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/api/models/image_configuration_structure.py +0 -0
  99. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/api/models/image_info_summary.py +0 -0
  100. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/api/models/image_status_filtering_option.py +0 -0
  101. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/api/models/instance_state.py +0 -0
  102. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/api/models/internal_service_exception_response_content.py +0 -0
  103. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/api/models/limit_exceeded_exception_response_content.py +0 -0
  104. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/api/models/list_cluster_log_streams_response_content.py +0 -0
  105. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/api/models/list_clusters_response_content.py +0 -0
  106. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/api/models/list_image_log_streams_response_content.py +0 -0
  107. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/api/models/list_images_response_content.py +0 -0
  108. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/api/models/list_official_images_response_content.py +0 -0
  109. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/api/models/log_event.py +0 -0
  110. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/api/models/log_stream.py +0 -0
  111. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/api/models/login_nodes_pool.py +0 -0
  112. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/api/models/login_nodes_state.py +0 -0
  113. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/api/models/metadata.py +0 -0
  114. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/api/models/node_type.py +0 -0
  115. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/api/models/not_found_exception_response_content.py +0 -0
  116. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/api/models/requested_compute_fleet_status.py +0 -0
  117. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/api/models/scheduler.py +0 -0
  118. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/api/models/stack_event.py +0 -0
  119. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/api/models/tag.py +0 -0
  120. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/api/models/unauthorized_client_error_response_content.py +0 -0
  121. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/api/models/update_cluster_bad_request_exception_response_content.py +0 -0
  122. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/api/models/update_cluster_request_content.py +0 -0
  123. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/api/models/update_cluster_response_content.py +0 -0
  124. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/api/models/update_compute_fleet_request_content.py +0 -0
  125. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/api/models/update_compute_fleet_response_content.py +0 -0
  126. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/api/models/update_error.py +0 -0
  127. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/api/models/validation_level.py +0 -0
  128. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/api/openapi/__init__.py +0 -0
  129. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/api/typing_utils.py +0 -0
  130. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/api/util.py +0 -0
  131. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/aws/__init__.py +0 -0
  132. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/aws/aws_api.py +0 -0
  133. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/aws/batch.py +0 -0
  134. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/aws/cfn.py +0 -0
  135. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/aws/common.py +0 -0
  136. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/aws/dynamo.py +0 -0
  137. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/aws/efs.py +0 -0
  138. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/aws/elb.py +0 -0
  139. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/aws/fsx.py +0 -0
  140. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/aws/iam.py +0 -0
  141. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/aws/imagebuilder.py +0 -0
  142. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/aws/kms.py +0 -0
  143. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/aws/logs.py +0 -0
  144. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/aws/resource_groups.py +0 -0
  145. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/aws/route53.py +0 -0
  146. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/aws/s3_resource.py +0 -0
  147. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/aws/secretsmanager.py +0 -0
  148. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/aws/ssm.py +0 -0
  149. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/aws/sts.py +0 -0
  150. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/cli/__init__.py +0 -0
  151. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/cli/commands/__init__.py +0 -0
  152. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/cli/commands/cluster_logs.py +0 -0
  153. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/cli/commands/commands.py +0 -0
  154. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/cli/commands/common.py +0 -0
  155. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/cli/commands/configure/__init__.py +0 -0
  156. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/cli/commands/configure/command.py +0 -0
  157. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/cli/commands/configure/networking.py +0 -0
  158. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/cli/commands/configure/subnet_computation.py +0 -0
  159. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/cli/commands/configure/utils.py +0 -0
  160. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/cli/commands/dcv_connect.py +0 -0
  161. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/cli/commands/dcv_util.py +0 -0
  162. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/cli/commands/image_logs.py +0 -0
  163. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/cli/commands/version.py +0 -0
  164. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/cli/entrypoint.py +0 -0
  165. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/cli/exceptions.py +0 -0
  166. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/cli/logger.py +0 -0
  167. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/cli/middleware.py +0 -0
  168. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/config/__init__.py +0 -0
  169. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/config/common.py +0 -0
  170. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/config/config_patch.py +0 -0
  171. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/config/imagebuilder_config.py +0 -0
  172. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/config/update_policy_utils.py +0 -0
  173. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/imagebuilder_utils.py +0 -0
  174. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/launch_template_utils.py +0 -0
  175. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/lib/__init__.py +0 -0
  176. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/lib/lib.py +0 -0
  177. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/models/__init__.py +0 -0
  178. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/models/cluster.py +0 -0
  179. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/models/cluster_resources.py +0 -0
  180. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/models/common.py +0 -0
  181. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/models/compute_fleet_status_manager.py +0 -0
  182. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/models/imagebuilder.py +0 -0
  183. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/models/imagebuilder_resources.py +0 -0
  184. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/models/login_nodes_status.py +0 -0
  185. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/networking/__init__.py +0 -0
  186. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/networking/vpc_factory.py +0 -0
  187. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/resources/batch/docker/alinux2/Dockerfile +0 -0
  188. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/resources/batch/docker/alinux2023/Dockerfile +0 -0
  189. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/resources/batch/docker/build-docker-images.sh +0 -0
  190. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/resources/batch/docker/buildspec.yml +0 -0
  191. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/resources/batch/docker/scripts/entrypoint.sh +0 -0
  192. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/resources/batch/docker/scripts/generate_hostfile.sh +0 -0
  193. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/resources/batch/docker/scripts/modify_yum_vars.sh +0 -0
  194. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/resources/batch/docker/scripts/mount_efs.sh +0 -0
  195. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/resources/batch/docker/scripts/mount_nfs.sh +0 -0
  196. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/resources/batch/docker/upload-docker-images.sh +0 -0
  197. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/resources/custom_resources/custom_resources_code/__init__.py +0 -0
  198. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/resources/custom_resources/custom_resources_code/cleanup_resources.py +0 -0
  199. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/resources/custom_resources/custom_resources_code/crhelper/LICENSE +0 -0
  200. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/resources/custom_resources/custom_resources_code/crhelper/NOTICE +0 -0
  201. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/resources/custom_resources/custom_resources_code/crhelper/__init__.py +0 -0
  202. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/resources/custom_resources/custom_resources_code/crhelper/log_helper.py +0 -0
  203. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/resources/custom_resources/custom_resources_code/crhelper/resource_helper.py +0 -0
  204. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/resources/custom_resources/custom_resources_code/crhelper/utils.py +0 -0
  205. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/resources/custom_resources/custom_resources_code/delete_image_stack.py +0 -0
  206. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/resources/custom_resources/custom_resources_code/manage_docker_images.py +0 -0
  207. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/resources/custom_resources/custom_resources_code/send_build_notification.py +0 -0
  208. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/resources/imagebuilder/custom_script.yaml +0 -0
  209. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/resources/imagebuilder/parallelcluster_tag.yaml +0 -0
  210. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/resources/imagebuilder/parallelcluster_validate.yaml +0 -0
  211. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/resources/imagebuilder/update_and_reboot.yaml +0 -0
  212. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/resources/supported-regions +0 -0
  213. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/schemas/__init__.py +0 -0
  214. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/schemas/imagebuilder_schema.py +0 -0
  215. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/templates/__init__.py +0 -0
  216. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/templates/awsbatch_builder.py +0 -0
  217. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/templates/cdk_artifacts_manager.py +0 -0
  218. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/templates/cdk_builder.py +0 -0
  219. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/templates/cdk_builder_utils.py +0 -0
  220. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/templates/compute_fleet_stack.py +0 -0
  221. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/templates/imagebuilder_stack.py +0 -0
  222. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/templates/import_cdk.py +0 -0
  223. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/templates/slurm_builder.py +0 -0
  224. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/validators/__init__.py +0 -0
  225. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/validators/awsbatch_validators.py +0 -0
  226. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/validators/common.py +0 -0
  227. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/validators/database_validators.py +0 -0
  228. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/validators/directory_service_validators.py +0 -0
  229. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/validators/ebs_validators.py +0 -0
  230. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/validators/efs_validators.py +0 -0
  231. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/validators/feature_validators.py +0 -0
  232. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/validators/fsx_validators.py +0 -0
  233. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/validators/iam_validators.py +0 -0
  234. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/validators/imagebuilder_validators.py +0 -0
  235. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/validators/kms_validators.py +0 -0
  236. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/validators/monitoring_validators.py +0 -0
  237. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/validators/networking_validators.py +0 -0
  238. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/validators/s3_validators.py +0 -0
  239. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/validators/secret_validators.py +0 -0
  240. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/validators/slurm_settings_validator.py +0 -0
  241. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/validators/tags_validators.py +0 -0
  242. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster/validators/utils.py +0 -0
  243. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster3_config_converter/__init__.py +0 -0
  244. {aws_parallelcluster-3.14.2 → aws_parallelcluster-3.15.1}/src/pcluster3_config_converter/pcluster3_config_converter.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aws-parallelcluster
3
- Version: 3.14.2
3
+ Version: 3.15.1
4
4
  Summary: AWS ParallelCluster is an AWS supported Open Source cluster management tool to deploy and manage HPC clusters in the AWS cloud.
5
5
  Home-page: https://github.com/aws/aws-parallelcluster
6
6
  Author: Amazon Web Services
@@ -21,7 +21,7 @@ Classifier: License :: OSI Approved :: Apache Software License
21
21
  Requires-Python: >=3.9
22
22
  Requires-Dist: setuptools
23
23
  Requires-Dist: boto3>=1.39.4
24
- Requires-Dist: tabulate<=0.8.10,>=0.8.8
24
+ Requires-Dist: tabulate<=0.9.0,>=0.8.8
25
25
  Requires-Dist: PyYAML!=5.4,>=5.3.1
26
26
  Requires-Dist: jinja2~=3.0
27
27
  Requires-Dist: marshmallow~=3.10
@@ -44,7 +44,7 @@ Requires-Dist: aws-cdk.aws-ssm~=1.164
44
44
  Requires-Dist: aws-cdk.aws-sqs~=1.164
45
45
  Requires-Dist: aws-cdk.aws-cloudformation~=1.164
46
46
  Requires-Dist: connexion~=2.15.1
47
- Requires-Dist: jmespath~=0.10
47
+ Requires-Dist: jmespath~=1.0
48
48
  Requires-Dist: jsii==1.85.0
49
49
  Requires-Dist: werkzeug~=3.1
50
50
  Requires-Dist: flask~=3.1.0
@@ -20,12 +20,12 @@ def readme():
20
20
  return f.read()
21
21
 
22
22
 
23
- VERSION = "3.14.2"
23
+ VERSION = "3.15.1"
24
24
  CDK_VERSION = "1.164"
25
25
  REQUIRES = [
26
26
  "setuptools",
27
27
  "boto3>=1.39.4",
28
- "tabulate>=0.8.8,<=0.8.10",
28
+ "tabulate>=0.8.8,<=0.9.0",
29
29
  "PyYAML>=5.3.1,!=5.4",
30
30
  "jinja2~=3.0",
31
31
  "marshmallow~=3.10",
@@ -48,7 +48,7 @@ REQUIRES = [
48
48
  "aws-cdk.aws-sqs~=" + CDK_VERSION,
49
49
  "aws-cdk.aws-cloudformation~=" + CDK_VERSION,
50
50
  "connexion~=2.15.1",
51
- "jmespath~=0.10",
51
+ "jmespath~=1.0",
52
52
  "jsii==1.85.0",
53
53
  "werkzeug~=3.1",
54
54
  "flask~=3.1.0",
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aws-parallelcluster
3
- Version: 3.14.2
3
+ Version: 3.15.1
4
4
  Summary: AWS ParallelCluster is an AWS supported Open Source cluster management tool to deploy and manage HPC clusters in the AWS cloud.
5
5
  Home-page: https://github.com/aws/aws-parallelcluster
6
6
  Author: Amazon Web Services
@@ -21,7 +21,7 @@ Classifier: License :: OSI Approved :: Apache Software License
21
21
  Requires-Python: >=3.9
22
22
  Requires-Dist: setuptools
23
23
  Requires-Dist: boto3>=1.39.4
24
- Requires-Dist: tabulate<=0.8.10,>=0.8.8
24
+ Requires-Dist: tabulate<=0.9.0,>=0.8.8
25
25
  Requires-Dist: PyYAML!=5.4,>=5.3.1
26
26
  Requires-Dist: jinja2~=3.0
27
27
  Requires-Dist: marshmallow~=3.10
@@ -44,7 +44,7 @@ Requires-Dist: aws-cdk.aws-ssm~=1.164
44
44
  Requires-Dist: aws-cdk.aws-sqs~=1.164
45
45
  Requires-Dist: aws-cdk.aws-cloudformation~=1.164
46
46
  Requires-Dist: connexion~=2.15.1
47
- Requires-Dist: jmespath~=0.10
47
+ Requires-Dist: jmespath~=1.0
48
48
  Requires-Dist: jsii==1.85.0
49
49
  Requires-Dist: werkzeug~=3.1
50
50
  Requires-Dist: flask~=3.1.0
@@ -229,7 +229,6 @@ src/pcluster/validators/iam_validators.py
229
229
  src/pcluster/validators/imagebuilder_validators.py
230
230
  src/pcluster/validators/instances_validators.py
231
231
  src/pcluster/validators/kms_validators.py
232
- src/pcluster/validators/login_nodes_validators.py
233
232
  src/pcluster/validators/monitoring_validators.py
234
233
  src/pcluster/validators/networking_validators.py
235
234
  src/pcluster/validators/s3_validators.py
@@ -1,6 +1,6 @@
1
1
  setuptools
2
2
  boto3>=1.39.4
3
- tabulate<=0.8.10,>=0.8.8
3
+ tabulate<=0.9.0,>=0.8.8
4
4
  PyYAML!=5.4,>=5.3.1
5
5
  jinja2~=3.0
6
6
  marshmallow~=3.10
@@ -23,7 +23,7 @@ aws-cdk.aws-ssm~=1.164
23
23
  aws-cdk.aws-sqs~=1.164
24
24
  aws-cdk.aws-cloudformation~=1.164
25
25
  connexion~=2.15.1
26
- jmespath~=0.10
26
+ jmespath~=1.0
27
27
  jsii==1.85.0
28
28
  werkzeug~=3.1
29
29
  flask~=3.1.0
@@ -2,7 +2,7 @@ openapi: 3.0.2
2
2
  info:
3
3
  description: ParallelCluster API
4
4
  title: ParallelCluster
5
- version: 3.14.2
5
+ version: 3.15.1
6
6
  servers:
7
7
  - url: /
8
8
  # override: auth is defined the the API GW level
@@ -268,8 +268,10 @@ class InstanceTypeInfo:
268
268
  return len(self.network_cards())
269
269
 
270
270
  def network_cards_list(self) -> list:
271
- """List of NICs for the instance."""
272
- return [NetworkCardInfo(nic) for nic in self.network_cards() if nic.get("NetworkCardIndex") is not None]
271
+ """List of NICs for the instance, sorted by NetworkCardIndex."""
272
+ cards = [NetworkCardInfo(nic) for nic in self.network_cards() if nic.get("NetworkCardIndex") is not None]
273
+ cards.sort(key=lambda c: c.network_card_index())
274
+ return cards
273
275
 
274
276
  def default_threads_per_core(self):
275
277
  """Return the default threads per core for the given instance type."""
@@ -325,6 +327,18 @@ class InstanceTypeInfo:
325
327
  """Return the amount of memory in MiB."""
326
328
  return self.instance_type_data.get("MemoryInfo", {}).get("SizeInMiB")
327
329
 
330
+ def max_efa_interfaces(self) -> int:
331
+ """Return the maximum number of EFA interfaces for the instance.
332
+
333
+ If EfaInfo/MaximumEfaInterfaces is not present in the API response (older API versions),
334
+ fall back to 1 if EfaSupported is true, 0 otherwise.
335
+ """
336
+ efa_info = self.instance_type_data.get("NetworkInfo", {}).get("EfaInfo", {})
337
+ max_efa = efa_info.get("MaximumEfaInterfaces")
338
+ if max_efa is not None:
339
+ return max_efa
340
+ return 1 if self.is_efa_supported() else 0
341
+
328
342
 
329
343
  class FsxStorageInfo:
330
344
  """Data object wrapping the result of a describe_file_systems and describe_file_caches call."""
@@ -310,8 +310,10 @@ class Ec2Client(Boto3Client):
310
310
  """Return the id of the current official image, for the provided os-architecture combination."""
311
311
  owner = filters.owner if filters and filters.owner else "amazon"
312
312
  tags = filters.tags if filters and filters.tags else []
313
+ name_prefix = filters.name_prefix if filters and filters.name_prefix else ""
314
+ name = name_prefix + "{0}*".format(self._get_official_image_name_prefix(os, architecture))
313
315
 
314
- filters = [{"Name": "name", "Values": ["{0}*".format(self._get_official_image_name_prefix(os, architecture))]}]
316
+ filters = [{"Name": "name", "Values": [name]}]
315
317
  filters.extend([{"Name": f"tag:{tag.key}", "Values": [tag.value]} for tag in tags])
316
318
  images = self._describe_images_with_pagination(Owners=[owner], Filters=filters, IncludeDeprecated=True)
317
319
  if not images:
@@ -568,7 +570,9 @@ class Ec2Client(Boto3Client):
568
570
  raise Exception(f"No subnet found with ID {subnet_id}")
569
571
  vpc_id = subnets[0].get("VpcId")
570
572
 
571
- route_tables = self.describe_route_tables(filters=[{"Name": "vpc-id", "Values": [vpc_id]}])
573
+ route_tables = self.describe_route_tables(
574
+ filters=[{"Name": "vpc-id", "Values": [vpc_id]}, {"Name": "association.main", "Values": ["true"]}]
575
+ )
572
576
  if not route_tables:
573
577
  raise Exception("No route tables found. The subnet or VPC configuration may be incorrect.")
574
578
 
@@ -679,3 +683,28 @@ class Ec2Client(Boto3Client):
679
683
  reservation_type = reservation.reservation_type()
680
684
 
681
685
  return instance_type, reservation_type
686
+
687
+ @AWSExceptionHandler.handle_client_exception
688
+ @Cache.cached
689
+ def describe_launch_template_version(self, launch_template_id: str, version: str):
690
+ """
691
+ Describe a launch template version and return its data.
692
+
693
+ Args:
694
+ launch_template_id: The launch template ID (e.g., 'lt-0abc123def456')
695
+ version: The version number or '$Default'/'$Latest'
696
+
697
+ Returns:
698
+ dict: The LaunchTemplateData from the specified version
699
+ """
700
+ response = self._client.describe_launch_template_versions(
701
+ LaunchTemplateId=launch_template_id,
702
+ Versions=[version],
703
+ )
704
+ versions = response.get("LaunchTemplateVersions", [])
705
+ if versions:
706
+ return versions[0].get("LaunchTemplateData", {})
707
+ raise AWSClientError(
708
+ function_name="describe_launch_template_versions",
709
+ message=f"Launch template {launch_template_id} version {version} not found",
710
+ )
@@ -39,14 +39,17 @@ class S3Client(Boto3Client):
39
39
  error_code=client_error.response["Error"]["Code"],
40
40
  )
41
41
 
42
- def head_bucket(self, bucket_name):
42
+ def head_bucket(self, bucket_name, expected_bucket_owner=None):
43
43
  """Retrieve metadata for a bucket without returning the object itself."""
44
44
  try:
45
- return self._client.head_bucket(Bucket=bucket_name)
45
+ if expected_bucket_owner:
46
+ return self._client.head_bucket(Bucket=bucket_name, ExpectedBucketOwner=expected_bucket_owner)
47
+ else:
48
+ return self._client.head_bucket(Bucket=bucket_name)
46
49
  except ClientError as client_error:
47
50
  raise AWSClientError(
48
51
  function_name="head_bucket",
49
- message=_process_s3_bucket_error(client_error, bucket_name),
52
+ message=_process_s3_bucket_error(client_error, bucket_name, expected_bucket_owner),
50
53
  error_code=client_error.response["Error"]["Code"],
51
54
  )
52
55
 
@@ -150,6 +153,11 @@ def _process_s3_bucket_error(client_error, bucket_name, expected_bucket_owner=No
150
153
  f"Failed when accessing object '{object_name}' from bucket '{bucket_name}'. This can be due to "
151
154
  f"bucket owner not matching the expected one '{expected_bucket_owner}'"
152
155
  )
156
+ elif expected_bucket_owner and error_code == "403" and error_message == "Forbidden":
157
+ message = (
158
+ f"Failed in accessing bucket '{bucket_name}'. This can be due to "
159
+ f"bucket owner not matching the expected one '{expected_bucket_owner}'"
160
+ )
153
161
  elif object_name and error_code == "404" and error_message == "Not Found":
154
162
  message = (
155
163
  f"Failed when accessing object '{object_name}' from bucket '{bucket_name}'. This can be due to "
@@ -177,9 +177,9 @@ def configure(args): # noqa: C901
177
177
  for queue_index in range(number_of_queues):
178
178
  while True:
179
179
  queue_name = prompt(
180
- f"Name of queue {queue_index+1}",
180
+ f"Name of queue {queue_index + 1}",
181
181
  validator=lambda x: len(NameValidator().execute(x)) == 0,
182
- default_value=f"queue{queue_index+1}",
182
+ default_value=f"queue{queue_index + 1}",
183
183
  )
184
184
  if queue_name not in queue_names:
185
185
  break
@@ -208,7 +208,7 @@ def configure(args): # noqa: C901
208
208
  if scheduler != "awsbatch":
209
209
  while True:
210
210
  compute_instance_type = prompt(
211
- f"Compute instance type for compute resource {compute_resource_index+1} in {queue_name}",
211
+ f"Compute instance type for compute resource {compute_resource_index + 1} in {queue_name}",
212
212
  validator=lambda x: x in AWSApi.instance().ec2.list_instance_types(),
213
213
  default_value=default_instance_type,
214
214
  )
@@ -79,15 +79,13 @@ class SshCommand(CliCommand):
79
79
  "Run ssh command with the cluster username and IP address pre-populated. "
80
80
  "Arbitrary arguments are appended to the end of the ssh command."
81
81
  )
82
- epilog = textwrap.dedent(
83
- """Example:
82
+ epilog = textwrap.dedent("""Example:
84
83
 
85
84
  pcluster ssh --cluster-name mycluster -i ~/.ssh/id_rsa
86
85
 
87
86
  Returns an ssh command with the cluster username and IP address pre-populated:
88
87
 
89
- ssh ec2-user@1.1.1.1 -i ~/.ssh/id_rsa"""
90
- )
88
+ ssh ec2-user@1.1.1.1 -i ~/.ssh/id_rsa""")
91
89
 
92
90
  def __init__(self, subparsers):
93
91
  super().__init__(
@@ -20,12 +20,6 @@ from pcluster.api import encoder, openapi
20
20
  from pcluster.cli.exceptions import APIOperationException
21
21
  from pcluster.utils import to_kebab_case, to_snake_case, yaml_load
22
22
 
23
- # For importing package resources
24
- try:
25
- import importlib.resources as pkg_resources # pylint: disable=ungrouped-imports # nosem
26
- except ImportError:
27
- import importlib_resources as pkg_resources
28
-
29
23
 
30
24
  def _param_overrides(operation, param):
31
25
  """Provide updates to the model that are specific to the CLI."""
@@ -88,7 +82,7 @@ def _resolve_body(spec, operation):
88
82
 
89
83
  def package_spec():
90
84
  """Load the OpenAPI specification from the package."""
91
- with pkg_resources.open_text(openapi, "openapi.yaml") as spec_file: # pylint: disable=deprecated-method
85
+ with importlib.resources.open_text(openapi, "openapi.yaml") as spec_file: # pylint: disable=deprecated-method
92
86
  return yaml_load(spec_file.read())
93
87
 
94
88
 
@@ -188,9 +188,9 @@ from pcluster.validators.instances_validators import (
188
188
  InstancesEFAValidator,
189
189
  InstancesMemorySchedulingWarningValidator,
190
190
  InstancesNetworkingValidator,
191
+ LaunchTemplateValidator,
191
192
  )
192
193
  from pcluster.validators.kms_validators import KmsKeyIdEncryptedValidator, KmsKeyValidator
193
- from pcluster.validators.login_nodes_validators import LoginNodesSshKeyNameDeprecatedValidator
194
194
  from pcluster.validators.monitoring_validators import DetailedMonitoringValidator, LogRotationValidator
195
195
  from pcluster.validators.networking_validators import (
196
196
  ElasticIpValidator,
@@ -842,25 +842,14 @@ class HeadNodeSsh(_BaseSsh):
842
842
  self.allowed_ips = Resource.init_param(allowed_ips, default=CIDR_ALL_IPS)
843
843
 
844
844
 
845
- class LoginNodesSsh(_BaseSsh):
845
+ class LoginNodesSsh(Resource):
846
846
  """Represent the SSH configuration for LoginNodes."""
847
847
 
848
848
  def __init__(self, allowed_ips: str = None, **kwargs):
849
- key_name_explicitly_set = kwargs.pop("key_name_explicitly_set", False)
850
849
  super().__init__(**kwargs)
851
850
  # If AllowedIPs is not specified for the login node pool, then allowed_ips will default to the same settings
852
851
  # in the HeadNode to restrict SSH access from a specific CIDR or prefix-list.
853
852
  self.allowed_ips = Resource.init_param(allowed_ips)
854
- # Track whether the key_name was explicitly set in the configuration.
855
- self._key_name_explicitly_set = key_name_explicitly_set
856
-
857
- def _register_validators(self, context=None):
858
- super()._register_validators(context)
859
- self._register_validator(
860
- LoginNodesSshKeyNameDeprecatedValidator,
861
- key_name=self.key_name,
862
- key_name_explicitly_set=self._key_name_explicitly_set,
863
- )
864
853
 
865
854
 
866
855
  class SharedStorageEfsSettings(Resource):
@@ -890,6 +879,15 @@ class Efa(Resource):
890
879
  self.gdr_support = Resource.init_param(gdr_support, default=False)
891
880
 
892
881
 
882
+ class LaunchTemplateOverrides(Resource):
883
+ """Represent the Launch Template Overrides configuration."""
884
+
885
+ def __init__(self, launch_template_id: str = None, version: int = None, **kwargs):
886
+ super().__init__(**kwargs)
887
+ self.launch_template_id = Resource.init_param(launch_template_id)
888
+ self.version = Resource.init_param(version)
889
+
890
+
893
891
  # ---------------------- Health Checks ---------------------- #
894
892
 
895
893
 
@@ -1199,10 +1197,11 @@ class AdditionalPackages(Resource):
1199
1197
  class AmiSearchFilters(Resource):
1200
1198
  """Represent the configuration for AMI search filters."""
1201
1199
 
1202
- def __init__(self, tags: List[Tag] = None, owner: str = None):
1200
+ def __init__(self, tags: List[Tag] = None, owner: str = None, name_prefix: str = None):
1203
1201
  super().__init__()
1204
1202
  self.tags = tags
1205
1203
  self.owner = owner
1204
+ self.name_prefix = name_prefix
1206
1205
 
1207
1206
 
1208
1207
  class Timeouts(Resource):
@@ -1237,6 +1236,7 @@ class ClusterDevSettings(BaseDevSettings):
1237
1236
  instance_types_data: str = None,
1238
1237
  timeouts: Timeouts = None,
1239
1238
  compute_startup_time_metric_enabled: bool = None,
1239
+ efa_interface_type: str = None,
1240
1240
  **kwargs,
1241
1241
  ):
1242
1242
  super().__init__(**kwargs)
@@ -1247,6 +1247,7 @@ class ClusterDevSettings(BaseDevSettings):
1247
1247
  self.compute_startup_time_metric_enabled = Resource.init_param(
1248
1248
  compute_startup_time_metric_enabled, default=False
1249
1249
  )
1250
+ self.efa_interface_type = Resource.init_param(efa_interface_type)
1250
1251
 
1251
1252
  def _register_validators(self, context: ValidatorContext = None):
1252
1253
  super()._register_validators(context)
@@ -2239,6 +2240,7 @@ class _BaseSlurmComputeResource(BaseComputeResource):
2239
2240
  tags: List[Tag] = None,
2240
2241
  static_node_priority: int = None,
2241
2242
  dynamic_node_priority: int = None,
2243
+ launch_template_overrides: LaunchTemplateOverrides = None,
2242
2244
  **kwargs,
2243
2245
  ):
2244
2246
  super().__init__(**kwargs)
@@ -2259,6 +2261,7 @@ class _BaseSlurmComputeResource(BaseComputeResource):
2259
2261
  self.tags = tags
2260
2262
  self.static_node_priority = Resource.init_param(static_node_priority, default=1)
2261
2263
  self.dynamic_node_priority = Resource.init_param(dynamic_node_priority, default=1000)
2264
+ self.launch_template_overrides = launch_template_overrides
2262
2265
 
2263
2266
  @abstractmethod
2264
2267
  def is_flexible(self) -> bool:
@@ -2303,6 +2306,11 @@ class _BaseSlurmComputeResource(BaseComputeResource):
2303
2306
  def max_network_cards(self) -> int:
2304
2307
  """Return max number of NICs for the instance."""
2305
2308
 
2309
+ @property
2310
+ @abstractmethod
2311
+ def max_efa_interfaces(self) -> int:
2312
+ """Return max number of EFA interfaces for the instance."""
2313
+
2306
2314
  @property
2307
2315
  @abstractmethod
2308
2316
  def network_cards_list(self) -> list:
@@ -2361,6 +2369,13 @@ class SlurmFlexibleComputeResource(_BaseSlurmComputeResource):
2361
2369
  ec2memory=min_memory,
2362
2370
  instance_type=smallest_type,
2363
2371
  )
2372
+ if self.launch_template_overrides:
2373
+ self._register_validator(
2374
+ LaunchTemplateValidator,
2375
+ compute_resource_name=self.name,
2376
+ launch_template_id=self.launch_template_overrides.launch_template_id,
2377
+ launch_template_version=self.launch_template_overrides.version,
2378
+ )
2364
2379
 
2365
2380
  def is_flexible(self):
2366
2381
  """Return True because the ComputeResource can contain multiple instance types."""
@@ -2387,6 +2402,11 @@ class SlurmFlexibleComputeResource(_BaseSlurmComputeResource):
2387
2402
  least_max_nics = min(least_max_nics, max_nics)
2388
2403
  return least_max_nics
2389
2404
 
2405
+ @property
2406
+ def max_efa_interfaces(self) -> int:
2407
+ """Return max number of EFA interfaces for the compute resource."""
2408
+ return min(self.instance_type_info_map[it].max_efa_interfaces() for it in self.instance_types)
2409
+
2390
2410
  @property
2391
2411
  def network_cards_list(self) -> list:
2392
2412
  """Return the list of NIC indexes for the compute resource.
@@ -2448,6 +2468,13 @@ class SlurmComputeResource(_BaseSlurmComputeResource):
2448
2468
  ec2memory=self._instance_type_info.ec2memory_size_in_mib(),
2449
2469
  instance_type=self.instance_type,
2450
2470
  )
2471
+ if self.launch_template_overrides:
2472
+ self._register_validator(
2473
+ LaunchTemplateValidator,
2474
+ compute_resource_name=self.name,
2475
+ launch_template_id=self.launch_template_overrides.launch_template_id,
2476
+ launch_template_version=self.launch_template_overrides.version,
2477
+ )
2451
2478
 
2452
2479
  @property
2453
2480
  def architecture(self) -> str:
@@ -2464,6 +2491,11 @@ class SlurmComputeResource(_BaseSlurmComputeResource):
2464
2491
  """Return max number of NICs for the instance."""
2465
2492
  return self._instance_type_info.max_network_cards()
2466
2493
 
2494
+ @property
2495
+ def max_efa_interfaces(self) -> int:
2496
+ """Return max number of EFA interfaces for the instance."""
2497
+ return self._instance_type_info.max_efa_interfaces()
2498
+
2467
2499
  @property
2468
2500
  def network_cards_list(self) -> list:
2469
2501
  """List of NIC indexes for the instance."""
@@ -2706,6 +2738,7 @@ class SlurmQueue(_CommonQueue):
2706
2738
  is False,
2707
2739
  multi_az_enabled=self.multi_az_enabled,
2708
2740
  capacity_type=self.capacity_type,
2741
+ queue_name=self.name,
2709
2742
  )
2710
2743
  self._register_validator(
2711
2744
  ComputeResourceSizeValidator,
@@ -2936,16 +2969,9 @@ class SlurmClusterConfig(BaseClusterConfig):
2936
2969
  # Create a LocalStorage for the LoginNodesPool and ensure that encrypted = true
2937
2970
  for pool in self.login_nodes.pools:
2938
2971
  pool.local_storage = LocalStorage(implied=True)
2939
- # If there's no customer ssh key for LoginNodes pool, set a default value as HeadNode's ssh key
2940
- if pool.ssh and not pool.ssh.key_name:
2941
- pool.ssh.key_name = self.head_node.ssh.key_name
2942
- # Mark that this key was not explicitly set by the user
2943
- pool.ssh._key_name_explicitly_set = False
2944
- elif not pool.ssh:
2945
- pool.ssh = LoginNodesSsh(key_name=self.head_node.ssh.key_name, key_name_explicitly_set=False)
2946
- else:
2947
- # SSH config exists and has a key_name, mark it as explicitly set
2948
- pool.ssh._key_name_explicitly_set = True
2972
+ # If the login node pool SSH config is not specified, create one
2973
+ if not pool.ssh:
2974
+ pool.ssh = LoginNodesSsh()
2949
2975
  # If the login node pool allowed IPs is not specified, forces the source allowed IP for the
2950
2976
  # SSH connection to the one defined in the HeadNode
2951
2977
  if not pool.ssh.allowed_ips:
@@ -3211,7 +3237,6 @@ class SlurmClusterConfig(BaseClusterConfig):
3211
3237
  subnet=queue.networking.subnet_ids[0],
3212
3238
  instance_types=compute_resource.instance_types,
3213
3239
  multi_az_enabled=queue.multi_az_enabled,
3214
- subnet_id_az_mapping=queue.networking.subnet_id_az_mapping,
3215
3240
  )
3216
3241
  for instance_type in compute_resource.instance_types:
3217
3242
  if self.scheduling.settings.enable_memory_based_scheduling:
@@ -11,6 +11,7 @@
11
11
  import re
12
12
  from enum import Enum
13
13
 
14
+ from pcluster.aws.common import get_region
14
15
  from pcluster.config.cluster_config import QueueUpdateStrategy
15
16
  from pcluster.config.update_policy_utils import SharedStorageChangeInfo
16
17
  from pcluster.constants import (
@@ -20,6 +21,7 @@ from pcluster.constants import (
20
21
  SLURM,
21
22
  STORAGE_TYPES_SUPPORTING_LIVE_UPDATES,
22
23
  )
24
+ from pcluster.utils import get_dictionary_diff, parse_json_string
23
25
 
24
26
 
25
27
  class UpdatePolicy:
@@ -148,6 +150,12 @@ def is_slurm_queues_change(change):
148
150
  return any(path.startswith("SlurmQueues[") for path in change.path)
149
151
 
150
152
 
153
+ def _is_adc_region():
154
+ """Return True if the currently configured AWS region belongs to an ADC partition."""
155
+ region = get_region() or ""
156
+ return region.startswith("us-iso")
157
+
158
+
151
159
  def extract_type_and_name_from_path(path):
152
160
  # Example path = 'SlurmQueues[slurm-q-name]'
153
161
  # This function returns the type and name extracted like this: 'SlurmQueues', 'slurm-q-name'
@@ -510,6 +518,40 @@ def get_pool_name_from_change_paths(change):
510
518
  return ""
511
519
 
512
520
 
521
+ # ExtraChefAttributes update policy helpers
522
+ # Define which paths within ExtraChefAttributes JSON are updatable (dot-notation)
523
+ # IMPORTANT: We assume this set to contain the path to leaf fields.
524
+ EXTRA_CHEF_ATTRIBUTES_UPDATABLE_PATHS: set[str] = {
525
+ "cluster.slurm.reconfigure_timeout",
526
+ "cluster.cluster_readiness_check_enabled",
527
+ "cluster.cluster_readiness_check_ignore_failure",
528
+ }
529
+
530
+
531
+ def _get_non_updatable_changes(old_value: str, new_value: str) -> list[str]:
532
+ """Parse and compare two ExtraChefAttributes JSON strings, returning paths that are not updatable."""
533
+ old_attrs = parse_json_string(old_value, raise_on_error=False, default={}) if old_value else {}
534
+ new_attrs = parse_json_string(new_value, raise_on_error=False, default={}) if new_value else {}
535
+
536
+ return [p for p in get_dictionary_diff(old_attrs, new_attrs) if p not in EXTRA_CHEF_ATTRIBUTES_UPDATABLE_PATHS]
537
+
538
+
539
+ def condition_checker_extra_chef_attributes(change, _) -> bool:
540
+ """
541
+ Check if ExtraChefAttributes changes are allowed.
542
+
543
+ Only changes to paths defined in EXTRA_CHEF_ATTRIBUTES_UPDATABLE_PATHS are allowed.
544
+ """
545
+ return len(_get_non_updatable_changes(change.old_value, change.new_value)) == 0
546
+
547
+
548
+ def fail_reason_extra_chef_attributes(change, _) -> str:
549
+ """Generate fail reason for ExtraChefAttributes update."""
550
+ non_updatable_changes = _get_non_updatable_changes(change.old_value, change.new_value)
551
+ paths_str = ", ".join(sorted(non_updatable_changes))
552
+ return f"The following ExtraChefAttributes fields cannot be updated: {paths_str}"
553
+
554
+
513
555
  # Common fail_reason messages
514
556
  UpdatePolicy.FAIL_REASONS = {
515
557
  "ebs_volume_resize": "Updating the file system after a resize operation requires commands specific to your "
@@ -526,6 +568,7 @@ UpdatePolicy.FAIL_REASONS = {
526
568
  "compute_or_login_nodes_running": lambda change, patch: (
527
569
  "The update is not supported when compute or login nodes are running"
528
570
  ),
571
+ "extra_chef_attributes_update": fail_reason_extra_chef_attributes,
529
572
  }
530
573
 
531
574
  # Common action_needed messages
@@ -548,6 +591,9 @@ UpdatePolicy.ACTIONS_NEEDED = {
548
591
  "Stop the login nodes by setting Count parameter to 0 "
549
592
  "and update the cluster with the pcluster update-cluster command"
550
593
  ),
594
+ "extra_chef_attributes_update": lambda change, patch: (
595
+ "Revert the non-updatable ExtraChefAttributes fields to their original values."
596
+ ),
551
597
  }
552
598
 
553
599
  # Base policies
@@ -567,6 +613,15 @@ UpdatePolicy.SUPPORTED = UpdatePolicy(
567
613
  name="SUPPORTED", level=0, fail_reason="-", condition_checker=(lambda change, patch: True)
568
614
  )
569
615
 
616
+ # Update policy for ExtraChefAttributes - allows updates to specific fields only
617
+ UpdatePolicy.EXTRA_CHEF_ATTRIBUTES = UpdatePolicy(
618
+ name="EXTRA_CHEF_ATTRIBUTES",
619
+ level=5,
620
+ fail_reason=UpdatePolicy.FAIL_REASONS["extra_chef_attributes_update"],
621
+ action_needed=UpdatePolicy.ACTIONS_NEEDED["extra_chef_attributes_update"],
622
+ condition_checker=condition_checker_extra_chef_attributes,
623
+ )
624
+
570
625
  # Checks resize of max_vcpus in Batch Compute Environment
571
626
  UpdatePolicy.AWSBATCH_CE_MAX_RESIZE = UpdatePolicy(
572
627
  name="AWSBATCH_CE_MAX_RESIZE",
@@ -682,6 +737,25 @@ UpdatePolicy.UNSUPPORTED = UpdatePolicy(
682
737
  + ". If you need this change, please consider creating a new cluster instead of updating the existing one.",
683
738
  )
684
739
 
740
+ # Update supported everywhere except ADC regions (us-iso*, us-isob*).
741
+ #
742
+ # In ADC regions there is a CloudFormation behavior where an UpdateStack call that includes
743
+ # both a Tags change and a resource whose change is only in Metadata does not update that
744
+ # resource. This breaks the head node update flow because cfn-hup on the head node polls
745
+ # DescribeStackResource for Metadata changes on HeadNodeLaunchTemplate and never sees them,
746
+ # leaving the HeadNodeWaitCondition to time out.
747
+ #
748
+ # Until the CloudFormation behavior is fixed in ADC, block tag updates in those regions.
749
+ UpdatePolicy.SUPPORTED_UNLESS_ADC = UpdatePolicy(
750
+ name="SUPPORTED_UNLESS_ADC",
751
+ level=1000,
752
+ fail_reason=lambda change, patch: (
753
+ f"Updating '{change.key}' during a cluster update is not supported in ADC regions."
754
+ ),
755
+ action_needed=lambda change, patch: f"Restore '{change.key}' to its previous value.",
756
+ condition_checker=lambda change, patch: not _is_adc_region(),
757
+ )
758
+
685
759
  # Block update if cluster has a managed Fsx for Lustre FileSystem, otherwise fallback to QueueUpdateStrategy
686
760
  UpdatePolicy.MANAGED_FSX = UpdatePolicy(
687
761
  name="MANAGED_FSX",