Files
phpsite/netbox_integration/netbox_api.php
alex 8c069ee82a Add usernames and sudo_usernames fields to VM request form
- DB: add usernames/sudo_usernames columns to vm_requests table
- create.php: add form inputs for usernames and sudo_usernames
- send.php: capture, validate, and store both fields in DB
- netbox_integration/netbox_api.php: pass custom_fields to NetBox VM API
- requests.php: show usernames/sudo_usernames in request list
2026-05-09 23:57:36 +02:00

148 lines
4.5 KiB
PHP
Executable File

<?php
/**
* NetBox Virtualization API Client
* Creates Virtual Machines (not physical devices) in NetBox.
*/
class NetBoxClient {
private $baseUrl;
private $token;
public function __construct($baseUrl, $token) {
$this->baseUrl = rtrim($baseUrl, '/');
$this->token = $token;
}
private function headers() {
$h = [
'Content-Type: application/json',
'Accept: application/json',
];
if ($this->token) {
$h[] = 'Authorization: Token ' . $this->token;
}
return $h;
}
private function request($method, $endpoint, $body = null) {
$url = $this->baseUrl . '/api/' . ltrim($endpoint, '/');
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => $this->headers(),
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_CUSTOMREQUEST => strtoupper($method),
]);
if ($body !== null) {
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($body));
}
$resp = curl_exec($ch);
$info = curl_getinfo($ch);
curl_close($ch);
if ($info['http_code'] >= 400) {
throw new Exception("NetBox API {$method} {$endpoint} failed (HTTP {$info['http_code']}): {$resp}");
}
return json_decode($resp, true);
}
/**
* Get list endpoint (handles pagination for small result sets).
*/
public function getList($endpoint) {
$results = [];
$url = $endpoint . '?limit=100';
while ($url) {
$page = $this->request('get', $url);
foreach (($page['results'] ?? []) as $item) {
$results[] = $item;
}
$url = $page['next'] ?? null;
// Normalize next URL — NetBox returns absolute URLs
if ($url && strpos($url, 'http') === 0) {
$url = str_replace($this->baseUrl . '/api/', '', $url);
}
}
return $results;
}
public function post($endpoint, $data) {
return $this->request('post', $endpoint, $data);
}
/**
* Find a tag by name; returns the tag array or null.
*/
public function findTag($name) {
$tags = $this->getList('/extras/tags/');
foreach ($tags as $tag) {
if ($tag['name'] === $name) {
return $tag;
}
}
return null;
}
/**
* Find a cluster by name; returns the cluster array or null.
*/
public function findCluster($name) {
$clusters = $this->getList('/virtualization/clusters/');
foreach ($clusters as $c) {
if ($c['name'] === $name) {
return $c;
}
}
return null;
}
/**
* Create a Virtual Machine in NetBox.
*
* NetBox virtualization VM API uses:
* - vcpus: float (e.g. 2.0)
* - memory: int in MB (e.g. 4096)
* - disk: int in MB (e.g. 51200)
* - cluster: required (int id)
* - tags: array of tag names to look up
*/
public function createVirtualMachine(array $params) {
$payload = [
'name' => $params['name'],
'cluster' => $params['cluster_id'],
'status' => $params['status'] ?? 'active',
'vcpus' => (float) $params['vcpus'],
'memory' => (int) ($params['ram_gb'] * 1024), // GB -> MB
'disk' => (int) ($params['disk_gb'] * 1024), // GB -> MB
'description' => $params['description'] ?? '',
];
// Custom fields: usernames and sudo_usernames
$cf = [];
if (!empty($params['usernames'])) {
$cf['usernames'] = $params['usernames'];
}
if (!empty($params['sudo_usernames'])) {
$cf['sudo_usernames'] = $params['sudo_usernames'];
}
if (!empty($cf)) {
$payload['custom_fields'] = $cf;
}
// Tag lookup for domain — tags must be numeric IDs in the NetBox API
if (!empty($params['domain'])) {
$tag = $this->findTag($params['domain']);
if ($tag) {
$payload['tags'] = [$tag['id']];
} else {
error_log("NetBox: tag '{$params['domain']}' not found — creating VM without domain tag.");
}
}
$result = $this->post('/virtualization/virtual-machines/', $payload);
return $result;
}
}