Files
vultr-api/vultr_api/resources/bare_metal.py
HWANG BYUNGHA 184054c6c1 Initial commit: Vultr API v2 Python wrapper with FastAPI server
- vultr_api/: Python library wrapping Vultr API v2
  - 17 resource modules (instances, dns, firewall, vpc, etc.)
  - Pagination support, error handling

- server/: FastAPI REST server
  - All API endpoints exposed via HTTP
  - X-API-Key header authentication
  - Swagger docs at /docs

- Podman quadlet config for systemd deployment

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-22 01:08:17 +09:00

292 lines
8.4 KiB
Python

"""
Bare Metal Resource
Bare metal server management
"""
from typing import Dict, List
from .base import BaseResource
class BareMetalResource(BaseResource):
"""
Bare metal server management
Usage:
# List bare metal servers
servers = client.bare_metal.list()
# Create server
server = client.bare_metal.create(
region="ewr",
plan="vbm-4c-32gb",
os_id=215
)
"""
def list(
self,
per_page: int = 100,
cursor: str = None,
tag: str = None,
label: str = None,
main_ip: str = None,
region: str = None,
) -> Dict:
"""
List bare metal servers
Returns:
Dict with 'bare_metals' list and 'meta' pagination
"""
params = {"per_page": per_page}
if cursor:
params["cursor"] = cursor
if tag:
params["tag"] = tag
if label:
params["label"] = label
if main_ip:
params["main_ip"] = main_ip
if region:
params["region"] = region
return self.client.get("bare-metals", params=params)
def list_all(self, **kwargs) -> List[Dict]:
"""List all bare metal servers (auto-paginate)"""
return self.client.paginate("bare-metals", "bare_metals", params=kwargs)
def get(self, baremetal_id: str) -> Dict:
"""
Get bare metal server details
Args:
baremetal_id: Bare metal ID
Returns:
Server details
"""
response = self.client.get(f"bare-metals/{baremetal_id}")
return response.get("bare_metal", {})
def create(
self,
region: str,
plan: str,
os_id: int = None,
script_id: str = None,
snapshot_id: str = None,
enable_ipv6: bool = False,
label: str = None,
sshkey_id: List[str] = None,
app_id: int = None,
image_id: str = None,
user_data: str = None,
activation_email: bool = False,
hostname: str = None,
tag: str = None,
tags: List[str] = None,
reserved_ipv4: str = None,
persistent_pxe: bool = False,
attach_vpc2: List[str] = None,
) -> Dict:
"""
Create a bare metal server
Args:
region: Region ID
plan: Plan ID
os_id: Operating System ID
script_id: Startup script ID
snapshot_id: Snapshot ID
enable_ipv6: Enable IPv6
label: Server label
sshkey_id: SSH key IDs
app_id: Application ID
image_id: Custom image ID
user_data: Cloud-init user data
activation_email: Send activation email
hostname: Server hostname
tag: Deprecated, use tags
tags: Tags
reserved_ipv4: Reserved IPv4 to assign
persistent_pxe: Enable persistent PXE
attach_vpc2: VPC 2.0 IDs to attach
Returns:
Created server details
"""
data = {"region": region, "plan": plan}
if os_id is not None:
data["os_id"] = os_id
if script_id:
data["script_id"] = script_id
if snapshot_id:
data["snapshot_id"] = snapshot_id
if enable_ipv6:
data["enable_ipv6"] = enable_ipv6
if label:
data["label"] = label
if sshkey_id:
data["sshkey_id"] = sshkey_id
if app_id is not None:
data["app_id"] = app_id
if image_id:
data["image_id"] = image_id
if user_data:
data["user_data"] = user_data
if activation_email:
data["activation_email"] = activation_email
if hostname:
data["hostname"] = hostname
if tag:
data["tag"] = tag
if tags:
data["tags"] = tags
if reserved_ipv4:
data["reserved_ipv4"] = reserved_ipv4
if persistent_pxe:
data["persistent_pxe"] = persistent_pxe
if attach_vpc2:
data["attach_vpc2"] = attach_vpc2
response = self.client.post("bare-metals", data)
return response.get("bare_metal", {})
def update(
self,
baremetal_id: str,
user_data: str = None,
label: str = None,
tag: str = None,
tags: List[str] = None,
os_id: int = None,
app_id: int = None,
image_id: str = None,
enable_ipv6: bool = None,
) -> Dict:
"""
Update a bare metal server
Args:
baremetal_id: Bare metal ID
(other args same as create)
Returns:
Updated server details
"""
data = {}
if user_data is not None:
data["user_data"] = user_data
if label is not None:
data["label"] = label
if tag is not None:
data["tag"] = tag
if tags is not None:
data["tags"] = tags
if os_id is not None:
data["os_id"] = os_id
if app_id is not None:
data["app_id"] = app_id
if image_id is not None:
data["image_id"] = image_id
if enable_ipv6 is not None:
data["enable_ipv6"] = enable_ipv6
response = self.client.patch(f"bare-metals/{baremetal_id}", data)
return response.get("bare_metal", {})
def delete(self, baremetal_id: str) -> None:
"""
Delete a bare metal server
Args:
baremetal_id: Bare metal ID to delete
"""
self.client.delete(f"bare-metals/{baremetal_id}")
def start(self, baremetal_id: str) -> None:
"""Start a bare metal server"""
self.client.post(f"bare-metals/{baremetal_id}/start")
def halt(self, baremetal_id: str) -> None:
"""Halt a bare metal server"""
self.client.post(f"bare-metals/{baremetal_id}/halt")
def reboot(self, baremetal_id: str) -> None:
"""Reboot a bare metal server"""
self.client.post(f"bare-metals/{baremetal_id}/reboot")
def reinstall(self, baremetal_id: str, hostname: str = None) -> Dict:
"""
Reinstall a bare metal server
Args:
baremetal_id: Bare metal ID
hostname: New hostname (optional)
Returns:
Server details
"""
data = {}
if hostname:
data["hostname"] = hostname
response = self.client.post(f"bare-metals/{baremetal_id}/reinstall", data)
return response.get("bare_metal", {})
def get_bandwidth(self, baremetal_id: str) -> Dict:
"""Get bandwidth usage"""
return self.client.get(f"bare-metals/{baremetal_id}/bandwidth")
def get_user_data(self, baremetal_id: str) -> Dict:
"""Get user data"""
return self.client.get(f"bare-metals/{baremetal_id}/user-data")
def get_upgrades(self, baremetal_id: str, upgrade_type: str = None) -> Dict:
"""Get available upgrades"""
params = {}
if upgrade_type:
params["type"] = upgrade_type
return self.client.get(f"bare-metals/{baremetal_id}/upgrades", params=params)
def get_vnc(self, baremetal_id: str) -> Dict:
"""Get VNC URL"""
return self.client.get(f"bare-metals/{baremetal_id}/vnc")
# IPv4 management
def list_ipv4(self, baremetal_id: str) -> List[Dict]:
"""List IPv4 addresses"""
response = self.client.get(f"bare-metals/{baremetal_id}/ipv4")
return response.get("ipv4s", [])
def list_ipv6(self, baremetal_id: str) -> List[Dict]:
"""List IPv6 addresses"""
response = self.client.get(f"bare-metals/{baremetal_id}/ipv6")
return response.get("ipv6s", [])
# VPC 2.0
def list_vpc2(self, baremetal_id: str) -> List[Dict]:
"""List attached VPC 2.0 networks"""
response = self.client.get(f"bare-metals/{baremetal_id}/vpc2")
return response.get("vpcs", [])
def attach_vpc2(
self,
baremetal_id: str,
vpc_id: str,
ip_address: str = None
) -> None:
"""Attach VPC 2.0 to bare metal"""
data = {"vpc_id": vpc_id}
if ip_address:
data["ip_address"] = ip_address
self.client.post(f"bare-metals/{baremetal_id}/vpc2/attach", data)
def detach_vpc2(self, baremetal_id: str, vpc_id: str) -> None:
"""Detach VPC 2.0 from bare metal"""
self.client.post(f"bare-metals/{baremetal_id}/vpc2/detach", {"vpc_id": vpc_id})