@ -1,12 +1,14 @@
package main
package main
import "core:encoding/ini"
import "core:encoding/json"
import "core:fmt"
import "core:fmt"
import "core:log"
import "core:log"
import "core:mem"
import "core:os"
import "core:os"
import "core:strings"
import "core:strconv"
import "core:strconv"
import "core:strings"
import "libs/ini"
import "libs/http"
import "libs/http"
import "libs/http/client"
import "libs/http/client"
import "libs/sysinfo"
import "libs/sysinfo"
@ -15,37 +17,62 @@ CONFIG_FILE_PATH :: "./config.ini"
PC: Program_Config = {}
PC: Program_Config = {}
get_config :: proc(config_file_path: string) -> Maybe(ini.INI) {
// get_config :: proc(config_file_path: string) -> Maybe(ini.INI) {
bytes, ok := os.read_entire_file_from_filename(config_file_path)
// bytes, ok := os.read_entire_file_from_filename(config_file_path)
if !ok {
// if !ok {
return nil
// return nil
}
// }
defer delete(bytes)
// defer delete(bytes)
config, res := ini.parse(bytes)
// config, res := ini.parse(bytes)
if res.err == ini.ParseErr.EOF {
// if res.err == ini.ParseErr.EOF {
return config
// return config
}
// }
return nil
// return nil
}
// }
// Returns the host ID, of if the host doesn't exist in
api_request_get :: proc(endpoint: string) -> (body: client.Body_Type, allocation: bool, ok: bool) {
// LSM then it will return -1
get_host_id :: proc(hostname: string) -> (int, bool) {
request: client.Request
request: client.Request
client.request_init(&request, .Get)
client.request_init(&request, .Get)
defer client.request_destroy(&request)
defer client.request_destroy(&request)
response, err := client.request(&request, fmt.tprintf("%s/get_host_id_for_hostname/%s", PC.api_address, hostname) )
response, err := client.request(&request, endpoint )
if err != nil {
if err != nil {
return 0 , false
return nil, false , false
}
}
defer client.response_destroy(&response)
defer client.response_destroy(&response)
body, allocation, body_err := client.response_body(&response)
body_err: client.Body_Error
body, allocation, body_err = client.response_body(&response)
if body_err != nil {
if body_err != nil {
return 0, false
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) -> (int, bool) {
endpoint := fmt.tprintf("%s/get_host_id_for_hostname/%s", PC.api_address, hostname)
body, allocation, ok := api_request_get(endpoint)
if !ok {
return 0, ok
}
}
defer client.body_destroy(body, allocation)
defer client.body_destroy(body, allocation)
@ -54,13 +81,88 @@ get_host_id :: proc(hostname: string) -> (int, bool) {
return host_id, true
return host_id, true
}
}
main :: proc() {
get_cpus_for_host_from_id :: proc(host_id: int) -> (cpus: [dynamic]CPU, ok: bool) {
endpoint := fmt.tprintf("%s/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: int, host_id: int) -> bool {
request: client.Request
client.request_init(&request, .Post)
defer client.request_destroy(&request)
post_body := Base_CPU{cpu_name, socket, host_id}
if err := client.with_json(&request, post_body); err != nil {
return false
}
response, err := client.request(&request, fmt.tprintf("%s/add_cpu/", PC.api_address))
if err != nil do log.fatal("Failed to add host to API with the error: %s", err)
defer client.response_destroy(&response)
if response.status != .Created {
return false
}
return true
}
_main :: proc() {
context.logger = log.create_console_logger(.Info)
context.logger = log.create_console_logger(.Info)
defer log.destroy_console_logger(context.logger)
ini_config, ok := get_config(CONFIG_FILE_PATH).?
data, ok := os.read_entire_file_from_filename("config.ini")
if !ok {
if !ok {
log.fatal("Failed to read config file, please ensure it's in the correct format")
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)
fmt.println("ini_config[\"api\"][\"address\"]:", ini_config["api"]["address"])
if _, ok := ini_config["log"]; ok {
if _, ok := ini_config["log"]; ok {
if level, ok := ini_config["log"]["level"]; ok && level in Log_Level_Map {
if level, ok := ini_config["log"]["level"]; ok && level in Log_Level_Map {
@ -77,21 +179,28 @@ main :: proc() {
context.logger.lowest_level = PC.log_level
context.logger.lowest_level = PC.log_level
if _, ok := ini_config["api"]; ok {
if _, ok := ini_config["api"]; ok {
if api_address, ok := ini_config["api"]["address"]; ok do PC.api_address = strings.clone(api_address)
if api_address, ok := ini_config["api"]["address"]; ok {
else do log.fatal("API address not specified in config file")
PC.api_address = api_address
} else {
log.fatal("API address not specified in config file")
return
}
}
}
log.debug("Program config:", PC)
log.debug("Program config:", PC)
hostname, hostname_ok := sysinfo.get_hostname().?
PC.hostname, ok = sysinfo.get_hostname().?
if !hostname_ok {
if !ok {
log.fatal("Failed to get hostname")
return
return
}
}
defer delete(PC.hostname)
log.info("Successfully got hostname")
log.info("Successfully got hostname")
PC.host_id, ok = get_host_id(hostname)
PC.host_id, ok = get_host_id(PC. hostname)
if !ok {
if !ok {
log.fatal("Failed to contact API and determine if host already exists in LSM")
log.fatal("Failed to contact API and determine if host already exists in LSM")
return
}
}
if PC.host_id < 0 {
if PC.host_id < 0 {
@ -102,9 +211,10 @@ main :: proc() {
client.request_init(&request, .Post)
client.request_init(&request, .Post)
defer client.request_destroy(&request)
defer client.request_destroy(&request)
post_body := Base_Host{hostname}
post_body := Base_Host{PC. hostname}
if err := client.with_json(&request, post_body); err != nil {
if err := client.with_json(&request, post_body); err != nil {
log.fatal("JSON error: %s", err)
log.fatal("JSON error:", err)
// TODO: Handle this
}
}
response, err := client.request(&request, fmt.tprintf("%s/add_host/", PC.api_address))
response, err := client.request(&request, fmt.tprintf("%s/add_host/", PC.api_address))
@ -113,7 +223,7 @@ main :: proc() {
if response.status == .Created {
if response.status == .Created {
log.info("Successfully added host to LSM")
log.info("Successfully added host to LSM")
PC.host_id, ok = get_host_id(hostname)
PC.host_id, ok = get_host_id(PC. hostname)
if !ok do log.fatal("Failed to get host ID, exiting")
if !ok do log.fatal("Failed to get host ID, exiting")
}
}
} else {
} else {
@ -121,4 +231,36 @@ main :: proc() {
}
}
log.debug("Host ID", PC.host_id)
log.debug("Host ID", PC.host_id)
// cpus, cpu_ok := get_cpus_for_host_from_id(PC.host_id)
// if len(cpus) == 0 {
// delete(cpus)
// log.info("Need to add CPUs to LSM")
// cpu_name, socket, ok := sysinfo.get_cpu_name_and_socket_number()
// log.info("Attempting to add CPU", cpu_name, "to LSM")
// if ok := add_cpu_to_lsm(cpu_name, socket, PC.host_id); !ok {
// log.fatal("Failed to add CPU, exiting")
// os.exit(1)
// }
// log.info("Successfully added CPU to LSM")
// cpus, cpu_ok := get_cpus_for_host_from_id(PC.host_id)
// }
// defer delete(cpus)
// log.debug("cpus for host: ", cpus)
}
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")
}
}
}