1use serde::{Deserialize, Serialize};
2use crate::types::common::{Labels, Label, Tags};
3
4pub const VIDEO_MODEL_VGA: &str = "vga";
5pub const VIDEO_MODEL_CIRRUS: &str = "cirrus";
6
7pub const NIC_MODEL_E1000: &str = "e1000";
8pub const NIC_MODEL_VIRTIO: &str = "virtio";
9pub const NIC_MODEL_RTL8139: &str = "rtl8139";
10
11pub const STOP_TYPE_SOFT: &str = "soft";
12pub const STOP_TYPE_HARD: &str = "hard";
13
14pub const PASSWORD_DELIVERY_NONE: &str = "none";
15pub const PASSWORD_DELIVERY_EMAIL: &str = "email";
16pub const PASSWORD_DELIVERY_SMS: &str = "sms";
17
18pub const CREATE_SERVER_STORAGE_DEVICE_ACTION_CREATE: &str = "create";
19pub const CREATE_SERVER_STORAGE_DEVICE_ACTION_CLONE: &str = "clone";
20pub const CREATE_SERVER_STORAGE_DEVICE_ACTION_ATTACH: &str = "attach";
21
22pub enum ServerState {
23 Started,
24 Stopped,
25 Maintenance,
26 Error,
27}
28
29impl ServerState {
30 pub fn as_str(&self) -> &'static str {
31 match self {
32 Self::Started => "started",
33 Self::Stopped => "stopped",
34 Self::Maintenance => "maintenance",
35 Self::Error => "error",
36 }
37 }
38}
39
40#[derive(Debug, Deserialize)]
41pub struct GetServerResponse {
42 pub servers: ServerList,
43}
44
45#[derive(Debug, Deserialize)]
46pub struct GetServerDetailsResponse {
47 pub server: ServerDetails,
48}
49
50#[derive(Debug, Deserialize)]
51pub struct CreateServerResponse {
52 pub server: ServerDetails,
53}
54
55#[derive(Debug, Clone, Deserialize)]
56pub struct ServerList {
57 pub server: Vec<Server>,
58}
59
60#[derive(Debug, Default, Serialize, Clone, Deserialize)]
61pub struct Server {
62 #[serde(skip_serializing_if = "Option::is_none")]
63 pub core_number: Option<String>,
64 #[serde(skip_serializing_if = "Option::is_none")]
65 pub created: Option<i64>,
66 #[serde(default)]
67 pub host: i64,
68 pub hostname: String,
69 #[serde(skip_serializing_if = "Option::is_none")]
70 pub labels: Option<Labels>,
71 pub license: f64,
72 pub memory_amount: String,
73 pub plan: String,
74 #[serde(default)]
75 pub plan_ipv4_bytes: String,
76 #[serde(default)]
77 pub plan_ipv6_bytes: String,
78 #[serde(default)]
79 pub server_group: Option<String>,
80 #[serde(default)]
81 pub simple_backup: String,
82 pub state: String,
83 #[serde(default)]
84 pub tags: Tags,
85 pub title: String,
86 pub uuid: String,
87 pub zone: String,
88}
89
90#[derive(Debug, Default, Clone, Deserialize)]
91pub struct ServerDetails {
92 #[serde(flatten)]
93 pub server: Server,
94 pub boot_order: Option<String>,
95 #[serde(skip_serializing_if = "Option::is_none")]
96 pub firewall: Option<String>,
97 #[serde(rename = "ip_addresses")]
98 pub ip_addresses: Option<IPAddressWrapper>,
99 pub networking: Option<CreateServerNetworking>,
100 pub nic_model: Option<String>,
101 #[serde(skip_serializing_if = "Option::is_none")]
102 pub password: Option<String>,
103 #[serde(skip_serializing_if = "Option::is_none", rename = "storage_devices")]
104 pub storage_devices: Option<StorageDeviceListWrapper>,
105 pub video_model: Option<String>,
106 #[serde(serialize_with = "serialize_bool_as_yes_no", deserialize_with = "deserialize_yes_no_as_bool")]
107 pub remote_access_enabled: bool,
108 pub remote_access_password: String,
109}
110
111#[derive(Debug, Serialize, Clone, Deserialize)]
112pub struct StorageDeviceListWrapper {
113 pub storage_device: Vec<ServerStorageDevice>,
114}
115
116impl Default for StorageDeviceListWrapper {
117 fn default() -> Self {
118 Self {
119 storage_device: Vec::new()
120 }
121 }
122}
123
124#[derive(Debug, Serialize, Deserialize)]
125pub struct IPAddress {
126 pub access: String,
127 pub family: String,
128 pub address: String,
129 pub ptr_record: String,
130 pub server: String,
131 pub floating: Option<bool>,
132 pub mac: Option<String>,
133 pub network: Option<String>,
134}
135
136#[derive(Debug, Serialize, Clone, Deserialize)]
137pub struct ServerStorageDevice {
138 pub address: String,
139 #[serde(rename = "part_of_plan")]
140 pub part_of_plan: String,
141 pub labels: Vec<Label>,
142 pub storage: String,
143 #[serde(rename = "storage_size")]
144 pub storage_size: i32,
145 #[serde(rename = "storage_encrypted")]
146 pub storage_encrypted: String,
147 #[serde(rename = "storage_tier")]
148 pub storage_tier: String,
149 #[serde(rename = "storage_title")]
150 pub storage_title: String,
151 #[serde(skip_serializing_if = "Option::is_none", rename = "type")]
152 pub storage_type: Option<String>,
153 #[serde(rename = "boot_disk")]
154 pub boot_disk: String,
155}
156
157#[derive(Debug, Serialize, Deserialize)]
158pub struct NetworkInterface {
159 #[serde(skip_serializing_if = "Option::is_none")]
160 pub index: Option<i32>,
161 #[serde(skip_serializing_if = "Option::is_none")]
162 pub ip_addresses: Option<Vec<IPAddress>>,
163 #[serde(skip_serializing_if = "Option::is_none", rename = "type")]
164 pub interface_type: Option<String>,
165 #[serde(skip_serializing_if = "Option::is_none")]
166 pub network: Option<String>,
167 #[serde(skip_serializing_if = "Option::is_none")]
168 pub mac: Option<String>,
169 #[serde(skip_serializing_if = "Option::is_none")]
170 pub source_ip_filtering: Option<bool>,
171 #[serde(skip_serializing_if = "Option::is_none")]
172 pub bootable: Option<bool>,
173}
174
175#[derive(Debug, Serialize, Deserialize)]
176pub struct ServerNetworking {
177 pub interfaces: Vec<NetworkInterface>,
178}
179
180#[derive(Debug, Default, Serialize)]
181pub struct ServerRequest {
182 #[serde(skip_serializing_if = "Option::is_none")]
183 pub avoid_host: Option<i32>,
184 #[serde(skip_serializing_if = "Option::is_none")]
185 pub host: Option<i32>,
186 #[serde(skip_serializing_if = "Option::is_none")]
187 pub boot_order: Option<String>,
188 #[serde(skip_serializing_if = "Option::is_none")]
189 pub core_number: Option<i32>,
190 #[serde(skip_serializing_if = "Option::is_none")]
191 pub firewall: Option<String>,
192 pub hostname: String,
193 #[serde(skip_serializing_if = "Option::is_none")]
194 pub labels: Option<Labels>,
195 pub login_user: LoginUser,
196 #[serde(skip_serializing_if = "Option::is_none")]
197 pub memory_amount: Option<i32>,
198 #[serde(skip_serializing_if = "Option::is_none")]
199 pub metadata: Option<String>,
200 #[serde(skip_serializing_if = "Option::is_none")]
201 pub nic_model: Option<String>,
202 #[serde(skip_serializing_if = "Option::is_none")]
203 pub networking: Option<CreateServerNetworking>,
204 #[serde(skip_serializing_if = "Option::is_none")]
205 pub password_delivery: Option<String>,
206 #[serde(skip_serializing_if = "Option::is_none")]
207 pub plan: Option<String>,
208 #[serde(skip_serializing_if = "Option::is_none")]
209 pub server_group: Option<String>,
210 #[serde(skip_serializing_if = "Option::is_none")]
211 pub simple_backup: Option<String>,
212 #[serde(rename = "storage_devices")]
213 pub storage_devices: StorageDeviceWrapper,
214 #[serde(skip_serializing_if = "Option::is_none")]
215 pub timezone: Option<String>,
216 pub title: String,
217 #[serde(skip_serializing_if = "Option::is_none")]
218 pub user_data: Option<String>,
219 #[serde(skip_serializing_if = "Option::is_none")]
220 pub video_model: Option<String>,
221 #[serde(skip_serializing_if = "Option::is_none")]
222 pub remote_access_enabled: Option<bool>,
223 #[serde(skip_serializing_if = "Option::is_none")]
224 pub remote_access_type: Option<String>,
225 #[serde(skip_serializing_if = "Option::is_none")]
226 pub remote_access_password: Option<String>,
227 pub zone: String,
228}
229
230#[derive(Debug, Default, Serialize)]
231pub struct CreateServerRequest {
232 pub server: ServerRequest,
233}
234
235impl CreateServerRequest {
236 pub fn new() -> Self {
237 Self::default()
238 }
239
240 pub fn with_zone(mut self, zone: impl Into<String>) -> Self {
241 self.server.zone = zone.into();
242 self
243 }
244
245 pub fn with_hostname(mut self, hostname: impl Into<String>) -> Self {
246 self.server.hostname = hostname.into();
247 self
248 }
249
250 pub fn with_title(mut self, title: impl Into<String>) -> Self {
251 self.server.title = title.into();
252 self
253 }
254
255 pub fn with_plan(mut self, plan: impl Into<String>) -> Self {
256 self.server.plan = Some(plan.into());
257 self
258 }
259
260 pub fn with_core_number(mut self, core_number: i32) -> Self {
261 self.server.core_number = Some(core_number);
262 self
263 }
264
265 pub fn with_memory_amount(mut self, memory_amount: i32) -> Self {
266 self.server.memory_amount = Some(memory_amount);
267 self
268 }
269
270 pub fn with_storage_device(mut self, device: CreateServerStorageDevice) -> Self {
271 self.server.storage_devices.storage_device.push(device);
272 self
273 }
274
275 pub fn with_networking(mut self, networking: CreateServerNetworking) -> Self {
276 self.server.networking = Some(networking);
277 self
278 }
279
280 pub fn with_login_user(mut self, login_user: LoginUser) -> Self {
281 self.server.login_user = login_user;
282 self
283 }
284
285 pub fn with_user_data(mut self, user_data: String) -> Self {
286 self.server.user_data = Some(user_data);
287 self
288 }
289
290 pub fn with_avoid_host(mut self, avoid_host: i32) -> Self {
291 self.server.avoid_host = Some(avoid_host);
292 self
293 }
294
295 pub fn with_host(mut self, host: i32) -> Self {
296 self.server.host = Some(host);
297 self
298 }
299
300 pub fn with_boot_order(mut self, boot_order: String) -> Self {
301 self.server.boot_order = Some(boot_order);
302 self
303 }
304
305 pub fn with_firewall(mut self, firewall: String) -> Self {
306 self.server.firewall = Some(firewall);
307 self
308 }
309
310 pub fn with_labels(mut self, labels: Labels) -> Self {
311 self.server.labels = Some(labels);
312 self
313 }
314
315 pub fn with_metadata(mut self, metadata: impl Into<String>) -> Self {
316 self.server.metadata = Some(metadata.into());
317 self
318 }
319
320 pub fn with_nic_model(mut self, nic_model: String) -> Self {
321 self.server.nic_model = Some(nic_model);
322 self
323 }
324
325 pub fn with_password_delivery(mut self, password_delivery: String) -> Self {
326 self.server.password_delivery = Some(password_delivery);
327 self
328 }
329
330 pub fn with_server_group(mut self, server_group: String) -> Self {
331 self.server.server_group = Some(server_group);
332 self
333 }
334
335 pub fn with_simple_backup(mut self, simple_backup: String) -> Self {
336 self.server.simple_backup = Some(simple_backup);
337 self
338 }
339
340 pub fn with_timezone(mut self, timezone: String) -> Self {
341 self.server.timezone = Some(timezone);
342 self
343 }
344
345 pub fn with_video_model(mut self, video_model: String) -> Self {
346 self.server.video_model = Some(video_model);
347 self
348 }
349
350 pub fn with_remote_access(
351 mut self,
352 enabled: bool,
353 access_type: Option<String>,
354 password: Option<String>,
355 ) -> Self {
356 self.server.remote_access_enabled = Some(enabled);
357 self.server.remote_access_type = access_type;
358 self.server.remote_access_password = password;
359 self
360 }
361
362 pub fn build(mut self) -> CreateServerRequest {
363 if self.server.networking.is_none() {
365 self.server.networking = Some(
366 CreateServerNetworking::new()
367 .with_interface(
368 CreateServerInterface::new("public")
369 .with_ip_address("IPv4", None)
370 .with_index(1)
371 )
372 );
373 }
374 CreateServerRequest {
375 server: self.server
376 }
377 }
378}
379
380#[derive(Debug, Default, Serialize)]
381pub struct CreateServerStorageDevice {
382 pub action: String,
383 pub address: Option<String>,
384 #[serde(serialize_with = "serialize_bool_as_yes_no", deserialize_with = "deserialize_yes_no_as_bool")]
385 pub encrypted: Option<bool>,
386 pub storage: String,
387 pub title: Option<String>,
388 pub size: Option<i32>,
390 pub tier: Option<String>,
391 #[serde(rename = "type")]
392 pub storage_type: Option<String>,
393}
394
395impl CreateServerStorageDevice {
396 pub fn new(action: impl Into<String>, storage: impl Into<String>) -> Self {
397 Self {
398 action: action.into(),
399 storage: storage.into(),
400 ..Default::default()
401 }
402 }
403
404 pub fn from_template(template_uuid: impl Into<String>) -> Self {
405 Self::new(
406 CREATE_SERVER_STORAGE_DEVICE_ACTION_CLONE.to_string(),
407 template_uuid.into()
408 )
409 .with_title("System Disk")
410 }
411
412 pub fn with_size(mut self, size: i32) -> Self {
413 self.size = Some(size);
414 self
415 }
416
417 pub fn with_tier(mut self, tier: impl Into<String>) -> Self {
418 self.tier = Some(tier.into());
419 self
420 }
421
422 pub fn with_title(mut self, title: impl Into<String>) -> Self {
423 self.title = Some(title.into());
424 self
425 }
426
427 pub fn with_encrypted(mut self, encrypted: bool) -> Self {
428 self.encrypted = Some(encrypted);
429 self
430 }
431
432 pub fn with_address(mut self, address: impl Into<String>) -> Self {
433 self.address = Some(address.into());
434 self
435 }
436}
437
438#[derive(Debug, Serialize, Clone, Deserialize)]
439pub struct CreateServerNetworking {
440 pub interfaces: InterfaceWrapper,
441}
442
443#[derive(Debug, Default, Serialize, Clone, Deserialize)]
444pub struct InterfaceWrapper {
445 pub interface: Vec<CreateServerInterface>,
446}
447
448#[derive(Debug, Serialize, Clone, Deserialize)]
449pub struct CreateServerInterface {
450 pub ip_addresses: IPAddressWrapper,
451 #[serde(rename = "type")]
452 pub interface_type: String,
453 #[serde(skip_serializing_if = "Option::is_none")]
454 pub network: Option<String>,
455 #[serde(skip_serializing_if = "Option::is_none")]
456 pub source_ip_filtering: Option<String>,
457 #[serde(skip_serializing_if = "Option::is_none")]
458 pub bootable: Option<String>,
459 #[serde(skip_serializing_if = "Option::is_none")]
460 pub index: Option<i32>,
461}
462
463#[derive(Debug, Serialize, Clone, Deserialize)]
464pub struct CreateServerIPAddress {
465 pub family: Option<String>,
466 pub address: Option<String>,
467}
468
469#[derive(Debug, Default, Clone, Serialize, Deserialize)]
470pub struct IPAddressWrapper {
471 pub ip_address: Vec<CreateServerIPAddress>,
472}
473
474#[derive(Debug, Serialize)]
475pub struct LoginUser {
476 pub username: String,
477 #[serde(skip_serializing_if = "Option::is_none")]
478 pub ssh_keys: Option<SSHKey>,
479 #[serde(skip_serializing_if = "Option::is_none")]
480 pub create_password: Option<String>,
481}
482
483#[derive(Debug, Serialize)]
484pub struct SSHKey {
485 pub ssh_key: Vec<String>,
486}
487
488impl LoginUser {
489 pub fn new(username: impl Into<String>) -> Self {
490 Self {
491 username: username.into(),
492 ssh_keys: None,
493 create_password: Some("yes".to_string()),
494 }
495 }
496
497 pub fn with_ssh_key(self, key: impl Into<String>) -> Self {
498 self.with_ssh_keys(vec![key.into()])
499 }
500
501 pub fn with_ssh_keys(mut self, keys: impl Into<Vec<String>>) -> Self {
502 match &mut self.ssh_keys {
503 Some(ssh_keys) => ssh_keys.ssh_key.extend(keys.into()),
504 None => self.ssh_keys = Some(SSHKey { ssh_key: keys.into() }),
505 }
506 self
507 }
508
509 pub fn with_create_password(mut self, create: bool) -> Self {
510 self.create_password = Some(if create { "yes" } else { "no" }.to_string());
511 self
512 }
513}
514
515impl Default for LoginUser {
516 fn default() -> Self {
517 Self {
518 username: "root".to_string(),
519 ssh_keys: None,
520 create_password: Some("yes".to_string()),
521 }
522 }
523}
524
525#[derive(Debug, Serialize)]
526pub struct StartServerRequest {
527 pub host: Option<i32>,
528 pub avoid_host: Option<i32>,
529}
530
531#[derive(Debug, Deserialize)]
532pub struct StartServerResponse {
533 pub server: ServerDetails,
534}
535
536#[derive(Debug, Serialize)]
537pub struct StopServerRequest {
538 pub stop_type: Option<String>,
539 pub timeout: Option<i64>,
540}
541
542#[derive(Debug, Deserialize)]
543pub struct StopServerResponse {
544 pub server: ServerDetails,
545}
546
547#[derive(Debug, Serialize)]
548pub struct RestartServerRequest {
549 pub stop_type: Option<String>,
550 pub timeout: Option<i64>,
551 pub timeout_action: Option<String>,
552 pub host: Option<i32>,
553}
554
555#[derive(Debug, Deserialize)]
556pub struct RestartServerResponse {
557 pub server: ServerDetails,
558}
559
560#[derive(Debug, Serialize)]
561pub struct ModifyServerRequest {
562 pub boot_order: Option<String>,
563 pub core_number: Option<i32>,
564 pub memory_amount: Option<i32>,
565 pub title: Option<String>,
566 pub zone: Option<String>,
567 }
569
570#[derive(Debug, Deserialize)]
571pub struct ModifyServerResponse {
572 pub server: ServerDetails,
573}
574
575#[derive(Debug, Serialize)]
576pub struct StorageDeviceWrapper {
577 pub storage_device: Vec<CreateServerStorageDevice>,
578}
579
580impl Default for StorageDeviceWrapper {
581 fn default() -> Self {
582 Self {
583 storage_device: Vec::new()
584 }
585 }
586}
587
588fn deserialize_yes_no_as_bool<'de, D>(deserializer: D) -> Result<bool, D::Error>
589where
590 D: serde::Deserializer<'de>,
591{
592 let s = String::deserialize(deserializer)?;
593 Ok(s == "yes")
594}
595
596fn serialize_bool_as_yes_no<S>(value: &Option<bool>, serializer: S) -> Result<S::Ok, S::Error>
597where
598 S: serde::Serializer,
599{
600 match value {
601 Some(true) => serializer.serialize_str("yes"),
602 Some(false) => serializer.serialize_str("no"),
603 None => serializer.serialize_none(),
604 }
605}
606
607impl CreateServerNetworking {
609 pub fn new() -> Self {
610 Self {
611 interfaces: InterfaceWrapper { interface: Vec::new() }
612 }
613 }
614
615 pub fn with_interface(mut self, interface: CreateServerInterface) -> Self {
616 self.interfaces.interface.push(interface);
617 self
618 }
619}
620
621impl CreateServerInterface {
622 pub fn new(interface_type: impl Into<String>) -> Self {
623 Self {
624 ip_addresses: IPAddressWrapper { ip_address: Vec::new() },
625 interface_type: interface_type.into(),
626 network: None,
627 source_ip_filtering: None,
628 bootable: None,
629 index: None,
630 }
631 }
632
633 pub fn with_ip_address(mut self, family: impl Into<String>, address: Option<String>) -> Self {
634 self.ip_addresses.ip_address.push(CreateServerIPAddress {
635 family: Some(family.into()),
636 address,
637 });
638 self
639 }
640
641 pub fn with_source_ip_filtering(mut self, enabled: bool) -> Self {
642 self.source_ip_filtering = Some(if enabled { "yes" } else { "no" }.to_string());
643 self
644 }
645
646 pub fn with_bootable(mut self, bootable: bool) -> Self {
647 self.bootable = Some(if bootable { "yes" } else { "no" }.to_string());
648 self
649 }
650
651 pub fn with_index(mut self, index: i32) -> Self {
652 self.index = Some(index);
653 self
654 }
655}