You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
295 lines
7.6 KiB
Plaintext
295 lines
7.6 KiB
Plaintext
package main
|
|
|
|
import "core:encoding/ini"
|
|
import "core:encoding/json"
|
|
import "core:fmt"
|
|
import "core:log"
|
|
import "core:mem"
|
|
import "core:os"
|
|
import "core:strconv"
|
|
import "core:strings"
|
|
import "core:time"
|
|
|
|
import "libs/http"
|
|
import "libs/http/client"
|
|
import "libs/sysinfo"
|
|
|
|
CONFIG_FILE_PATH :: "./config.ini"
|
|
|
|
PC: Program_Config = {}
|
|
|
|
api_request_get :: proc(endpoint: string) -> (body: client.Body_Type, allocation: bool, ok: bool) {
|
|
request: client.Request
|
|
client.request_init(&request, .Get)
|
|
defer client.request_destroy(&request)
|
|
|
|
response, err := client.request(&request, endpoint)
|
|
if err != nil {
|
|
return nil, false, false
|
|
}
|
|
defer client.response_destroy(&response)
|
|
|
|
body_err: client.Body_Error
|
|
body, allocation, body_err = client.response_body(&response)
|
|
if body_err != nil {
|
|
return nil, false, false
|
|
}
|
|
|
|
return body, allocation, true
|
|
}
|
|
|
|
// api_request_post :: proc(endpoint: string, post_body: any) -> (body: client.Body_Type, allocation: bool, ok: bool) {
|
|
// request: client.Request
|
|
// client.requset_init(&request, .Post)
|
|
// defer client.request_destroy(&request)
|
|
|
|
// if err := client.with_json(&request, post_body); err != nil do return nil, false, false
|
|
|
|
// response, err := client.request(&request, endpoint)
|
|
// if err != nil do return nil, false, false
|
|
// defer client.response_destroy(&response)
|
|
|
|
// }
|
|
|
|
// Returns the host ID, or if the host doesn't exist in
|
|
// LSM then it will return -1
|
|
get_host_id :: proc(hostname: string) -> (host_id: int, ok: bool) {
|
|
request: client.Request
|
|
client.request_init(&request, .Get)
|
|
defer client.request_destroy(&request)
|
|
|
|
endpoint := fmt.tprintf("%s/hosts/get_host_id_for_hostname/%s", PC.api_address, hostname)
|
|
response, err := client.request(&request, endpoint)
|
|
if err != nil {
|
|
return 0, false
|
|
}
|
|
defer client.response_destroy(&response)
|
|
|
|
body, allocation, body_err := client.response_body(&response)
|
|
if body_err != nil {
|
|
return 0, false
|
|
}
|
|
|
|
if response.status == .Not_Found && strings.contains(body.(client.Body_Plain), "record not found") {
|
|
return -1, true
|
|
} else if response.status != .OK {
|
|
return 0, false
|
|
}
|
|
|
|
host_id = strconv.atoi(body.(client.Body_Plain))
|
|
|
|
return host_id, true
|
|
}
|
|
|
|
get_cpus_for_host_from_id :: proc(host_id: int) -> (cpus: [dynamic]CPU, ok: bool) {
|
|
endpoint := fmt.tprintf("%s/cpus/get_cpus_by_host_id/%d", PC.api_address, host_id)
|
|
|
|
body, allocation, request_ok := api_request_get(endpoint)
|
|
if !request_ok {
|
|
return nil, false
|
|
}
|
|
defer client.body_destroy(body, allocation)
|
|
|
|
if body.(client.Body_Plain) == "[]" {
|
|
return cpus, true
|
|
}
|
|
|
|
body_data := transmute([]u8)body.(client.Body_Plain)
|
|
json_data, err := json.parse(body_data)
|
|
if err != .None {
|
|
return nil, false
|
|
}
|
|
defer json.destroy_value(json_data)
|
|
|
|
root := json_data.(json.Array)
|
|
|
|
for cpu, i in root {
|
|
resize(&cpus, len(cpus)+1)
|
|
|
|
cpu_object := cpu.(json.Object)
|
|
|
|
cpus[i].id = int(cpu_object["id"].(json.Float))
|
|
cpus[i].socket = int(cpu_object["socket"].(json.Float))
|
|
cpus[i].name = strings.clone(cpu_object["name"].(json.String))
|
|
}
|
|
|
|
return cpus, true
|
|
}
|
|
|
|
destroy_cpus :: proc(cpus: [dynamic]CPU) {
|
|
for cpu in cpus {
|
|
delete(cpu.name)
|
|
}
|
|
delete(cpus)
|
|
}
|
|
|
|
add_cpu_to_lsm :: proc(cpu_name: string, socket, cores: int, usage: f64, host_id: int) -> bool {
|
|
request: client.Request
|
|
client.request_init(&request, .Post)
|
|
defer client.request_destroy(&request)
|
|
|
|
post_body := Base_CPU{cpu_name, socket, cores, usage, host_id}
|
|
if err := client.with_json(&request, post_body); err != nil {
|
|
return false
|
|
}
|
|
|
|
response, err := client.request(&request, fmt.tprintf("%s/cpus/add_cpu_to_host", PC.api_address))
|
|
if err != nil {
|
|
log.fatal("failed to add host to api with the error: ", err)
|
|
os.exit(1)
|
|
}
|
|
defer client.response_destroy(&response)
|
|
|
|
log.debugf("got response status %v when attempting to add cpu to lsm", response.status)
|
|
|
|
if response.status != .Created {
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
_main :: proc() {
|
|
context.logger = log.create_console_logger(.Info)
|
|
defer log.destroy_console_logger(context.logger)
|
|
|
|
data, ok := os.read_entire_file_from_filename(CONFIG_FILE_PATH)
|
|
if !ok {
|
|
fmt.eprintln("Failed to open config file")
|
|
return
|
|
}
|
|
defer delete(data)
|
|
data_str := strings.to_lower(transmute(string)data, allocator=context.temp_allocator)
|
|
|
|
ini_config, err := ini.load_map_from_string(data_str, allocator=context.allocator)
|
|
if err != nil {
|
|
log.fatal("failed to read config file")
|
|
return
|
|
}
|
|
defer ini.delete_map(ini_config)
|
|
|
|
if _, ok := ini_config["log"]; ok {
|
|
if level, ok := ini_config["log"]["level"]; ok && level in Log_Level_Map {
|
|
log_level := strings.to_upper(level, context.temp_allocator)
|
|
log_level_ok: bool
|
|
PC.log_level, log_level_ok = Log_Level_Map[log_level]
|
|
} else {
|
|
log.info("log level has either been not specified in configuration file or an invalid level has been specified")
|
|
log.info("defaulting to info")
|
|
PC.log_level = log.Level.Info
|
|
}
|
|
}
|
|
|
|
context.logger.lowest_level = PC.log_level
|
|
|
|
if _, ok := ini_config["api"]; ok {
|
|
if api_address, ok := ini_config["api"]["address"]; ok {
|
|
PC.api_address = api_address
|
|
} else {
|
|
log.fatal("api address not specified in config file")
|
|
return
|
|
}
|
|
}
|
|
|
|
log.debug("program config:", PC)
|
|
|
|
PC.hostname, ok = sysinfo.get_hostname()
|
|
if !ok {
|
|
log.fatal("failed to get hostname")
|
|
return
|
|
}
|
|
defer delete(PC.hostname)
|
|
log.info("successfully got hostname")
|
|
|
|
PC.host_id, ok = get_host_id(PC.hostname)
|
|
if !ok {
|
|
log.fatal("failed to contact the lsm api and determine if host already exists in lsm")
|
|
return
|
|
}
|
|
|
|
if PC.host_id < 0 {
|
|
log.info("Host doesn't exist in LSM")
|
|
log.info("Adding host now")
|
|
|
|
request: client.Request
|
|
client.request_init(&request, .Post)
|
|
defer client.request_destroy(&request)
|
|
|
|
post_body := Base_Host{PC.hostname}
|
|
if err := client.with_json(&request, post_body); err != nil {
|
|
log.fatal("JSON error:", err)
|
|
// TODO: Handle this
|
|
}
|
|
|
|
response, err := client.request(&request, fmt.tprintf("%s/hosts/add_host", PC.api_address))
|
|
if err != nil {
|
|
log.fatal("failed to add host to LSM with the error: %s", err)
|
|
return
|
|
}
|
|
defer client.response_destroy(&response)
|
|
|
|
if response.status == .Created {
|
|
log.info("successfully added host to lsm")
|
|
PC.host_id, ok = get_host_id(PC.hostname)
|
|
if !ok {
|
|
log.fatal("failed to get host id, exiting")
|
|
return
|
|
}
|
|
} else {
|
|
log.fatal("failed to add host to LSM got status code:", response.status)
|
|
return
|
|
}
|
|
} else {
|
|
log.info("host found in lsm")
|
|
}
|
|
log.debug("host id", PC.host_id)
|
|
|
|
cpu_name, socket, cpu_name_and_socket_ok := sysinfo.get_cpu_name_and_socket_number()
|
|
if !cpu_name_and_socket_ok {
|
|
log.fatal("failed to get cpu name and socket")
|
|
return
|
|
}
|
|
log.debug("got cpu name and socket")
|
|
|
|
cores, cores_ok := sysinfo.get_numb_cpu_cores()
|
|
if !cores_ok {
|
|
log.fatal("failed to get number of cpu cores")
|
|
return
|
|
}
|
|
log.debug("got number of cpu cores")
|
|
|
|
log.debug("starting main loop")
|
|
for {
|
|
usage, usage_ok := sysinfo.get_cpu_usage_perc()
|
|
log.info("USAGE:", usage)
|
|
if !usage_ok {
|
|
log.fatal("failed to get cpu usage")
|
|
return
|
|
} else {
|
|
log.debug("successfully got cpu usage")
|
|
}
|
|
|
|
if ok := add_cpu_to_lsm(cpu_name, socket, cores, usage, PC.host_id); !ok {
|
|
log.error("failed to add cpu")
|
|
} else {
|
|
log.info("successfully added cpu to lsm")
|
|
}
|
|
|
|
time.sleep(1 * time.Second)
|
|
}
|
|
}
|
|
|
|
main :: proc() {
|
|
track: mem.Tracking_Allocator
|
|
mem.tracking_allocator_init(&track, context.allocator)
|
|
context.allocator = mem.tracking_allocator(&track)
|
|
|
|
_main()
|
|
|
|
for _, leak in track.allocation_map {
|
|
fmt.println(leak.location, "leaked", leak.size, "bytes")
|
|
}
|
|
for bad_free in track.bad_free_array {
|
|
fmt.println(bad_free.location, "allocation", bad_free.memory, "was freed badly")
|
|
}
|
|
}
|