This commit is contained in:
2025-08-25 06:28:42 +02:00
parent 5f683ec4a8
commit 836c87fbec
44 changed files with 891 additions and 942 deletions

View File

@@ -1,6 +1,5 @@
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
import freeflowuniverse.herolib.osal.tmux
mut t := tmux.new()!

View File

@@ -3,13 +3,16 @@ module livekit
import freeflowuniverse.herolib.data.caching
import os
const CACHING_METHOD = caching.CachingMethod.once_per_process
// const CACHING_METHOD = caching.CachingMethod.once_per_process
fn _init() ! {
if caching.is_set(key: 'livekit_clients') {
return
}
caching.set[map[string]LivekitClient](key: 'livekit_clients', val: map[string]LivekitClient{}, CachingMethod.once_per_process)!
caching.set[map[string]LivekitClient](
key: 'livekit_clients'
val: map[string]LivekitClient{}
)!
}
fn _get() !map[string]LivekitClient {
@@ -25,7 +28,7 @@ pub fn get(name string) !LivekitClient {
pub fn set(client LivekitClient) ! {
mut clients := _get()!
clients[client.name] = client
caching.set[map[string]LivekitClient](key: 'livekit_clients', val: clients, CachingMethod.once_per_process)!
caching.set[map[string]LivekitClient](key: 'livekit_clients', val: clients)!
}
pub fn exists(name string) !bool {

View File

@@ -60,25 +60,36 @@ pub fn (mut c LivekitClient) start_web_egress(args StartWebEgressArgs) !EgressIn
}
pub fn (mut c LivekitClient) update_layout(egress_id string, layout string) !EgressInfo {
mut resp := c.post('twirp/livekit.Egress/UpdateLayout', {'egress_id': egress_id, 'layout': layout})!
mut resp := c.post('twirp/livekit.Egress/UpdateLayout', {
'egress_id': egress_id
'layout': layout
})!
egress_info := json.decode[EgressInfo](resp.body)!
return egress_info
}
pub fn (mut c LivekitClient) update_stream(egress_id string, args UpdateStreamArgs) !EgressInfo {
mut resp := c.post('twirp/livekit.Egress/UpdateStream', {'egress_id': egress_id, 'add_output_urls': args.add_output_urls, 'remove_output_urls': args.remove_output_urls})!
mut resp := c.post('twirp/livekit.Egress/UpdateStream', {
'egress_id': egress_id
'add_output_urls': args.add_output_urls
'remove_output_urls': args.remove_output_urls
})!
egress_info := json.decode[EgressInfo](resp.body)!
return egress_info
}
pub fn (mut c LivekitClient) list_egress(room_name string) ![]EgressInfo {
mut resp := c.post('twirp/livekit.Egress/ListEgress', {'room_name': room_name})!
mut resp := c.post('twirp/livekit.Egress/ListEgress', {
'room_name': room_name
})!
egress_infos := json.decode[[]EgressInfo](resp.body)!
return egress_infos
}
pub fn (mut c LivekitClient) stop_egress(egress_id string) !EgressInfo {
mut resp := c.post('twirp/livekit.Egress/StopEgress', {'egress_id': egress_id})!
mut resp := c.post('twirp/livekit.Egress/StopEgress', {
'egress_id': egress_id
})!
egress_info := json.decode[EgressInfo](resp.body)!
return egress_info
}

View File

@@ -93,8 +93,15 @@ pub mut:
video IngressVideoOptions
}
pub fn (mut c LivekitClient) create_ingress(args CreateIngressArgs) !IngressInfo {
mut resp := c.post('twirp/livekit.Ingress/CreateIngress', args)!
ingress_info := json.decode[IngressInfo](resp.body)!
return ingress_info
}
pub struct UpdateIngressArgs {
pub mut:
ingress_id string
name string
room_name string
participant_identity string
@@ -103,26 +110,32 @@ pub mut:
video IngressVideoOptions
}
pub fn (mut c LivekitClient) create_ingress(args CreateIngressArgs) !IngressInfo {
mut resp := c.post('twirp/livekit.Ingress/CreateIngress', args)!
ingress_info := json.decode[IngressInfo](resp.body)!
return ingress_info
}
pub fn (mut c LivekitClient) update_ingress(ingress_id string, args UpdateIngressArgs) !IngressInfo {
mut resp := c.post('twirp/livekit.Ingress/UpdateIngress', {'ingress_id': ingress_id, ...args})!
pub fn (mut c LivekitClient) update_ingress(args UpdateIngressArgs) !IngressInfo {
mut resp := c.post('twirp/livekit.Ingress/UpdateIngress', {
'ingress_id': args.ingress_id
'name': args.name
'room_name': args.room_name
'participant_identity': args.participant_identity
'participant_name': args.participant_name
'audio': args.audio
'video': args.video
})!
ingress_info := json.decode[IngressInfo](resp.body)!
return ingress_info
}
pub fn (mut c LivekitClient) list_ingress(room_name string) ![]IngressInfo {
mut resp := c.post('twirp/livekit.Ingress/ListIngress', {'room_name': room_name})!
mut resp := c.post('twirp/livekit.Ingress/ListIngress', {
'room_name': room_name
})!
ingress_infos := json.decode[[]IngressInfo](resp.body)!
return ingress_infos
}
pub fn (mut c LivekitClient) delete_ingress(ingress_id string) !IngressInfo {
mut resp := c.post('twirp/livekit.Ingress/DeleteIngress', {'ingress_id': ingress_id})!
mut resp := c.post('twirp/livekit.Ingress/DeleteIngress', {
'ingress_id': ingress_id
})!
ingress_info := json.decode[IngressInfo](resp.body)!
return ingress_info
}

View File

@@ -33,19 +33,27 @@ pub mut:
}
pub fn (mut c LivekitClient) list_participants(room_name string) ![]ParticipantInfo {
mut resp := c.post('twirp/livekit.RoomService/ListParticipants', {'room': room_name})!
mut resp := c.post('twirp/livekit.RoomService/ListParticipants', {
'room': room_name
})!
participants := json.decode[[]ParticipantInfo](resp.body)!
return participants
}
pub fn (mut c LivekitClient) get_participant(room_name string, identity string) !ParticipantInfo {
mut resp := c.post('twirp/livekit.RoomService/GetParticipant', {'room': room_name, 'identity': identity})!
mut resp := c.post('twirp/livekit.RoomService/GetParticipant', {
'room': room_name
'identity': identity
})!
participant := json.decode[ParticipantInfo](resp.body)!
return participant
}
pub fn (mut c LivekitClient) remove_participant(room_name string, identity string) ! {
_ = c.post('twirp/livekit.RoomService/RemoveParticipant', {'room': room_name, 'identity': identity})!
_ = c.post('twirp/livekit.RoomService/RemoveParticipant', {
'room': room_name
'identity': identity
})!
}
pub fn (mut c LivekitClient) update_participant(args UpdateParticipantArgs) ! {

View File

@@ -39,7 +39,9 @@ pub fn (mut c LivekitClient) create_room(args CreateRoomArgs) !Room {
}
pub fn (mut c LivekitClient) delete_room(room_name string) ! {
_ = c.post('twirp/livekit.RoomService/DeleteRoom', {'room': room_name})!
_ = c.post('twirp/livekit.RoomService/DeleteRoom', {
'room': room_name
})!
}
pub fn (mut c LivekitClient) update_room_metadata(args UpdateRoomMetadataArgs) ! {

View File

@@ -15,19 +15,19 @@ pub:
unix_micro string
}
pub struct Room {
pub:
active_recording bool
creation_time string
departure_timeout int
empty_timeout int
enabled_codecs []Codec
max_participants int
metadata string
name string
num_participants int
num_publishers int
sid string
turn_password string
version Version
}
// pub struct Room {
// pub:
// active_recording bool
// creation_time string
// departure_timeout int
// empty_timeout int
// enabled_codecs []Codec
// max_participants int
// metadata string
// name string
// num_participants int
// num_publishers int
// sid string
// turn_password string
// version Version
// }

View File

@@ -18,60 +18,60 @@ pub mut:
name string
}
// VideoGrant struct placeholder
pub struct VideoGrant {
pub mut:
room string
room_join bool @[json: 'roomJoin']
room_list bool @[json: 'roomList']
can_publish bool @[json: 'canPublish']
can_publish_data bool @[json: 'canPublishData']
can_subscribe bool @[json: 'canSubscribe']
}
// // VideoGrant struct placeholder
// pub struct VideoGrant {
// pub mut:
// room string
// room_join bool @[json: 'roomJoin']
// room_list bool @[json: 'roomList']
// can_publish bool @[json: 'canPublish']
// can_publish_data bool @[json: 'canPublishData']
// can_subscribe bool @[json: 'canSubscribe']
// }
// SIPGrant struct placeholder
struct SIPGrant {}
// AccessToken class
pub struct AccessToken {
mut:
api_key string
api_secret string
grants ClaimGrants
identity string
ttl int
}
// // AccessToken class
// pub struct AccessToken {
// mut:
// api_key string
// api_secret string
// grants ClaimGrants
// identity string
// ttl int
// }
// Method to add a video grant to the token
pub fn (mut token AccessToken) add_video_grant(grant VideoGrant) {
token.grants.video = grant
}
// pub fn (mut token AccessToken) add_video_grant(grant VideoGrant) {
// token.grants.video = grant
// }
// Method to generate a JWT token
pub fn (token AccessToken) to_jwt() !string {
// Create JWT payload
payload := json.encode(token.grants)
// // Method to generate a JWT token
// pub fn (token AccessToken) to_jwt() !string {
// // Create JWT payload
// payload := json.encode(token.grants)
println('payload: ${payload}')
// println('payload: ${payload}')
// Create JWT header
header := '{"alg":"HS256","typ":"JWT"}'
// // Create JWT header
// header := '{"alg":"HS256","typ":"JWT"}'
// Encode header and payload in base64
header_encoded := base64.url_encode_str(header)
payload_encoded := base64.url_encode_str(payload)
// // Encode header and payload in base64
// header_encoded := base64.url_encode_str(header)
// payload_encoded := base64.url_encode_str(payload)
// Create the unsigned token
unsigned_token := '${header_encoded}.${payload_encoded}'
// // Create the unsigned token
// unsigned_token := '${header_encoded}.${payload_encoded}'
// Create the HMAC-SHA256 signature
signature := hmac.new(token.api_secret.bytes(), unsigned_token.bytes(), sha256.sum,
sha256.block_size)
// // Create the HMAC-SHA256 signature
// signature := hmac.new(token.api_secret.bytes(), unsigned_token.bytes(), sha256.sum,
// sha256.block_size)
// Encode the signature in base64
signature_encoded := base64.url_encode(signature)
// // Encode the signature in base64
// signature_encoded := base64.url_encode(signature)
// Create the final JWT
jwt := '${unsigned_token}.${signature_encoded}'
return jwt
}
// // Create the final JWT
// jwt := '${unsigned_token}.${signature_encoded}'
// return jwt
// }

View File

@@ -40,12 +40,6 @@ pub fn (key SSHKey) private_key() !string {
return content
}
module core
import freeflowuniverse.herolib.core.pathlib
import os
@[params]
pub struct SSHConfig {
pub:

View File

@@ -0,0 +1,12 @@
# Auto-start ssh-agent if not running
SSH_AGENT_PID_FILE="$HOME/.ssh/agent.pid"
SSH_AUTH_SOCK_FILE="$HOME/.ssh/agent.sock"
chown "$NEWUSER":"$NEWUSER" "$PROFILE_SCRIPT"
chmod 644 "$PROFILE_SCRIPT"
# --- source it on login ---
#TODO should be done in vcode
if ! grep -q ".profile_sshagent" "$USERHOME/.bashrc"; then
echo "[ -f ~/.profile_sshagent ] && source ~/.profile_sshagent" >> "$USERHOME/.bashrc"
fi

View File

@@ -57,19 +57,4 @@ chown root:ourworld /code
chmod 2775 /code # rwx for user+group, SGID bit so new files inherit group
echo "✅ /code prepared (group=ourworld, rwx for group, SGID bit set)"
# --- create login helper script for ssh-agent ---
PROFILE_SCRIPT="$USERHOME/.profile_sshagent"
cat > "$PROFILE_SCRIPT" <<'EOF'
# Auto-start ssh-agent if not running
SSH_AGENT_PID_FILE="$HOME/.ssh/agent.pid"
SSH_AUTH_SOCK_FILE="$HOME/.ssh/agent.sock"
chown "$NEWUSER":"$NEWUSER" "$PROFILE_SCRIPT"
chmod 644 "$PROFILE_SCRIPT"
# --- source it on login ---
if ! grep -q ".profile_sshagent" "$USERHOME/.bashrc"; then
echo "[ -f ~/.profile_sshagent ] && source ~/.profile_sshagent" >> "$USERHOME/.bashrc"
fi
echo "🎉 Setup complete for user $NEWUSER"

View File

@@ -119,7 +119,9 @@ pub fn (mut lf LinuxFactory) sshkey_create(args SSHKeyCreateArgs) ! {
} else {
// Generate new SSH key (modern ed25519)
key_path := '${ssh_dir}/${args.sshkey_name}'
osal.exec(cmd: 'ssh-keygen -t ed25519 -f ${key_path} -N "" -C "${args.username}@$(hostname)"')!
osal.exec(
cmd: 'ssh-keygen -t ed25519 -f ${key_path} -N "" -C "${args.username}@$(hostname)"'
)!
console.print_green(' New SSH key generated for ${args.username}')
}
@@ -201,7 +203,7 @@ fn (mut lf LinuxFactory) remove_user_config(username string) ! {
config_path := '${config_dir}/myconfig.json'
if !os.exists(config_path) {
return // Nothing to remove
return
}
content := osal.file_read(config_path)!
@@ -243,7 +245,9 @@ fn (mut lf LinuxFactory) create_user_system(args UserCreateArgs) ! {
// Ensure ourworld group exists
group_check := osal.exec(cmd: 'getent group ourworld', raise_error: false) or {
osal.Job{ exit_code: 1 }
osal.Job{
exit_code: 1
}
}
if group_check.exit_code != 0 {
console.print_item(' Creating group ourworld')
@@ -284,58 +288,9 @@ fn (mut lf LinuxFactory) create_ssh_agent_profile(username string) ! {
user_home := '/home/${username}'
profile_script := '${user_home}/.profile_sshagent'
script_content := '# Auto-start ssh-agent if not running
SSH_AGENT_PID_FILE="$HOME/.ssh/agent.pid"
SSH_AUTH_SOCK_FILE="$HOME/.ssh/agent.sock"
// script_content := ''
# Function to start ssh-agent
start_ssh_agent() {
mkdir -p "$HOME/.ssh"
chmod 700 "$HOME/.ssh"
# Start ssh-agent and save connection info
ssh-agent -s > "$SSH_AGENT_PID_FILE"
source "$SSH_AGENT_PID_FILE"
# Save socket path for future sessions
echo "$SSH_AUTH_SOCK" > "$SSH_AUTH_SOCK_FILE"
# Load all private keys found in ~/.ssh
if [ -d "$HOME/.ssh" ]; then
for KEY in "$HOME"/.ssh/*; do
if [ -f "$KEY" ] && [ ! "${KEY##*.}" = "pub" ] && grep -q "PRIVATE KEY" "$KEY" 2>/dev/null; then
'ssh-' + 'add "$KEY" >/dev/null 2>&1 && echo "🔑 Loaded key: $(basename $KEY)"'
fi
done
fi
}
# Check if ssh-agent is running
if [ -f "$SSH_AGENT_PID_FILE" ]; then
source "$SSH_AGENT_PID_FILE" >/dev/null 2>&1
# Test if agent is responsive
if ! ('ssh-' + 'add -l >/dev/null 2>&1'); then
start_ssh_agent
else
# Agent is running, restore socket path
if [ -f "$SSH_AUTH_SOCK_FILE" ]; then
export SSH_AUTH_SOCK=$(cat "$SSH_AUTH_SOCK_FILE")
fi
fi
else
start_ssh_agent
fi
# For interactive shells
if [[ $- == *i* ]]; then
echo "🔑 SSH Agent ready at $SSH_AUTH_SOCK"
# Show loaded keys
KEY_COUNT=$('ssh-' + 'add -l 2>/dev/null | wc -l')
if [ "$KEY_COUNT" -gt 0 ]; then
echo "🔑 $KEY_COUNT SSH key(s) loaded"
fi
fi
'
panic('implement')
osal.file_write(profile_script, script_content)!
osal.exec(cmd: 'chown ${username}:${username} ${profile_script}')!

View File

@@ -96,9 +96,7 @@ fn sshkey_delete(mut agent SSHAgent, name string) ! {
fn sshkey_load(mut agent SSHAgent, name string) ! {
console.print_header('Loading SSH key: ${name}')
mut key := agent.get(name: name) or {
return error('SSH key "${name}" not found')
}
mut key := agent.get(name: name) or { return error('SSH key "${name}" not found') }
if key.loaded {
console.print_debug('SSH key "${name}" is already loaded')
@@ -113,18 +111,12 @@ fn sshkey_load(mut agent SSHAgent, name string) ! {
fn sshkey_check(mut agent SSHAgent, name string) ! {
console.print_header('Checking SSH key: ${name}')
mut key := agent.get(name: name) or {
return error('SSH key "${name}" not found')
}
mut key := agent.get(name: name) or { return error('SSH key "${name}" not found') }
// Check if key files exist
key_path := key.keypath() or {
return error('Private key file not found for "${name}"')
}
key_path := key.keypath() or { return error('Private key file not found for "${name}"') }
key_pub_path := key.keypath_pub() or {
return error('Public key file not found for "${name}"')
}
key_pub_path := key.keypath_pub() or { return error('Public key file not found for "${name}"') }
if !key_path.exists() {
return error('Private key file does not exist: ${key_path.path}')
@@ -157,9 +149,7 @@ fn remote_copy(mut agent SSHAgent, node_addr string, key_name string) ! {
console.print_header('Copying SSH key "${key_name}" to ${node_addr}')
// Get the key
mut key := agent.get(name: key_name) or {
return error('SSH key "${key_name}" not found')
}
mut key := agent.get(name: key_name) or { return error('SSH key "${key_name}" not found') }
// Create builder node
mut b := builder.new()!

View File

@@ -92,9 +92,7 @@ pub fn (mut agent SSHAgent) verify_key_access(mut node builder.Node, key_name st
}
// Test basic connectivity
result := node.exec_silent('echo "SSH key verification successful"') or {
return false
}
result := node.exec_silent('echo "SSH key verification successful"') or { return false }
return result.contains('SSH key verification successful')
}

View File

@@ -184,7 +184,12 @@ fn play_pane_kill(mut plbook PlayBook, mut tmux_instance Tmux) ! {
// Kill the active pane in the window
if pane := window.pane_active() {
tmux_cmd := 'tmux kill-pane -t ${session.name}:@${window.id}.%${pane.id}'
osal.exec(cmd: tmux_cmd, stdout: false, name: 'tmux_pane_kill', ignore_error: true)!
osal.exec(
cmd: tmux_cmd
stdout: false
name: 'tmux_pane_kill'
ignore_error: true
)!
}
}
}

View File

@@ -14,7 +14,6 @@ pub mut:
sessionid string // unique link to job
}
// get session (session has windows) .
// returns none if not found
pub fn (mut t Tmux) session_get(name_ string) !&Session {
@@ -56,8 +55,6 @@ pub mut:
reset bool
}
// create session, if reset will re-create
pub fn (mut t Tmux) session_create(args SessionCreateArgs) !&Session {
name := texttools.name_fix(args.name)
@@ -83,7 +80,6 @@ pub fn (mut t Tmux) session_create(args SessionCreateArgs) !&Session {
return s
}
@[params]
pub struct TmuxNewArgs {
sessionid string
@@ -126,7 +122,6 @@ pub fn (mut t Tmux) window_new(args WindowNewArgs) !&Window {
)!
}
pub fn (mut t Tmux) stop() ! {
$if debug {
console.print_debug('Stopping tmux...')
@@ -156,7 +151,6 @@ pub fn (mut t Tmux) start() ! {
t.scan()!
}
// print list of tmux sessions
pub fn (mut t Tmux) list_print() {
// os.log('TMUX - Start listing ....')

View File

@@ -20,7 +20,6 @@ pub mut:
last_output_offset int // for tracking new logs
}
pub fn (mut p Pane) stats() !ProcessStats {
if p.pid == 0 {
return ProcessStats{}
@@ -48,7 +47,6 @@ pub fn (mut p Pane) stats() !ProcessStats {
}
}
pub struct TMuxLogEntry {
pub mut:
content string
@@ -57,20 +55,17 @@ pub mut:
}
pub fn (mut p Pane) logs_get_new(reset bool) ![]TMuxLogEntry {
if reset{
if reset {
p.last_output_offset = 0
}
// Capture pane content with line numbers
cmd := 'tmux capture-pane -t ${p.window.session.name}:@${p.window.id}.%${p.id} -S ${p.last_output_offset} -p'
result := osal.execute_silent(cmd) or {
return error('Cannot capture pane output: ${err}')
}
result := osal.execute_silent(cmd) or { return error('Cannot capture pane output: ${err}') }
lines := result.split_into_lines()
mut entries := []TMuxLogEntry{}
mut i:= 0
mut i := 0
for line in lines {
if line.trim_space() != '' {
entries << TMuxLogEntry{
@@ -106,9 +101,7 @@ pub fn (mut p Pane) exit_status() !ProcessStatus {
pub fn (mut p Pane) logs_all() !string {
cmd := 'tmux capture-pane -t ${p.window.session.name}:@${p.window.id}.%${p.id} -S -2000 -p'
return osal.execute_silent(cmd) or {
error('Cannot capture pane output: ${err}')
}
return osal.execute_silent(cmd) or { error('Cannot capture pane output: ${err}') }
}
// Fix the output_wait method to use correct method name

View File

@@ -1,7 +1,5 @@
module tmux
pub struct ProcessStats {
pub mut:
cpu_percent f64
@@ -9,13 +7,9 @@ pub mut:
memory_percent f64
}
enum ProcessStatus {
running
finished_ok
finished_error
not_found
}
}

View File

@@ -65,7 +65,7 @@ fn (mut t Tmux) scan_add(line string) !&Pane {
}
// scan the system to detect sessions .
//TODO needs to be done differently, here only find the sessions, then per session call the scan() which will find the windows, call scan() there as well ...
// TODO needs to be done differently, here only find the sessions, then per session call the scan() which will find the windows, call scan() there as well ...
pub fn (mut t Tmux) scan() ! {
// os.log('TMUX - Scanning ....')

View File

@@ -21,6 +21,7 @@ pub mut:
env map[string]string
reset bool
}
@[params]
pub struct WindowGetArgs {
pub mut:
@@ -28,10 +29,9 @@ pub mut:
id int
}
pub fn (mut s Session) create() ! {
// Check if session already exists
cmd_check := "tmux has-session -t ${s.name}"
cmd_check := 'tmux has-session -t ${s.name}'
check_result := osal.exec(cmd: cmd_check, stdout: false, ignore_error: true) or {
// Session doesn't exist, this is expected
osal.Job{}
@@ -42,19 +42,19 @@ pub fn (mut s Session) create() ! {
}
// Create new session
cmd := "tmux new-session -d -s ${s.name}"
cmd := 'tmux new-session -d -s ${s.name}'
osal.exec(cmd: cmd, stdout: false, name: 'tmux_session_create') or {
return error("Can't create session ${s.name}: ${err}")
}
}
//load info from reality
// load info from reality
pub fn (mut s Session) scan() ! {
// Get current windows from tmux for this session
cmd := "tmux list-windows -t ${s.name} -F '#{window_name}|#{window_id}|#{window_active}'"
result := osal.execute_silent(cmd) or {
if err.msg().contains('session not found') {
return // Session doesn't exist anymore
return
}
return error('Cannot list windows for session ${s.name}: ${err}')
}
@@ -102,7 +102,6 @@ pub fn (mut s Session) scan() ! {
s.windows = s.windows.filter(current_windows[it.name] == true)
}
// window_name is the name of the window in session main (will always be called session main)
// cmd to execute e.g. bash file
// environment arguments to use
@@ -143,10 +142,6 @@ pub fn (mut s Session) window_new(args WindowArgs) !Window {
return w
}
// get all windows as found in a session
pub fn (mut s Session) windows_get() []&Window {
mut res := []&Window{}
@@ -208,8 +203,6 @@ pub fn (mut s Session) stats() !ProcessStats {
// }
// }
fn (mut s Session) window_exist(args_ WindowGetArgs) bool {
mut args := args_
s.window_get(args) or { return false }
@@ -249,7 +242,6 @@ pub fn (mut s Session) window_delete(args_ WindowGetArgs) ! {
s.windows.delete(i) // i is now the one in the list which needs to be removed
}
pub fn (mut s Session) restart() ! {
s.stop()!
s.create()!

View File

@@ -22,12 +22,11 @@ pub mut:
pub struct PaneNewArgs {
pub mut:
name string
reset bool //means we reset the pane if it already exists
reset bool // means we reset the pane if it already exists
cmd string
env map[string]string
}
pub fn (mut w Window) scan() ! {
// Get current panes for this window
cmd := "tmux list-panes -t ${w.session.name}:@${w.id} -F '#{pane_id}|#{pane_pid}|#{pane_active}|#{pane_start_command}'"
@@ -81,12 +80,12 @@ pub fn (mut w Window) scan() ! {
w.panes = w.panes.filter(current_panes[it.id] == true)
}
pub fn (mut w Window) stop() ! {
w.kill()!
}
//helper function
//TODO env variables are not inserted in pane
// helper function
// TODO env variables are not inserted in pane
pub fn (mut w Window) create(cmd_ string) ! {
mut final_cmd := cmd_
if cmd_.contains('\n') {
@@ -100,7 +99,7 @@ pub fn (mut w Window) create(cmd_ string) ! {
}
mut newcmd := '/bin/bash -c "${final_cmd}"'
if cmd_ == "" {
if cmd_ == '' {
newcmd = '/bin/bash'
}

View File

@@ -1,17 +1,17 @@
module datamodel
// I can bid for infra, and optionally get accepted
@[heap]
//I can bid for infra, and optionally get accepted
pub struct Bid {
pub mut:
id u32
customer_id u32 //links back to customer for this capacity (user on ledger)
compute_slices_nr int //nr of slices I need in 1 machine
compute_slice f64 //price per 1 GB slice I want to accept
customer_id u32 // links back to customer for this capacity (user on ledger)
compute_slices_nr int // nr of slices I need in 1 machine
compute_slice f64 // price per 1 GB slice I want to accept
storage_slices []u32
status BidStatus
obligation bool //if obligation then will be charged and money needs to be in escrow, otherwise its an intent
start_date u32 //epoch
obligation bool // if obligation then will be charged and money needs to be in escrow, otherwise its an intent
start_date u32 // epoch
end_date u32
}

View File

@@ -4,11 +4,11 @@ module datamodel
pub struct Reservation {
pub mut:
id u32
customer_id u32 //links back to customer for this capacity
customer_id u32 // links back to customer for this capacity
compute_slices []u32
storage_slices []u32
status ReservationStatus
start_date u32 //epoch
start_date u32 // epoch
end_date u32
}

View File

@@ -1,5 +1,7 @@
module datamodel
import freeflowuniverse.herolib.threefold.grid4.datamodel { Node }
pub struct NodeSim {
Node
pub mut: