Files
cloudly/ts/manager.baremetal/classes.baremetal.ts
T
jkunz f40ef6b7c0 chore: update cloudly dependency stack
Align Cloudly with the current typedserver, smartconfig, smartstate, and Docker tooling releases so builds and Docker output stay compatible with the upgraded stack.
2026-05-08 13:56:20 +00:00

114 lines
3.2 KiB
TypeScript

import * as plugins from '../plugins.js';
/**
* BareMetal represents an actual physical server
*/
@plugins.smartdata.Manager()
export class BareMetal extends plugins.smartdata.SmartDataDbDoc<
BareMetal,
plugins.servezoneInterfaces.data.IBareMetal
> {
// STATIC
public static async createFromHetznerServer(
hetznerServerArg: plugins.hetznercloud.HetznerServer,
) {
const serverData = hetznerServerArg.data;
if (!serverData) {
throw new Error('Hetzner server response is missing server data');
}
const ipv4 = serverData.public_net.ipv4;
if (!ipv4) {
throw new Error(`Hetzner server ${serverData.id} has no primary IPv4 address`);
}
const newBareMetal = new BareMetal();
newBareMetal.id = plugins.smartunique.shortId(8);
const data: plugins.servezoneInterfaces.data.IBareMetal['data'] = {
hostname: serverData.name,
primaryIp: ipv4.ip,
provider: 'hetzner',
location: serverData.datacenter.name,
specs: {
cpuModel: serverData.server_type.cpu_type,
cpuCores: serverData.server_type.cores,
memoryGB: serverData.server_type.memory,
storageGB: serverData.server_type.disk,
storageType: 'nvme',
},
powerState: serverData.status === 'running' ? 'on' : 'off',
osInfo: {
name: 'Debian',
version: '12',
},
assignedNodeIds: [],
providerMetadata: {
hetznerServerId: serverData.id,
hetznerServerName: serverData.name,
},
};
Object.assign(newBareMetal, { data });
await newBareMetal.save();
return newBareMetal;
}
// INSTANCE
@plugins.smartdata.unI()
public id!: string;
@plugins.smartdata.svDb()
public data!: plugins.servezoneInterfaces.data.IBareMetal['data'];
constructor() {
super();
}
public async assignNode(nodeId: string) {
if (!this.data.assignedNodeIds.includes(nodeId)) {
this.data.assignedNodeIds.push(nodeId);
await this.save();
}
}
public async removeNode(nodeId: string) {
this.data.assignedNodeIds = this.data.assignedNodeIds.filter(id => id !== nodeId);
await this.save();
}
public async updatePowerState(state: 'on' | 'off' | 'unknown') {
this.data.powerState = state;
await this.save();
}
public async powerOn(): Promise<boolean> {
// TODO: Implement IPMI power on
if (this.data.ipmiAddress && this.data.ipmiCredentials) {
// Implement IPMI power on command
console.log(`Powering on BareMetal ${this.id} via IPMI`);
await this.updatePowerState('on');
return true;
}
return false;
}
public async powerOff(): Promise<boolean> {
// TODO: Implement IPMI power off
if (this.data.ipmiAddress && this.data.ipmiCredentials) {
// Implement IPMI power off command
console.log(`Powering off BareMetal ${this.id} via IPMI`);
await this.updatePowerState('off');
return true;
}
return false;
}
public async reset(): Promise<boolean> {
// TODO: Implement IPMI reset
if (this.data.ipmiAddress && this.data.ipmiCredentials) {
// Implement IPMI reset command
console.log(`Resetting BareMetal ${this.id} via IPMI`);
return true;
}
return false;
}
}