diff --git a/scaleway-async/scaleway_async/instance/v2alpha1/__init__.py b/scaleway-async/scaleway_async/instance/v2alpha1/__init__.py index 6f9013cb4..38d847836 100644 --- a/scaleway-async/scaleway_async/instance/v2alpha1/__init__.py +++ b/scaleway-async/scaleway_async/instance/v2alpha1/__init__.py @@ -45,6 +45,7 @@ from .types import CreateServerRequestCreateVolume from .types import ServerTypeGpuInfo from .types import ServerTypeLimits +from .types import ServerTypeSpotInfo from .types import ServerIP from .types import CreateTemplateRequestPrivateNetworkTemplate from .types import CreateTemplateRequestVolumeTemplate @@ -67,6 +68,7 @@ from .types import ServerPrivateNetworkInterface from .types import ServerPublicNetworkInterface from .types import ServerRDPPassword +from .types import ServerRuntimeInfo from .types import ServerVolume from .types import UpdateServerRequestPublicNetworkInterface from .types import UpdateTemplateRequestUpdatePrivateNetworks @@ -146,6 +148,7 @@ from .types import SetTemplateUserDataRequest from .types import SetUserDataRequest from .types import StartServerRequest +from .types import StartSpotServerRequest from .types import StopAndDeleteServerRequest from .types import StopServerRequest from .types import Template @@ -219,6 +222,7 @@ "CreateServerRequestCreateVolume", "ServerTypeGpuInfo", "ServerTypeLimits", + "ServerTypeSpotInfo", "ServerIP", "CreateTemplateRequestPrivateNetworkTemplate", "CreateTemplateRequestVolumeTemplate", @@ -241,6 +245,7 @@ "ServerPrivateNetworkInterface", "ServerPublicNetworkInterface", "ServerRDPPassword", + "ServerRuntimeInfo", "ServerVolume", "UpdateServerRequestPublicNetworkInterface", "UpdateTemplateRequestUpdatePrivateNetworks", @@ -320,6 +325,7 @@ "SetTemplateUserDataRequest", "SetUserDataRequest", "StartServerRequest", + "StartSpotServerRequest", "StopAndDeleteServerRequest", "StopServerRequest", "Template", diff --git a/scaleway-async/scaleway_async/instance/v2alpha1/api.py b/scaleway-async/scaleway_async/instance/v2alpha1/api.py index 1c8ab43d0..03fde4560 100644 --- a/scaleway-async/scaleway_async/instance/v2alpha1/api.py +++ b/scaleway-async/scaleway_async/instance/v2alpha1/api.py @@ -672,6 +672,40 @@ async def start_server( self._throw_on_error(res) return unmarshal_Server(res.json()) + async def start_spot_server( + self, + *, + server_id: str, + zone: Optional[ScwZone] = None, + ) -> Server: + """ + Start an Instance as Spot. + Spot instances are billed at a discount compared to regular instances. However, they can be interrupted + at any time. + :param server_id: ID of the server to start as spot instance. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`Server ` + + Usage: + :: + + result = await api.start_spot_server( + server_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_server_id = validate_path_param("server_id", server_id) + + res = self._request( + "POST", + f"/instance/v2alpha1/zones/{param_zone}/servers/{param_server_id}/start-spot", + body={}, + ) + + self._throw_on_error(res) + return unmarshal_Server(res.json()) + async def reboot_server( self, *, diff --git a/scaleway-async/scaleway_async/instance/v2alpha1/marshalling.py b/scaleway-async/scaleway_async/instance/v2alpha1/marshalling.py index 6cb9e138a..a97e65325 100644 --- a/scaleway-async/scaleway_async/instance/v2alpha1/marshalling.py +++ b/scaleway-async/scaleway_async/instance/v2alpha1/marshalling.py @@ -44,6 +44,7 @@ ListPrivateNetworkInterfacesResponse, SecurityGroupSummary, ListSecurityGroupsResponse, + ServerTypeSpotInfo, ServerType, ListServerCompatibleTypesResponse, ListServerTypesResponse, @@ -64,6 +65,7 @@ ServerPrivateNetworkInterface, ServerPublicNetworkInterface, ServerRDPPassword, + ServerRuntimeInfo, ServerVolume, Server, CreateTemplateRequestPrivateNetworkTemplate, @@ -1215,6 +1217,23 @@ def unmarshal_ListSecurityGroupsResponse(data: Any) -> ListSecurityGroupsRespons return ListSecurityGroupsResponse(**args) +def unmarshal_ServerTypeSpotInfo(data: Any) -> ServerTypeSpotInfo: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ServerTypeSpotInfo' failed as data isn't a dictionary." + ) + + args: dict[str, Any] = {} + + field = data.get("availability", None) + if field is not None: + args["availability"] = field + else: + args["availability"] = None + + return ServerTypeSpotInfo(**args) + + def unmarshal_ServerType(data: Any) -> ServerType: if not isinstance(data, dict): raise TypeError( @@ -1277,6 +1296,12 @@ def unmarshal_ServerType(data: Any) -> ServerType: else: args["gpu_info"] = None + field = data.get("spot_info", None) + if field is not None: + args["spot_info"] = unmarshal_ServerTypeSpotInfo(field) + else: + args["spot_info"] = None + return ServerType(**args) @@ -2139,6 +2164,23 @@ def unmarshal_ServerRDPPassword(data: Any) -> ServerRDPPassword: return ServerRDPPassword(**args) +def unmarshal_ServerRuntimeInfo(data: Any) -> ServerRuntimeInfo: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ServerRuntimeInfo' failed as data isn't a dictionary." + ) + + args: dict[str, Any] = {} + + field = data.get("spot", None) + if field is not None: + args["spot"] = field + else: + args["spot"] = False + + return ServerRuntimeInfo(**args) + + def unmarshal_ServerVolume(data: Any) -> ServerVolume: if not isinstance(data, dict): raise TypeError( @@ -2306,6 +2348,12 @@ def unmarshal_Server(data: Any) -> Server: else: args["public_network_interface"] = None + field = data.get("runtime_info", None) + if field is not None: + args["runtime_info"] = unmarshal_ServerRuntimeInfo(field) + else: + args["runtime_info"] = None + return Server(**args) diff --git a/scaleway-async/scaleway_async/instance/v2alpha1/types.py b/scaleway-async/scaleway_async/instance/v2alpha1/types.py index 69e0f33fb..071bebc59 100644 --- a/scaleway-async/scaleway_async/instance/v2alpha1/types.py +++ b/scaleway-async/scaleway_async/instance/v2alpha1/types.py @@ -267,6 +267,7 @@ class ServerTypeAvailability(str, Enum, metaclass=StrEnumMeta): AVAILABLE = "available" LOW_STOCK = "low_stock" OUT_OF_STOCK = "out_of_stock" + UNAVAILABLE = "unavailable" def __str__(self) -> str: return str(self.value) @@ -504,6 +505,11 @@ class ServerTypeLimits: """ +@dataclass +class ServerTypeSpotInfo: + availability: ServerTypeAvailability + + @dataclass class ServerIP: id: str @@ -1026,6 +1032,11 @@ class ServerType: GPU information for the server type. """ + spot_info: Optional[ServerTypeSpotInfo] = None + """ + Availability status of the server type as a spot instance. + """ + @dataclass class ServerSummary: @@ -1358,6 +1369,14 @@ class ServerRDPPassword: rdp_ssh_key_id: str +@dataclass +class ServerRuntimeInfo: + spot: bool + """ + True if the Instance is running as Spot. + """ + + @dataclass class ServerVolume: id: str @@ -3113,6 +3132,11 @@ class Server: Public network interface of the server. """ + runtime_info: Optional[ServerRuntimeInfo] = None + """ + Runtime information of this server, only available only when it is running. + """ + @dataclass class SetSecurityGroupRulesRequest: @@ -3247,6 +3271,19 @@ class StartServerRequest: """ +@dataclass +class StartSpotServerRequest: + server_id: str + """ + ID of the server to start as spot instance. + """ + + zone: Optional[ScwZone] = None + """ + Zone to target. If none is passed will use default zone from the config. + """ + + @dataclass class StopAndDeleteServerRequest: server_id: str diff --git a/scaleway/scaleway/instance/v2alpha1/__init__.py b/scaleway/scaleway/instance/v2alpha1/__init__.py index 6f9013cb4..38d847836 100644 --- a/scaleway/scaleway/instance/v2alpha1/__init__.py +++ b/scaleway/scaleway/instance/v2alpha1/__init__.py @@ -45,6 +45,7 @@ from .types import CreateServerRequestCreateVolume from .types import ServerTypeGpuInfo from .types import ServerTypeLimits +from .types import ServerTypeSpotInfo from .types import ServerIP from .types import CreateTemplateRequestPrivateNetworkTemplate from .types import CreateTemplateRequestVolumeTemplate @@ -67,6 +68,7 @@ from .types import ServerPrivateNetworkInterface from .types import ServerPublicNetworkInterface from .types import ServerRDPPassword +from .types import ServerRuntimeInfo from .types import ServerVolume from .types import UpdateServerRequestPublicNetworkInterface from .types import UpdateTemplateRequestUpdatePrivateNetworks @@ -146,6 +148,7 @@ from .types import SetTemplateUserDataRequest from .types import SetUserDataRequest from .types import StartServerRequest +from .types import StartSpotServerRequest from .types import StopAndDeleteServerRequest from .types import StopServerRequest from .types import Template @@ -219,6 +222,7 @@ "CreateServerRequestCreateVolume", "ServerTypeGpuInfo", "ServerTypeLimits", + "ServerTypeSpotInfo", "ServerIP", "CreateTemplateRequestPrivateNetworkTemplate", "CreateTemplateRequestVolumeTemplate", @@ -241,6 +245,7 @@ "ServerPrivateNetworkInterface", "ServerPublicNetworkInterface", "ServerRDPPassword", + "ServerRuntimeInfo", "ServerVolume", "UpdateServerRequestPublicNetworkInterface", "UpdateTemplateRequestUpdatePrivateNetworks", @@ -320,6 +325,7 @@ "SetTemplateUserDataRequest", "SetUserDataRequest", "StartServerRequest", + "StartSpotServerRequest", "StopAndDeleteServerRequest", "StopServerRequest", "Template", diff --git a/scaleway/scaleway/instance/v2alpha1/api.py b/scaleway/scaleway/instance/v2alpha1/api.py index 4b04c81fc..0ab39d285 100644 --- a/scaleway/scaleway/instance/v2alpha1/api.py +++ b/scaleway/scaleway/instance/v2alpha1/api.py @@ -672,6 +672,40 @@ def start_server( self._throw_on_error(res) return unmarshal_Server(res.json()) + def start_spot_server( + self, + *, + server_id: str, + zone: Optional[ScwZone] = None, + ) -> Server: + """ + Start an Instance as Spot. + Spot instances are billed at a discount compared to regular instances. However, they can be interrupted + at any time. + :param server_id: ID of the server to start as spot instance. + :param zone: Zone to target. If none is passed will use default zone from the config. + :return: :class:`Server ` + + Usage: + :: + + result = api.start_spot_server( + server_id="example", + ) + """ + + param_zone = validate_path_param("zone", zone or self.client.default_zone) + param_server_id = validate_path_param("server_id", server_id) + + res = self._request( + "POST", + f"/instance/v2alpha1/zones/{param_zone}/servers/{param_server_id}/start-spot", + body={}, + ) + + self._throw_on_error(res) + return unmarshal_Server(res.json()) + def reboot_server( self, *, diff --git a/scaleway/scaleway/instance/v2alpha1/marshalling.py b/scaleway/scaleway/instance/v2alpha1/marshalling.py index 6cb9e138a..a97e65325 100644 --- a/scaleway/scaleway/instance/v2alpha1/marshalling.py +++ b/scaleway/scaleway/instance/v2alpha1/marshalling.py @@ -44,6 +44,7 @@ ListPrivateNetworkInterfacesResponse, SecurityGroupSummary, ListSecurityGroupsResponse, + ServerTypeSpotInfo, ServerType, ListServerCompatibleTypesResponse, ListServerTypesResponse, @@ -64,6 +65,7 @@ ServerPrivateNetworkInterface, ServerPublicNetworkInterface, ServerRDPPassword, + ServerRuntimeInfo, ServerVolume, Server, CreateTemplateRequestPrivateNetworkTemplate, @@ -1215,6 +1217,23 @@ def unmarshal_ListSecurityGroupsResponse(data: Any) -> ListSecurityGroupsRespons return ListSecurityGroupsResponse(**args) +def unmarshal_ServerTypeSpotInfo(data: Any) -> ServerTypeSpotInfo: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ServerTypeSpotInfo' failed as data isn't a dictionary." + ) + + args: dict[str, Any] = {} + + field = data.get("availability", None) + if field is not None: + args["availability"] = field + else: + args["availability"] = None + + return ServerTypeSpotInfo(**args) + + def unmarshal_ServerType(data: Any) -> ServerType: if not isinstance(data, dict): raise TypeError( @@ -1277,6 +1296,12 @@ def unmarshal_ServerType(data: Any) -> ServerType: else: args["gpu_info"] = None + field = data.get("spot_info", None) + if field is not None: + args["spot_info"] = unmarshal_ServerTypeSpotInfo(field) + else: + args["spot_info"] = None + return ServerType(**args) @@ -2139,6 +2164,23 @@ def unmarshal_ServerRDPPassword(data: Any) -> ServerRDPPassword: return ServerRDPPassword(**args) +def unmarshal_ServerRuntimeInfo(data: Any) -> ServerRuntimeInfo: + if not isinstance(data, dict): + raise TypeError( + "Unmarshalling the type 'ServerRuntimeInfo' failed as data isn't a dictionary." + ) + + args: dict[str, Any] = {} + + field = data.get("spot", None) + if field is not None: + args["spot"] = field + else: + args["spot"] = False + + return ServerRuntimeInfo(**args) + + def unmarshal_ServerVolume(data: Any) -> ServerVolume: if not isinstance(data, dict): raise TypeError( @@ -2306,6 +2348,12 @@ def unmarshal_Server(data: Any) -> Server: else: args["public_network_interface"] = None + field = data.get("runtime_info", None) + if field is not None: + args["runtime_info"] = unmarshal_ServerRuntimeInfo(field) + else: + args["runtime_info"] = None + return Server(**args) diff --git a/scaleway/scaleway/instance/v2alpha1/types.py b/scaleway/scaleway/instance/v2alpha1/types.py index 69e0f33fb..071bebc59 100644 --- a/scaleway/scaleway/instance/v2alpha1/types.py +++ b/scaleway/scaleway/instance/v2alpha1/types.py @@ -267,6 +267,7 @@ class ServerTypeAvailability(str, Enum, metaclass=StrEnumMeta): AVAILABLE = "available" LOW_STOCK = "low_stock" OUT_OF_STOCK = "out_of_stock" + UNAVAILABLE = "unavailable" def __str__(self) -> str: return str(self.value) @@ -504,6 +505,11 @@ class ServerTypeLimits: """ +@dataclass +class ServerTypeSpotInfo: + availability: ServerTypeAvailability + + @dataclass class ServerIP: id: str @@ -1026,6 +1032,11 @@ class ServerType: GPU information for the server type. """ + spot_info: Optional[ServerTypeSpotInfo] = None + """ + Availability status of the server type as a spot instance. + """ + @dataclass class ServerSummary: @@ -1358,6 +1369,14 @@ class ServerRDPPassword: rdp_ssh_key_id: str +@dataclass +class ServerRuntimeInfo: + spot: bool + """ + True if the Instance is running as Spot. + """ + + @dataclass class ServerVolume: id: str @@ -3113,6 +3132,11 @@ class Server: Public network interface of the server. """ + runtime_info: Optional[ServerRuntimeInfo] = None + """ + Runtime information of this server, only available only when it is running. + """ + @dataclass class SetSecurityGroupRulesRequest: @@ -3247,6 +3271,19 @@ class StartServerRequest: """ +@dataclass +class StartSpotServerRequest: + server_id: str + """ + ID of the server to start as spot instance. + """ + + zone: Optional[ScwZone] = None + """ + Zone to target. If none is passed will use default zone from the config. + """ + + @dataclass class StopAndDeleteServerRequest: server_id: str