f40ef6b7c0
Align Cloudly with the current typedserver, smartconfig, smartstate, and Docker tooling releases so builds and Docker output stay compatible with the upgraded stack.
114 lines
3.2 KiB
TypeScript
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;
|
|
}
|
|
}
|