...
This commit is contained in:
@@ -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()!
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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) ! {
|
||||
|
||||
@@ -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) ! {
|
||||
|
||||
@@ -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
|
||||
// }
|
||||
|
||||
@@ -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
|
||||
// }
|
||||
|
||||
@@ -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:
|
||||
|
||||
12
lib/osal/linux/templates/profile_sshagent.sh
Normal file
12
lib/osal/linux/templates/profile_sshagent.sh
Normal 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
|
||||
@@ -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"
|
||||
@@ -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}')!
|
||||
|
||||
@@ -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()!
|
||||
|
||||
@@ -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')
|
||||
}
|
||||
@@ -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
|
||||
)!
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 ....')
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -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 ....')
|
||||
|
||||
|
||||
@@ -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()!
|
||||
|
||||
@@ -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'
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
module datamodel
|
||||
|
||||
import freeflowuniverse.herolib.threefold.grid4.datamodel { Node }
|
||||
|
||||
pub struct NodeSim {
|
||||
Node
|
||||
pub mut:
|
||||
|
||||
Reference in New Issue
Block a user