diff --git a/CHANGELOG.md b/CHANGELOG.md
index fc955eb8..88caedf8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,14 @@
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).
+## [2.3.0] - 2023-11-25
+### Added
+- Added support for Azure Stateful Node APIs: `swap_os_disk_to_stateful_node`, `get_all_stateful_node_costs`,
+`get_all_stateful_node_aggregated_daily_costs`, `get_stateful_node_size_usage`.
+
+### Fixed
+- Updated fields in all Azure Stateful Node model classes as per latest schema.
+
## [2.2.2] - 2023-11-20
### Fixed
- Passing query parameters in `delete_virtual_node_group` API for AWS Ocean.
@@ -37,7 +45,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
## [2.1.40] - 2023-07-31
### Added
- Add support for GCP Eastigroup APIs: `get_elastilog`, `get_cost_per_account`, `get_instance_status`,
-- `lock_instance`, `unlock_instance`
+`lock_instance`, `unlock_instance`
## [2.1.39] - 2023-07-17
### Added
diff --git a/docs/clients/stateful_node/stateful_node_azure_client.md b/docs/clients/stateful_node/stateful_node_azure_client.md
index c5779d36..d3a09e3d 100644
--- a/docs/clients/stateful_node/stateful_node_azure_client.md
+++ b/docs/clients/stateful_node/stateful_node_azure_client.md
@@ -83,7 +83,8 @@ __Returns__
get_all_stateful_nodes
```python
-StatefulNodeAzureClient.get_all_stateful_nodes()
+StatefulNodeAzureClient.get_all_stateful_nodes(name: str = None,
+ region: str = None)
```
Get all Stateful Nodes
@@ -267,3 +268,78 @@ __Returns__
`(Object)`: Stateful Node API response
+swap_os_disk_to_stateful_node
+
+```python
+StatefulNodeAzureClient.swap_os_disk_to_stateful_node(
+ node_id: str, swap_osdisk_configuration: SwapOsDiskConfiguration)
+```
+
+Configure a new managed OS disk for an OS persisted paused Stateful Node
+
+__Arguments__
+
+- __node_id (String)__: Stateful Node ID
+- __swap_osdisk_configuration (SwapOsDiskConfiguration)__: Configuration of OS Disk
+
+__Returns__
+
+`(Object)`: StatefulNode API response
+
+get_all_stateful_node_costs
+
+```python
+StatefulNodeAzureClient.get_all_stateful_node_costs(
+ from_date: str, to_date: str, owner_id: str = None)
+```
+
+Get the total costs of a single stateful node/all stateful nodes and for a specific time period.
+
+__Arguments__
+
+- __to_date (String)__: On or Before this date
+- __from_date (String)__: On or After this date
+- __ownerId (String) (Optional)__: Log level severity
+
+__Returns__
+
+`(Object)`: Stateful Node API response
+
+get_all_stateful_node_aggregated_daily_costs
+
+```python
+StatefulNodeAzureClient.get_all_stateful_node_aggregated_daily_costs(
+ from_date: str, to_date: str, owner_id: str = None)
+```
+
+Get the total costs per day of a single stateful node/all stateful nodes and for a specific time period.
+
+__Arguments__
+
+- __to_date (String)__: On or Before this date
+- __from_date (String)__: On or After this date
+- __ownerId (String) (Optional)__: Log level severity
+
+__Returns__
+
+`(Object)`: Stateful Node API response
+
+get_stateful_node_size_usage
+
+```python
+StatefulNodeAzureClient.get_stateful_node_size_usage(
+ from_date: str, to_date: str, owner_id: str = None)
+```
+
+Get the daily costs per VM size of a single stateful node/all stateful nodes and for a specific time period.
+
+__Arguments__
+
+- __to_date (String)__: On or Before this date
+- __from_date (String)__: On or After this date
+- __ownerId (String) (Optional)__: Log level severity
+
+__Returns__
+
+`(Object)`: Stateful Node API response
+
diff --git a/docs/models/stateful_node.md b/docs/models/stateful_node.md
index 8f677edc..5c387698 100644
--- a/docs/models/stateful_node.md
+++ b/docs/models/stateful_node.md
@@ -1,13 +1,34 @@
spotinst_sdk2.models.stateful_node
+PersistenceMode
+
+```python
+PersistenceMode(cls,
+ value,
+ names=None,
+ *,
+ module,
+ qualname,
+ type,
+ start)
+```
+An enumeration.
+on_launch
+
+
+reattach
+
+
Persistence
```python
Persistence(
self,
- data_disks_persistence_mode: str = 'd3043820717d74d9a17694c176d39733',
- os_disk_persistence_mode: str = 'd3043820717d74d9a17694c176d39733',
+ data_disks_persistence_mode:
+ PersistenceMode = 'd3043820717d74d9a17694c176d39733',
+ os_disk_persistence_mode:
+ PersistenceMode = 'd3043820717d74d9a17694c176d39733',
should_persist_data_disks: bool = 'd3043820717d74d9a17694c176d39733',
should_persist_network: bool = 'd3043820717d74d9a17694c176d39733',
should_persist_os_disk: bool = 'd3043820717d74d9a17694c176d39733')
@@ -15,44 +36,87 @@ Persistence(
__Arguments__
-- __data_disks_persistence_mode__: str
-- __os_disk_persistence_mode__: str
+- __data_disks_persistence_mode__: PersistenceMode
+- __os_disk_persistence_mode__: PersistenceMode
- __should_persist_data_disks__: bool
- __should_persist_network__: bool
- __should_persist_os_disk__: bool
+HealthCheckTypes
+
+```python
+HealthCheckTypes(cls,
+ value,
+ names=None,
+ *,
+ module,
+ qualname,
+ type,
+ start)
+```
+An enumeration.
+application_gateway
+
+
+vm_state
+
+
Health
```python
-Health(self,
- health_check_types:
- typing.List[str] = 'd3043820717d74d9a17694c176d39733',
- auto_healing: bool = 'd3043820717d74d9a17694c176d39733',
- grace_period: int = 'd3043820717d74d9a17694c176d39733',
- unhealthy_duration: int = 'd3043820717d74d9a17694c176d39733')
+Health(
+ self,
+ health_check_types:
+ typing.List[spotinst_sdk2.models.stateful_node.HealthCheckTypes] = 'd3043820717d74d9a17694c176d39733',
+ auto_healing: bool = 'd3043820717d74d9a17694c176d39733',
+ grace_period: int = 'd3043820717d74d9a17694c176d39733',
+ unhealthy_duration: int = 'd3043820717d74d9a17694c176d39733')
```
__Arguments__
-- __health_check_types__: List[str]
+- __health_check_types__: List[HealthCheckTypes]
- __auto_healing__: bool
- __grace_period__: int
- __unhealthy_duration__: int
+SchedulingTaskType
+
+```python
+SchedulingTaskType(cls,
+ value,
+ names=None,
+ *,
+ module,
+ qualname,
+ type,
+ start)
+```
+An enumeration.
+pause
+
+
+recycle
+
+
+resume
+
+
SchedulingTask
```python
-SchedulingTask(self,
- is_enabled: bool = 'd3043820717d74d9a17694c176d39733',
- cron_expression: str = 'd3043820717d74d9a17694c176d39733',
- type: str = 'd3043820717d74d9a17694c176d39733')
+SchedulingTask(
+ self,
+ is_enabled: bool = 'd3043820717d74d9a17694c176d39733',
+ cron_expression: str = 'd3043820717d74d9a17694c176d39733',
+ type: SchedulingTaskType = 'd3043820717d74d9a17694c176d39733')
```
__Arguments__
- __is_enabled__: bool
- __cron_expression__: str
-- __type__: str
+- __type__: SchedulingTaskType
Scheduling
@@ -68,39 +132,143 @@ __Arguments__
- __tasks__: List[SchedulingTask]
+
+
+```python
+PerformAt(cls, value, names=None, *, module, qualname, type, start)
+```
+An enumeration.
+
+
+
+
+
+
+
+
+
RevertToSpot
```python
-RevertToSpot(self, perform_at: str = 'd3043820717d74d9a17694c176d39733')
+RevertToSpot(self,
+ perform_at: PerformAt = 'd3043820717d74d9a17694c176d39733')
```
__Arguments__
-- __perform_at__: str
+- __perform_at__: PerformAt
+
+SignalType
+
+```python
+SignalType(cls, value, names=None, *, module, qualname, type, start)
+```
+An enumeration.
+vm_ready
+
+
+vm_ready_to_shutdown
+
Signal
```python
Signal(self,
timeout: int = 'd3043820717d74d9a17694c176d39733',
- type: str = 'd3043820717d74d9a17694c176d39733')
+ type: SignalType = 'd3043820717d74d9a17694c176d39733')
```
__Arguments__
- __timeout__: int
-- __type__: str
+- __type__: SignalType
+
+CapacityReservationGroups
+
+```python
+CapacityReservationGroups(
+ self,
+ name: str = 'd3043820717d74d9a17694c176d39733',
+ resource_group_name: str = 'd3043820717d74d9a17694c176d39733',
+ should_prioritize: bool = 'd3043820717d74d9a17694c176d39733')
+```
+
+__Arguments__
+
+- __name__: str
+- __resource_group_name__: str
+- __should_prioritize__: bool
+
+UtilizationStrategy
+
+```python
+UtilizationStrategy(cls,
+ value,
+ names=None,
+ *,
+ module,
+ qualname,
+ type,
+ start)
+```
+An enumeration.
+utilize_over_od
+
+
+utilize_over_spot
+
+
+CapacityReservation
+
+```python
+CapacityReservation(
+ self,
+ capacity_reservation_groups:
+ typing.List[spotinst_sdk2.models.stateful_node.CapacityReservationGroups] = 'd3043820717d74d9a17694c176d39733',
+ should_utilize: bool = 'd3043820717d74d9a17694c176d39733',
+ utilization_strategy:
+ UtilizationStrategy = 'd3043820717d74d9a17694c176d39733')
+```
+
+__Arguments__
+
+- __capacity_reservation_groups__: List[CapacityReservationGroups]
+- __should_utilize__: bool
+- __utilization_strategy__: UtilizationStrategy
+
+PreferredLifeCycle
+
+```python
+PreferredLifeCycle(cls,
+ value,
+ names=None,
+ *,
+ module,
+ qualname,
+ type,
+ start)
+```
+An enumeration.
+od
+
+
+spot
+
Strategy
```python
Strategy(
self,
+ availability_vs_cost: int = 'd3043820717d74d9a17694c176d39733',
+ capacity_reservation:
+ CapacityReservation = 'd3043820717d74d9a17694c176d39733',
draining_timeout: int = 'd3043820717d74d9a17694c176d39733',
fallback_to_od: bool = 'd3043820717d74d9a17694c176d39733',
od_windows: typing.List[str] = 'd3043820717d74d9a17694c176d39733',
optimization_windows: typing.List[str] = 'd3043820717d74d9a17694c176d39733',
- preferred_lifecycle: str = 'd3043820717d74d9a17694c176d39733',
+ preferred_lifecycle:
+ PreferredLifeCycle = 'd3043820717d74d9a17694c176d39733',
revert_to_spot: RevertToSpot = 'd3043820717d74d9a17694c176d39733',
signals:
typing.List[spotinst_sdk2.models.stateful_node.Signal] = 'd3043820717d74d9a17694c176d39733'
@@ -109,28 +277,60 @@ Strategy(
__Arguments__
+- __availability_vs_cost__: int
+- __capacity_reservation__: CapacityReservation
- __draining_timeout__: int
- __fallback_to_od__: bool
- __od_windows__: List[str]
- __optimization_windows__: List[str]
-- __preferred_lifecycle__: str
+- __preferred_lifecycle__: PreferredLifeCycle
- __revert_to_spot__: RevertToSpot
- __signals__: List[Signal]
+StorageType
+
+```python
+StorageType(cls, value, names=None, *, module, qualname, type, start)
+```
+An enumeration.
+managed
+
+
+unmanaged
+
+
BootDiagnostics
```python
BootDiagnostics(self,
is_enabled: bool = 'd3043820717d74d9a17694c176d39733',
storage_uri: str = 'd3043820717d74d9a17694c176d39733',
- type: str = 'd3043820717d74d9a17694c176d39733')
+ type: StorageType = 'd3043820717d74d9a17694c176d39733')
```
__Arguments__
- __is_enabled__: bool
storage_uri = str
-- __type__: str
+- __type__: StorageType
+
+DataDiskType
+
+```python
+DataDiskType(cls, value, names=None, *, module, qualname, type, start)
+```
+An enumeration.
+premium_lrs
+
+
+standard_lrs
+
+
+standard_ssd_lrs
+
+
+ultra_ssd_lrs
+
DataDisk
@@ -138,14 +338,14 @@ storage_uri = str
DataDisk(self,
lun: int = 'd3043820717d74d9a17694c176d39733',
size_g_b: int = 'd3043820717d74d9a17694c176d39733',
- type: str = 'd3043820717d74d9a17694c176d39733')
+ type: DataDiskType = 'd3043820717d74d9a17694c176d39733')
```
__Arguments__
- __lun__: int
-size_gb = int
-- __type__: str
+size_g_b = int
+- __type__: DataDiskType
Extension
@@ -164,6 +364,8 @@ __Arguments__
- __api_version__: str
- __minor_version_auto_upgrade__: bool
- __name__: str
+- __protected_settings__: ProtectedSettings
+- __public_settings__: PublicSettings
- __publisher__: str
- __type__: str
@@ -231,6 +433,25 @@ __Arguments__
- __custom__: Custom
- __gallery__: Gallery
+LoadBalancerType
+
+```python
+LoadBalancerType(cls,
+ value,
+ names=None,
+ *,
+ module,
+ qualname,
+ type,
+ start)
+```
+An enumeration.
+application_gateway
+
+
+load_balancer
+
+
LoadBalancer
```python
@@ -241,7 +462,7 @@ LoadBalancer(
load_balancer_sku: str = 'd3043820717d74d9a17694c176d39733',
name: str = 'd3043820717d74d9a17694c176d39733',
resource_group_name: str = 'd3043820717d74d9a17694c176d39733',
- type: str = 'd3043820717d74d9a17694c176d39733')
+ type: LoadBalancerType = 'd3043820717d74d9a17694c176d39733')
```
__Arguments__
@@ -250,7 +471,7 @@ __Arguments__
- __load_balancer_sku__: str
- __name__: str
- __resource_group_name__: str
-- __type__: str
+- __type__: LoadBalancerType
LoadBalancerConfig
@@ -295,19 +516,39 @@ __Arguments__
- __resource_group_name__: str
- __name__: str
+PrivateIpAddressVersion
+
+```python
+PrivateIpAddressVersion(cls,
+ value,
+ names=None,
+ *,
+ module,
+ qualname,
+ type,
+ start)
+```
+An enumeration.
+ipv4
+
+
+ipv6
+
+
AdditionalIpConfiguration
```python
AdditionalIpConfiguration(
- self,
- name: str = 'd3043820717d74d9a17694c176d39733',
- private_ip_address_version: str = 'd3043820717d74d9a17694c176d39733')
+ self,
+ name: str = 'd3043820717d74d9a17694c176d39733',
+ private_ip_address_version:
+ PrivateIpAddressVersion = 'd3043820717d74d9a17694c176d39733')
```
__Arguments__
- __name__: str
-- __private_ip_address_version__: str
+- __private_ip_address_version__: PrivateIpAddressVersion
ApplicationSecurityGroup
@@ -350,6 +591,18 @@ __Arguments__
- __name__: str
- __resource_group_name__: str
+PublicIpSku
+
+```python
+PublicIpSku(cls, value, names=None, *, module, qualname, type, start)
+```
+An enumeration.
+basic
+
+
+standard
+
+
NetworkInterface
```python
@@ -362,12 +615,13 @@ NetworkInterface(
assign_public_ip: bool = 'd3043820717d74d9a17694c176d39733',
enable_ip_forwarding: bool = 'd3043820717d74d9a17694c176d39733',
is_primary: bool = 'd3043820717d74d9a17694c176d39733',
- network_security_group='d3043820717d74d9a17694c176d39733',
+ network_security_group:
+ NetworkSecurityGroup = 'd3043820717d74d9a17694c176d39733',
private_ip_addresses:
typing.List[str] = 'd3043820717d74d9a17694c176d39733',
public_ips:
typing.List[spotinst_sdk2.models.stateful_node.PublicIp] = 'd3043820717d74d9a17694c176d39733',
- public_ip_sku: str = 'd3043820717d74d9a17694c176d39733',
+ public_ip_sku: PublicIpSku = 'd3043820717d74d9a17694c176d39733',
subnet_name: str = 'd3043820717d74d9a17694c176d39733')
```
@@ -406,13 +660,13 @@ __Arguments__
```python
OsDisk(self,
size_g_b: int = 'd3043820717d74d9a17694c176d39733',
- type: str = 'd3043820717d74d9a17694c176d39733')
+ type: DataDiskType = 'd3043820717d74d9a17694c176d39733')
```
__Arguments__
- __size_g_b__: int
-- __type__: str
+- __type__: DataDiskType
SourceVault
@@ -488,6 +742,48 @@ __Arguments__
- __preferred_spot_sizes__: List[str]
- __spot_sizes__: List[str]
+ProximityPlacementGroups
+
+```python
+ProximityPlacementGroups(
+ self,
+ name: str = 'd3043820717d74d9a17694c176d39733',
+ resource_group_name: str = 'd3043820717d74d9a17694c176d39733')
+```
+
+__Arguments__
+
+- __name__: str
+- __resource_group_name__: str
+
+SecurityType
+
+```python
+SecurityType(cls, value, names=None, *, module, qualname, type, start)
+```
+An enumeration.
+standard
+
+
+trusted_launch
+
+
+Security
+
+```python
+Security(
+ self,
+ secure_boot_enabled: bool = 'd3043820717d74d9a17694c176d39733',
+ security_type: SecurityType = 'd3043820717d74d9a17694c176d39733',
+ v_tpm_enabled: bool = 'd3043820717d74d9a17694c176d39733')
+```
+
+__Arguments__
+
+- __secure_boot_enabled__: bool
+- __security_type__: SecurityType
+- __v_tpm_enabled__: bool
+
LaunchSpecification
```python
@@ -508,11 +804,15 @@ LaunchSpecification(
typing.List[spotinst_sdk2.models.stateful_node.ManagedServiceIdentity] = 'd3043820717d74d9a17694c176d39733',
network: Network = 'd3043820717d74d9a17694c176d39733',
os_disk: OsDisk = 'd3043820717d74d9a17694c176d39733',
+ proximity_placement_groups:
+ typing.List[spotinst_sdk2.models.stateful_node.ProximityPlacementGroups] = 'd3043820717d74d9a17694c176d39733',
secrets:
typing.List[spotinst_sdk2.models.stateful_node.Secret] = 'd3043820717d74d9a17694c176d39733',
+ security: Security = 'd3043820717d74d9a17694c176d39733',
shutdown_script: str = 'd3043820717d74d9a17694c176d39733',
tags:
typing.List[spotinst_sdk2.models.stateful_node.Tag] = 'd3043820717d74d9a17694c176d39733',
+ user_data: str = 'd3043820717d74d9a17694c176d39733',
vm_name: str = 'd3043820717d74d9a17694c176d39733',
vm_name_prefix: str = 'd3043820717d74d9a17694c176d39733')
```
@@ -530,19 +830,34 @@ __Arguments__
- __managed_service_identities__: List[ManagedServiceIdentity]
- __network__: Network
- __os_disk__: OsDisk
+- __proximity_placement_groups__: List[ProximityPlacementGroups]
- __secrets__: List[Secret]
+- __security__: Security
- __shutdown_script__: str
- __tags__: List[Tag]
+- __user_data__: str
- __vm_name__: str
- __vm_name_prefix__: str
+OsType
+
+```python
+OsType(cls, value, names=None, *, module, qualname, type, start)
+```
+An enumeration.
+linux
+
+
+windows
+
+
Compute
```python
Compute(self,
launch_specification:
LaunchSpecification = 'd3043820717d74d9a17694c176d39733',
- os: str = 'd3043820717d74d9a17694c176d39733',
+ os: OsType = 'd3043820717d74d9a17694c176d39733',
preferred_zone: str = 'd3043820717d74d9a17694c176d39733',
vm_sizes: VmSizes = 'd3043820717d74d9a17694c176d39733',
zones: typing.List[str] = 'd3043820717d74d9a17694c176d39733')
@@ -551,7 +866,7 @@ Compute(self,
__Arguments__
- __launch_specification__: LaunchSpecification
-- __os__: str
+- __os__: OsType
- __preferred_zone__: str
- __vm_sizes__: VmSizes
- __zones__: List[str]
diff --git a/spotinst_sdk2/clients/stateful_node/__init__.py b/spotinst_sdk2/clients/stateful_node/__init__.py
index b3fe4940..8d81a8d2 100644
--- a/spotinst_sdk2/clients/stateful_node/__init__.py
+++ b/spotinst_sdk2/clients/stateful_node/__init__.py
@@ -119,15 +119,18 @@ def get_stateful_node(self, node_id: str):
return formatted_response["response"]["items"][0]
- def get_all_stateful_nodes(self):
+ def get_all_stateful_nodes(self, name: str = None, region: str = None):
"""
Get all Stateful Nodes
# Returns
(List): List of Stateful Nodes API response
"""
+ query_params = dict(name=name, region=region)
+
response = self.send_get(
url=self.__base_stateful_node_url,
+ query_params=query_params,
entity_name=self.ENTITY_NAME)
formatted_response = self.convert_json(
@@ -375,3 +378,111 @@ def get_stateful_node_logs(self, node_id, from_date, to_date, severity=None, res
response, self.camel_to_underscore)
return formatted_response["response"]["items"]
+
+ def swap_os_disk_to_stateful_node(self, node_id: str,
+ swap_osdisk_configuration: azure_stateful_node.SwapOsDiskConfiguration):
+ """
+ Configure a new managed OS disk for an OS persisted paused Stateful Node
+
+ # Arguments
+ node_id (String): Stateful Node ID
+ swap_osdisk_configuration (SwapOsDiskConfiguration): Configuration of OS Disk
+
+ # Returns
+ (Object): StatefulNode API response
+ """
+ request = azure_stateful_node.SwapOsDiskToStatefulNodeRequest(
+ swap_osdisk_configuration)
+
+ excluded_node_update_dict = self.exclude_missing(
+ json.loads(request.toJSON()))
+
+ formatted_node_update_dict = self.convert_json(
+ excluded_node_update_dict, self.underscore_to_camel)
+
+ body_json = json.dumps(formatted_node_update_dict)
+
+ response = self.send_put(
+ body=body_json,
+ url=self.__base_stateful_node_url + "/" + node_id + "/osDisk/swap",
+ entity_name=self.ENTITY_NAME)
+
+ formatted_response = self.convert_json(
+ response, self.camel_to_underscore)
+
+ return formatted_response["response"]
+
+ def get_all_stateful_node_costs(self, from_date: str, to_date: str, owner_id: str = None):
+ """
+ Get the total costs of a single stateful node/all stateful nodes and for a specific time period.
+
+ # Arguments
+ to_date (String): On or Before this date
+ from_date (String): On or After this date
+ ownerId (String) (Optional): Log level severity
+
+ # Returns
+ (Object): Stateful Node API response
+ """
+ query_params = dict(
+ toDate=to_date, fromDate=from_date, ownerId=owner_id)
+
+ response = self.send_get(
+ url=self.__base_stateful_node_url + "/cost",
+ query_params=query_params,
+ entity_name=self.ENTITY_NAME)
+
+ formatted_response = self.convert_json(
+ response, self.camel_to_underscore)
+
+ return formatted_response["response"]["items"]
+
+ def get_all_stateful_node_aggregated_daily_costs(self, from_date: str, to_date: str, owner_id: str = None):
+ """
+ Get the total costs per day of a single stateful node/all stateful nodes and for a specific time period.
+
+ # Arguments
+ to_date (String): On or Before this date
+ from_date (String): On or After this date
+ ownerId (String) (Optional): Log level severity
+
+ # Returns
+ (Object): Stateful Node API response
+ """
+ query_params = dict(fromDate=from_date,
+ toDate=to_date, ownerId=owner_id)
+
+ response = self.send_get(
+ url=self.__base_stateful_node_url + "/cost/daily",
+ query_params=query_params,
+ entity_name=self.ENTITY_NAME)
+
+ formatted_response = self.convert_json(
+ response, self.camel_to_underscore)
+
+ return formatted_response["response"]["items"]
+
+ def get_stateful_node_size_usage(self, from_date: str, to_date: str, owner_id: str = None):
+ """
+ Get the daily costs per VM size of a single stateful node/all stateful nodes and for a specific time period.
+
+ # Arguments
+ to_date (String): On or Before this date
+ from_date (String): On or After this date
+ ownerId (String) (Optional): Log level severity
+
+ # Returns
+ (Object): Stateful Node API response
+ """
+ query_params = dict(fromDate=from_date,
+ toDate=to_date, ownerId=owner_id)
+
+ response = self.send_get(
+ url=self.__base_stateful_node_url + "/sizeUsage/daily",
+ query_params=query_params,
+ entity_name=self.ENTITY_NAME)
+
+ formatted_response = self.convert_json(
+ response, self.camel_to_underscore)
+
+ return formatted_response["response"]["items"]
diff --git a/spotinst_sdk2/models/stateful_node/__init__.py b/spotinst_sdk2/models/stateful_node/__init__.py
index 6c74f220..7ebf3259 100644
--- a/spotinst_sdk2/models/stateful_node/__init__.py
+++ b/spotinst_sdk2/models/stateful_node/__init__.py
@@ -1,22 +1,29 @@
import json
+from enum import Enum
from typing import List
none = "d3043820717d74d9a17694c176d39733"
+
# region Persistence
+class PersistenceMode(Enum):
+ reattach = "reattach"
+ on_launch = "onLaunch"
+
+
class Persistence:
"""
# Arguments
- data_disks_persistence_mode: str
- os_disk_persistence_mode: str
+ data_disks_persistence_mode: PersistenceMode
+ os_disk_persistence_mode: PersistenceMode
should_persist_data_disks: bool
should_persist_network: bool
should_persist_os_disk: bool
"""
- def __init__(self, data_disks_persistence_mode: str = none, os_disk_persistence_mode: str = none,
+ def __init__(self, data_disks_persistence_mode: PersistenceMode = none, os_disk_persistence_mode: PersistenceMode = none,
should_persist_data_disks: bool = none, should_persist_network: bool = none,
should_persist_os_disk: bool = none):
self.data_disks_persistence_mode = data_disks_persistence_mode
@@ -25,15 +32,20 @@ def __init__(self, data_disks_persistence_mode: str = none, os_disk_persistence_
self.should_persist_network = should_persist_network
self.should_persist_os_disk = should_persist_os_disk
+
# endregion
# region Health
+class HealthCheckTypes(Enum):
+ vm_state = "vmState"
+ application_gateway = "applicationGateway"
+
class Health:
"""
# Arguments
- health_check_types: List[str]
+ health_check_types: List[HealthCheckTypes]
auto_healing: bool
grace_period: int
unhealthy_duration: int
@@ -41,7 +53,7 @@ class Health:
def __init__(
self,
- health_check_types: List[str] = none,
+ health_check_types: List[HealthCheckTypes] = none,
auto_healing: bool = none,
grace_period: int = none,
unhealthy_duration: int = none):
@@ -50,24 +62,31 @@ def __init__(
self.grace_period = grace_period
self.unhealthy_duration = unhealthy_duration
+
# endregion
# region Scheduling
+class SchedulingTaskType(Enum):
+ pause = "pause"
+ resume = "resume"
+ recycle = "recycle"
+
+
class SchedulingTask:
"""
# Arguments
is_enabled: bool
cron_expression: str
- type: str
+ type: SchedulingTaskType
"""
def __init__(
self,
is_enabled: bool = none,
cron_expression: str = none,
- type: str = none):
+ type: SchedulingTaskType = none):
self.is_enabled = is_enabled
self.cron_expression = cron_expression
self.type = type
@@ -82,54 +101,117 @@ class Scheduling:
def __init__(self, tasks: List[SchedulingTask] = none):
self.tasks = tasks
+
# endregion
# region Strategy
+class PerformAt(Enum):
+ time_window = "timeWindow"
+ never = "never"
+ always = "always"
+
+
class RevertToSpot:
"""
# Arguments
- perform_at: str
+ perform_at: PerformAt
"""
- def __init__(self, perform_at: str = none):
+ def __init__(self, perform_at: PerformAt = none):
self.perform_at = perform_at
+class SignalType(Enum):
+ vm_ready = "vmReady"
+ vm_ready_to_shutdown = "vmReadyToShutdown"
+
+
class Signal:
"""
# Arguments
timeout: int
- type: str
+ type: SignalType
"""
- def __init__(self, timeout: int = none, type: str = none):
+ def __init__(self, timeout: int = none, type: SignalType = none):
self.timeout = timeout
self.type = type
+class CapacityReservationGroups:
+ """
+ # Arguments
+ name: str
+ resource_group_name: str
+ should_prioritize: bool
+ """
+
+ def __init__(self,
+ name: str = none,
+ resource_group_name: str = none,
+ should_prioritize: bool = none):
+ self.name = name
+ self.resource_group_name = resource_group_name
+ self.should_prioritize = should_prioritize
+
+
+class UtilizationStrategy(Enum):
+ utilize_over_spot = "utilizeOverSpot"
+ utilize_over_od = "utilizeOverOD"
+
+
+class CapacityReservation:
+ """
+ # Arguments
+ capacity_reservation_groups: List[CapacityReservationGroups]
+ should_utilize: bool
+ utilization_strategy: UtilizationStrategy
+ """
+
+ def __init__(
+ self,
+ capacity_reservation_groups: List[CapacityReservationGroups] = none,
+ should_utilize: bool = none,
+ utilization_strategy: UtilizationStrategy = none):
+ self.capacity_reservation_groups = capacity_reservation_groups
+ self.should_utilize = should_utilize
+ self.utilization_strategy = utilization_strategy
+
+
+class PreferredLifeCycle(Enum):
+ spot = "spot"
+ od = "od"
+
+
class Strategy:
"""
# Arguments
+ availability_vs_cost: int
+ capacity_reservation: CapacityReservation
draining_timeout: int
fallback_to_od: bool
od_windows: List[str]
optimization_windows: List[str]
- preferred_lifecycle: str
+ preferred_lifecycle: PreferredLifeCycle
revert_to_spot: RevertToSpot
signals: List[Signal]
"""
def __init__(
self,
+ availability_vs_cost: int = none,
+ capacity_reservation: CapacityReservation = none,
draining_timeout: int = none,
fallback_to_od: bool = none,
od_windows: List[str] = none,
optimization_windows: List[str] = none,
- preferred_lifecycle: str = none,
+ preferred_lifecycle: PreferredLifeCycle = none,
revert_to_spot: RevertToSpot = none,
signals: List[Signal] = none):
+ self.availability_vs_cost = availability_vs_cost
+ self.capacity_reservation = capacity_reservation
self.draining_timeout = draining_timeout
self.fallback_to_od = fallback_to_od
self.od_windows = od_windows
@@ -138,42 +220,54 @@ def __init__(
self.revert_to_spot = revert_to_spot
self.signals = signals
+
# endregion
# region Compute
+class StorageType(Enum):
+ managed = "managed"
+ unmanaged = "unmanaged"
+
class BootDiagnostics:
"""
# Arguments
is_enabled: bool
storage_uri = str
- type: str
+ type: StorageType
"""
def __init__(
self,
is_enabled: bool = none,
storage_uri: str = none,
- type: str = none):
+ type: StorageType = none):
self.is_enabled = is_enabled
self.storage_uri = storage_uri
self.type = type
+class DataDiskType(Enum):
+ standard_lrs = "Standard_LRS"
+ premium_lrs = "Premium_LRS"
+ standard_ssd_lrs = "StandardSSD_LRS"
+ ultra_ssd_lrs = "UltraSSD_LRS"
+
+
class DataDisk:
"""
# Arguments
lun: int
- size_gb = int
- type: str
+ size_g_b = int
+ type: DataDiskType
"""
def __init__(
self,
lun: int = none,
size_g_b: int = none,
- type: str = none):
+ type: DataDiskType = none):
self.lun = lun
self.size_g_b = size_g_b
self.type = type
@@ -185,6 +279,8 @@ class Extension:
api_version: str
minor_version_auto_upgrade: bool
name: str
+ protected_settings: ProtectedSettings
+ public_settings: PublicSettings
publisher: str
type: str
"""
@@ -277,6 +373,11 @@ def __init__(self, marketplace: Marketplace = none, custom: Custom = none, galle
self.gallery = gallery
+class LoadBalancerType(Enum):
+ load_balancer = "loadBalancer"
+ application_gateway = "applicationGateway"
+
+
class LoadBalancer:
"""
# Arguments
@@ -284,7 +385,7 @@ class LoadBalancer:
load_balancer_sku: str
name: str
resource_group_name: str
- type: str
+ type: LoadBalancerType
"""
def __init__(
@@ -293,7 +394,7 @@ def __init__(
load_balancer_sku: str = none,
name: str = none,
resource_group_name: str = none,
- type: str = none):
+ type: LoadBalancerType = none):
self.backend_pool_names = backend_pool_names
self.load_balancer_sku = load_balancer_sku
self.name = name
@@ -344,17 +445,22 @@ def __init__(
self.name = name
+class PrivateIpAddressVersion(Enum):
+ ipv4 = "IPv4"
+ ipv6 = "IPv6"
+
+
class AdditionalIpConfiguration:
"""
# Arguments
name: str
- private_ip_address_version: str
+ private_ip_address_version: PrivateIpAddressVersion
"""
def __init__(
self,
name: str = none,
- private_ip_address_version: str = none):
+ private_ip_address_version: PrivateIpAddressVersion = none):
self.name = name
self.private_ip_address_version = private_ip_address_version
@@ -404,6 +510,11 @@ def __init__(
self.resource_group_name = resource_group_name
+class PublicIpSku(Enum):
+ standard = "Standard"
+ basic = "Basic"
+
+
class NetworkInterface:
"""
# Arguments
@@ -426,10 +537,10 @@ def __init__(
assign_public_ip: bool = none,
enable_ip_forwarding: bool = none,
is_primary: bool = none,
- network_security_group=none,
+ network_security_group: NetworkSecurityGroup = none,
private_ip_addresses: List[str] = none,
public_ips: List[PublicIp] = none,
- public_ip_sku: str = none,
+ public_ip_sku: PublicIpSku = none,
subnet_name: str = none):
self.additional_ip_configurations = additional_ip_configurations
self.application_security_groups = application_security_groups
@@ -465,13 +576,13 @@ class OsDisk:
"""
# Arguments
size_g_b: int
- type: str
+ type: DataDiskType
"""
def __init__(
self,
size_g_b: int = none,
- type: str = none):
+ type: DataDiskType = none):
self.size_g_b = size_g_b
self.type = type
@@ -554,6 +665,44 @@ def __init__(
self.spot_sizes = spot_sizes
+class ProximityPlacementGroups:
+ """
+ # Arguments
+ name: str
+ resource_group_name: str
+ """
+
+ def __init__(
+ self,
+ name: str = none,
+ resource_group_name: str = none):
+ self.name = name
+ self.resource_group_name = resource_group_name
+
+
+class SecurityType(Enum):
+ standard = "Standard"
+ trusted_launch = "TrustedLaunch"
+
+
+class Security:
+ """
+ # Arguments
+ secure_boot_enabled: bool
+ security_type: SecurityType
+ v_tpm_enabled: bool
+ """
+
+ def __init__(
+ self,
+ secure_boot_enabled: bool = none,
+ security_type: SecurityType = none,
+ v_tpm_enabled: bool = none):
+ self.secure_boot_enabled = secure_boot_enabled
+ self.security_type = security_type
+ self.v_tpm_enabled = v_tpm_enabled
+
+
class LaunchSpecification:
"""
# Arguments
@@ -568,9 +717,12 @@ class LaunchSpecification:
managed_service_identities: List[ManagedServiceIdentity]
network: Network
os_disk: OsDisk
+ proximity_placement_groups: List[ProximityPlacementGroups]
secrets: List[Secret]
+ security: Security
shutdown_script: str
tags: List[Tag]
+ user_data: str
vm_name: str
vm_name_prefix: str
"""
@@ -588,9 +740,12 @@ def __init__(
managed_service_identities: List[ManagedServiceIdentity] = none,
network: Network = none,
os_disk: OsDisk = none,
+ proximity_placement_groups: List[ProximityPlacementGroups] = none,
secrets: List[Secret] = none,
+ security: Security = none,
shutdown_script: str = none,
tags: List[Tag] = none,
+ user_data: str = none,
vm_name: str = none,
vm_name_prefix: str = none):
self.boot_diagnostics = boot_diagnostics
@@ -604,18 +759,26 @@ def __init__(
self.managed_service_identities = managed_service_identities
self.network = network
self.os_disk = os_disk
+ self.proximity_placement_groups = proximity_placement_groups
self.secrets = secrets
+ self.security = security
self.shutdown_script = shutdown_script
self.tags = tags
+ self.user_data = user_data
self.vm_name = vm_name
self.vm_name_prefix = vm_name_prefix
+class OsType(Enum):
+ linux = "Linux"
+ windows = "Windows"
+
+
class Compute:
"""
# Arguments
launch_specification: LaunchSpecification
- os: str
+ os: OsType
preferred_zone: str
vm_sizes: VmSizes
zones: List[str]
@@ -624,7 +787,7 @@ class Compute:
def __init__(
self,
launch_specification: LaunchSpecification = none,
- os: str = none,
+ os: OsType = none,
preferred_zone: str = none,
vm_sizes: VmSizes = none,
zones: List[str] = none):
@@ -634,6 +797,7 @@ def __init__(
self.vm_sizes = vm_sizes
self.zones = zones
+
# endregion
# region StatefulNode
@@ -644,7 +808,7 @@ class StatefulNode:
# Arguments
compute: Compute
description: str
- health: Health
+ health: Health
name: str
persistence: Persistence
region: str
@@ -674,6 +838,7 @@ def __init__(
self.scheduling = scheduling
self.strategy = strategy
+
# endregion
@@ -738,11 +903,13 @@ def toJSON(self):
class ImportVmConfiguration:
def __init__(self,
+ convert_unmanaged_disks: bool = none,
draining_timeout: int = none,
node: StatefulNode = none,
original_vm_name: str = none,
resource_group_name: str = none,
resource_retention_time: int = none):
+ self.convert_unmanaged_disks = convert_unmanaged_disks
self.draining_timeout = draining_timeout
self.node = node
self.original_vm_name = original_vm_name
@@ -770,7 +937,7 @@ def __init__(
data_disk_resource_group_name: str = none,
lun: int = none,
size_g_b: int = none,
- storage_account_type: str = none,
+ storage_account_type: DataDiskType = none,
zone: str = none):
self.data_disk_name = data_disk_name
self.data_disk_resource_group_name = data_disk_resource_group_name
@@ -824,4 +991,31 @@ def toJSON(self):
sort_keys=True,
indent=4)
+
+class SwapOsDiskConfiguration:
+ def __init__(self, os_disk_name: str = none,
+ os_disk_resource_group_name: str = none,
+ retention_time: int = none,
+ should_terminate: bool = none):
+ self.os_disk_name = os_disk_name
+ self.os_disk_resource_group_name = os_disk_resource_group_name
+ self.retention_time = retention_time
+ self.should_terminate = should_terminate
+
+
+class SwapOsDiskToStatefulNodeRequest:
+ def __init__(self, config: SwapOsDiskConfiguration = none):
+ self.os_disk_name = config.os_disk_name
+ self.os_disk_resource_group_name = config.os_disk_resource_group_name
+ self.retention_time = config.retention_time
+ self.should_terminate = config.should_terminate
+
+ def toJSON(self):
+ return json.dumps(
+ self,
+ default=lambda o: o.__dict__,
+ sort_keys=True,
+ indent=4)
+
+
# endregion
diff --git a/spotinst_sdk2/version.py b/spotinst_sdk2/version.py
index f1edb192..82190396 100644
--- a/spotinst_sdk2/version.py
+++ b/spotinst_sdk2/version.py
@@ -1 +1 @@
-__version__ = '2.2.2'
+__version__ = '2.3.0'