proxmox-dashboard/lib/src/proxmox_webservice/service.dart

139 lines
3.4 KiB

import 'dart:convert' as convert;
import 'package:http/http.dart' as http;
10 months ago
import 'package:pi_dashboard/logger.dart';
import 'model.dart';
class ProxmoxWebService {
ProxmoxWebService({
this.hostname = "",
this.username = "",
this.password = "",
});
final String hostname;
final String username;
final String password;
String? _csrfToken;
String? _ticket;
bool _authenticated = false;
Future<bool> authenticate() async {
final resp = await http.post(
Uri.https(
hostname,
"/api2/json/access/ticket",
{
'username': username,
'password': password,
},
),
);
if (resp.statusCode == 200) {
final body = convert.jsonDecode(resp.body) as Map<String, dynamic>;
final data = body["data"] as Map<String, dynamic>;
_csrfToken = data["CSRFPreventionToken"];
_ticket = data["ticket"];
_authenticated = true;
} else {
_authenticated = false;
10 months ago
Log().info(
"Authentication returned error code ${resp.statusCode}: ${resp.body}");
}
return _authenticated;
}
10 months ago
Future<Map<String, dynamic>?> _doGet(String endpoint) async {
if (!_authenticated) return null;
final resp = await http.get(
Uri.https(
hostname,
endpoint,
),
headers: {
"CSRFPreventionToken": _csrfToken as String,
"Cookie": "PVEAuthCookie=$_ticket"
});
10 months ago
if (resp.statusCode != 200) {
Log().info("Get returned error code ${resp.statusCode}: ${resp.body}");
return null;
}
return convert.jsonDecode(resp.body) as Map<String, dynamic>;
}
Future<Map<String, dynamic>?> _doPost(
String endpoint, Map<String, dynamic> payload,
{debug = false}) async {
if (!_authenticated) return null;
final resp = await http.post(
Uri.https(
hostname,
endpoint,
),
headers: {
"CSRFPreventionToken": _csrfToken as String,
"Cookie": "PVEAuthCookie=$_ticket"
},
body: payload,
);
10 months ago
if (resp.statusCode != 200) {
Log().info("Post returned error code ${resp.statusCode}: ${resp.body}");
return null;
}
return convert.jsonDecode(resp.body) as Map<String, dynamic>;
}
Future<List<ProxmoxNode>> listNodes() async {
10 months ago
Log().debug("Querying nodes");
List<ProxmoxNode> nodes = [];
final resp = await _doGet("/api2/json/nodes");
if (resp == null) return [];
for (final nodeJson in resp["data"]) {
nodes.add(ProxmoxNode.fromJson(nodeJson as Map<String, dynamic>));
}
return nodes;
}
Future<List<ProxmoxVm>> listVms(String node) async {
10 months ago
Log().debug("Querying vms");
List<ProxmoxVm> vms = [];
final resp = await _doGet("/api2/json/nodes/$node/qemu");
if (resp == null) return [];
for (final vmJson in resp["data"]) {
vms.add(ProxmoxVm.fromJson(vmJson as Map<String, dynamic>));
}
vms.sort((a, b) => a.vmid.compareTo(b.vmid));
return vms;
}
Future<bool> toggleVm(ProxmoxNode node, ProxmoxVm vm) async {
if (!_authenticated) return false;
10 months ago
final isRunning = vm.status == "running";
Log().info("toggling VM: ${isRunning ? "stopping" : "starting"}");
final endpoint =
10 months ago
"/api2/json/nodes/${node.node}/qemu/${vm.vmid}/status/${isRunning ? "stop" : "start"}";
final resp = await _doPost(endpoint, {}, debug: true);
if (resp == null) return false;
return true;
}
}