lima installer

This commit is contained in:
2025-08-28 05:39:51 +02:00
parent db9d2b5a0a
commit d1ec4ff568
10 changed files with 559 additions and 133 deletions

View File

@@ -1,26 +1,27 @@
#!/usr/bin/env -S v -n -w -gc none -cc tcc -d use_openssl -enable-globals run
import freeflowuniverse.herolib.virt.lima
// import freeflowuniverse.herolib.virt.lima
import freeflowuniverse.herolib.core.texttools
import freeflowuniverse.herolib.ui.console
import freeflowuniverse.herolib.installers.virt.lima as limainstaller
import os
limainstaller.install()!
mut i:=limainstaller.get(create:true)!
i.install(reset:true)!
mut virtmanager := lima.new()!
// mut virtmanager := lima.new()!
virtmanager.vm_delete_all()!
// virtmanager.vm_delete_all()!
// virtmanager.vm_new(reset:true,template:.alpine,name:'alpine',install_hero:false)!
// // virtmanager.vm_new(reset:true,template:.alpine,name:'alpine',install_hero:false)!
// virtmanager.vm_new(reset:true,template:.arch,name:'arch',install_hero:true)!
// // virtmanager.vm_new(reset:true,template:.arch,name:'arch',install_hero:true)!
virtmanager.vm_new(reset: true, template: .ubuntucloud, name: 'hero', install_hero: false)!
mut vm := virtmanager.vm_get('hero')!
// virtmanager.vm_new(reset: true, template: .ubuntucloud, name: 'hero', install_hero: false)!
// mut vm := virtmanager.vm_get('hero')!
println(vm)
// println(vm)
// vm.install_hero()!
// // vm.install_hero()!
// console.print_debug_title("MYVM", vm.str())
// // console.print_debug_title("MYVM", vm.str())

View File

@@ -3,6 +3,7 @@ module playcmds
import freeflowuniverse.herolib.core.playbook { PlayBook }
import freeflowuniverse.herolib.data.doctree
import freeflowuniverse.herolib.biz.bizmodel
import freeflowuniverse.herolib.threefold.incatokens
import freeflowuniverse.herolib.web.site
import freeflowuniverse.herolib.web.docusaurus
import freeflowuniverse.herolib.clients.openai
@@ -49,6 +50,8 @@ pub fn run(args_ PlayArgs) ! {
site.play(mut plbook)!
doctree.play(mut plbook)!
incatokens.play(mut plbook)!
docusaurus.play(mut plbook)!
giteaclient.play(mut plbook)!

View File

@@ -0,0 +1,13 @@
!!hero_code.generate_installer
name:'lima'
classname:'LimaInstaller'
singleton:1
templates:1
default:1
title:''
supported_platforms:''
reset:0
startupmanager:1
hasconfig:1
build:0

View File

@@ -1,119 +0,0 @@
module lima
import freeflowuniverse.herolib.osal.core as osal
import freeflowuniverse.herolib.core
import freeflowuniverse.herolib.installers.base
import freeflowuniverse.herolib.ui.console
import freeflowuniverse.herolib.core.texttools
import freeflowuniverse.herolib.installers.virt.qemu
import os
@[params]
pub struct InstallArgs {
pub mut:
reset bool
uninstall bool
}
pub fn install_(args_ InstallArgs) ! {
mut args := args_
version := '0.22.0'
if args.reset || args.uninstall {
console.print_header('uninstall lima')
uninstall()!
console.print_debug(' - ok')
if args.uninstall {
return
}
}
console.print_header('install install lima')
base.install()!
res := os.execute('${osal.profile_path_source_and()!} lima -v')
if res.exit_code == 0 {
r := res.output.split_into_lines().filter(it.contains('limactl version'))
if r.len != 1 {
return error("couldn't parse lima version, expected 'lima version' on 1 row.\n${res.output}")
}
v := texttools.version(r[0].all_after('version'))
if v < texttools.version(version) {
args.reset = true
}
} else {
args.reset = true
}
if args.reset == false {
return
}
if args.reset {
console.print_header('install lima')
qemu.install_()!
mut url := ''
mut dest_on_os := '${os.home_dir()}/hero'
if core.is_linux_arm()! {
dest_on_os = '/usr/local'
url = 'https://github.com/lima-vm/lima/releases/download/v${version}/lima-${version}-Linux-aarch64.tar.gz'
} else if core.is_linux_intel()! {
dest_on_os = '/usr/local'
url = 'https://github.com/lima-vm/lima/releases/download/v${version}/lima-${version}-Linux-x86_64.tar.gz'
} else if core.is_osx()! {
osx_install()!
// } else if core.is_osx_arm()! {
// url = 'https://github.com/lima-vm/lima/releases/download/v${version}/lima-${version}-Darwin-arm64.tar.gz'
// } else if core.is_osx_intel()! {
// url = 'https://github.com/lima-vm/lima/releases/download/v${version}/lima-${version}-Darwin-x86_64.tar.gz'
} else {
return error('unsported platform')
}
console.print_header('download ${url}')
osal.download(
url: url
minsize_kb: 45000
reset: args.reset
dest: '/tmp/lima.tar.gz'
expand_file: '/tmp/download/lima'
)!
cmd := '
rsync -rv /tmp/download/lima/ ${dest_on_os}
'
osal.exec(cmd: cmd)!
}
}
@[params]
pub struct ExtensionsInstallArgs {
pub mut:
extensions string
default bool = true
}
pub fn exists() !bool {
e := osal.cmd_exists_profile('limactl')
if e {
console.print_header('lima already installed')
}
return e
}
pub fn uninstall() ! {
cmd := '
// # Quit Google Chrome
// osascript -e \'quit app "Google Chrome"\'
// # Wait a bit to ensure Chrome has completely quit
// sleep 2
'
osal.exec(cmd: cmd)!
}
pub fn osx_install() ! {
osal.package_install('lima')!
}

View File

@@ -0,0 +1,160 @@
module lima
import freeflowuniverse.herolib.osal.core as osal
import freeflowuniverse.herolib.ui.console
import freeflowuniverse.herolib.core.texttools
import freeflowuniverse.herolib.core
import freeflowuniverse.herolib.core.pathlib
import freeflowuniverse.herolib.osal.startupmanager
import freeflowuniverse.herolib.installers.ulist
import freeflowuniverse.herolib.installers.virt.qemu
import os
fn startupcmd() ![]startupmanager.ZProcessNewArgs {
mut installer := get()!
mut res := []startupmanager.ZProcessNewArgs{}
// THIS IS EXAMPLE CODEAND NEEDS TO BE CHANGED
// res << startupmanager.ZProcessNewArgs{
// name: 'lima'
// cmd: 'lima server'
// env: {
// 'HOME': '/root'
// }
// }
return res
}
fn running() !bool {
mut installer := get()!
// THIS IS EXAMPLE CODEAND NEEDS TO BE CHANGED
// this checks health of lima
// curl http://localhost:3333/api/v1/s --oauth2-bearer 1234 works
// url:='http://127.0.0.1:${cfg.port}/api/v1'
// mut conn := httpconnection.new(name: 'lima', url: url)!
// if cfg.secret.len > 0 {
// conn.default_header.add(.authorization, 'Bearer ${cfg.secret}')
// }
// conn.default_header.add(.content_type, 'application/json')
// console.print_debug("curl -X 'GET' '${url}'/tags --oauth2-bearer ${cfg.secret}")
// r := conn.get_json_dict(prefix: 'tags', debug: false) or {return false}
// println(r)
// if true{panic("ssss")}
// tags := r['Tags'] or { return false }
// console.print_debug(tags)
// console.print_debug('lima is answering.')
return false
}
fn start_pre() ! {
}
fn start_post() ! {
}
fn stop_pre() ! {
}
fn stop_post() ! {
}
//////////////////// following actions are not specific to instance of the object
// checks if a certain version or above is installed
fn installed() !bool {
if !osal.cmd_exists('limactl') {
return false
}
mut res:=os.execute("lima -v");
r := res.output.split_into_lines().filter(it.contains('limactl version'))
if r.len != 1 {
return error("couldn't parse lima version, expected 'lima version' on 1 row.\n${res.output}")
}
v := texttools.version(r[0].all_after('version'))
if v < texttools.version(version) {
return false
}
return true
}
// get the Upload List of the files
fn ulist_get() !ulist.UList {
return ulist.UList{}
}
fn upload() ! {
}
fn install() ! {
console.print_header('install lima')
qemu.install_()!
mut url := ''
mut url2 := ''
mut dest_on_os := '${os.home_dir()}/hero'
if core.is_linux_arm()! {
dest_on_os = '/usr/local'
url = 'https://github.com/lima-vm/lima/releases/download/v${version}/lima-${version}-Linux-aarch64.tar.gz'
url2 = 'https://github.com/lima-vm/lima/releases/download/v${version}/lima-additional-guestagents-${version}-Linux-aarch64.tar.gz'
} else if core.is_linux_intel()! {
dest_on_os = '/usr/local'
url = 'https://github.com/lima-vm/lima/releases/download/v${version}/lima-${version}-Linux-x86_64.tar.gz'
url2 = 'https://github.com/lima-vm/lima/releases/download/v${version}/lima-additional-guestagents-${version}-Linux-x86_64.tar.gz'
} else if core.is_osx()! {
url = 'https://github.com/lima-vm/lima/releases/download/v${version}/lima-${version}-Darwin-arm64.tar.gz'
url2 = 'https://github.com/lima-vm/lima/releases/download/v${version}/lima-additional-guestagents-${version}-Darwin-arm64.tar.gz'
} else if core.is_osx_intel()! {
url = 'https://github.com/lima-vm/lima/releases/download/v${version}/lima-${version}-Darwin-x86_64.tar.gz'
url2 = 'https://github.com/lima-vm/lima/releases/download/v${version}/lima-additional-guestagents-${version}-Darwin-x86_64.tar.gz'
} else {
return error('unsported platform')
}
console.print_header('download ${url}')
mut e:=osal.download(
url: url
minsize_kb: 20000
dest: '/tmp/lima.tar.gz'
expand_file: '/tmp/download/lima'
)!
e.copy(dest:dest_on_os)!
mut installer := get()!
if installer.extra {
mut e2:=osal.download(
url: url2
minsize_kb: 20000
dest: '/tmp/lima-additional-guestagents.tar.gz'
expand_file: '/tmp/download/lima-additional-guestagents'
)!
e2.copy(dest:dest_on_os)!
}
}
fn destroy() ! {
osal.process_kill_recursive(name:'lima')!
osal.package_remove('
lima
limactl
')!
osal.rm("
lima
limactl
${os.home_dir()}/bin/*.lima
${os.home_dir()}/bin/*.lima
${os.home_dir()}/share/doc/lima
${os.home_dir()}/share/lima
${os.home_dir()}/share/man/lima*
")!
}

View File

@@ -0,0 +1,299 @@
module lima
import freeflowuniverse.herolib.core.base
import freeflowuniverse.herolib.core.playbook { PlayBook }
import freeflowuniverse.herolib.ui.console
import json
import freeflowuniverse.herolib.osal.startupmanager
import time
__global (
lima_global map[string]&LimaInstaller
lima_default string
)
/////////FACTORY
@[params]
pub struct ArgsGet {
pub mut:
name string = 'default'
fromdb bool // will load from filesystem
create bool // default will not create if not exist
}
pub fn new(args ArgsGet) !&LimaInstaller {
mut obj := LimaInstaller{
name: args.name
}
set(obj)!
return get(name: args.name)!
}
pub fn get(args ArgsGet) !&LimaInstaller {
mut context := base.context()!
lima_default = args.name
if args.fromdb || args.name !in lima_global {
mut r := context.redis()!
if r.hexists('context:lima', args.name)! {
data := r.hget('context:lima', args.name)!
if data.len == 0 {
return error('LimaInstaller with name: lima does not exist, prob bug.')
}
mut obj := json.decode(LimaInstaller, data)!
set_in_mem(obj)!
} else {
if args.create {
new(args)!
} else {
return error("LimaInstaller with name 'lima' does not exist")
}
}
return get(name: args.name)! // no longer from db nor create
}
return lima_global[args.name] or {
return error('could not get config for lima with name:lima')
}
}
// register the config for the future
pub fn set(o LimaInstaller) ! {
mut o2 := set_in_mem(o)!
lima_default = o2.name
mut context := base.context()!
mut r := context.redis()!
r.hset('context:lima', o2.name, json.encode(o2))!
}
// does the config exists?
pub fn exists(args ArgsGet) !bool {
mut context := base.context()!
mut r := context.redis()!
return r.hexists('context:lima', args.name)!
}
pub fn delete(args ArgsGet) ! {
mut context := base.context()!
mut r := context.redis()!
r.hdel('context:lima', args.name)!
}
@[params]
pub struct ArgsList {
pub mut:
fromdb bool // will load from filesystem
}
// if fromdb set: load from filesystem, and not from mem, will also reset what is in mem
pub fn list(args ArgsList) ![]&LimaInstaller {
mut res := []&LimaInstaller{}
mut context := base.context()!
if args.fromdb {
// reset what is in mem
lima_global = map[string]&LimaInstaller{}
lima_default = ''
}
if args.fromdb {
mut r := context.redis()!
mut l := r.hkeys('context:lima')!
for name in l {
res << get(name: name, fromdb: true)!
}
return res
} else {
// load from memory
for _, client in lima_global {
res << client
}
}
return res
}
// only sets in mem, does not set as config
fn set_in_mem(o LimaInstaller) !LimaInstaller {
mut o2 := obj_init(o)!
lima_global[o2.name] = &o2
lima_default = o2.name
return o2
}
pub fn play(mut plbook PlayBook) ! {
if !plbook.exists(filter: 'lima.') {
return
}
mut install_actions := plbook.find(filter: 'lima.configure')!
if install_actions.len > 0 {
for install_action in install_actions {
heroscript := install_action.heroscript()
mut obj2 := heroscript_loads(heroscript)!
set(obj2)!
}
}
mut other_actions := plbook.find(filter: 'lima.')!
for other_action in other_actions {
if other_action.name in ['destroy', 'install', 'build'] {
mut p := other_action.params
reset := p.get_default_false('reset')
if other_action.name == 'destroy' || reset {
console.print_debug('install action lima.destroy')
destroy()!
}
if other_action.name == 'install' {
console.print_debug('install action lima.install')
install()!
}
}
if other_action.name in ['start', 'stop', 'restart'] {
mut p := other_action.params
name := p.get('name')!
mut lima_obj := get(name: name)!
console.print_debug('action object:\n${lima_obj}')
if other_action.name == 'start' {
console.print_debug('install action lima.${other_action.name}')
lima_obj.start()!
}
if other_action.name == 'stop' {
console.print_debug('install action lima.${other_action.name}')
lima_obj.stop()!
}
if other_action.name == 'restart' {
console.print_debug('install action lima.${other_action.name}')
lima_obj.restart()!
}
}
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////# LIVE CYCLE MANAGEMENT FOR INSTALLERS ///////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////
fn startupmanager_get(cat startupmanager.StartupManagerType) !startupmanager.StartupManager {
// unknown
// screen
// zinit
// tmux
// systemd
match cat {
.screen {
console.print_debug('startupmanager: screen')
return startupmanager.get(.screen)!
}
.zinit {
console.print_debug('startupmanager: zinit')
return startupmanager.get(.zinit)!
}
.systemd {
console.print_debug('startupmanager: systemd')
return startupmanager.get(.systemd)!
}
else {
console.print_debug('startupmanager: auto')
return startupmanager.get(.auto)!
}
}
}
// load from disk and make sure is properly intialized
pub fn (mut self LimaInstaller) reload() ! {
self = obj_init(self)!
}
pub fn (mut self LimaInstaller) start() ! {
if self.running()! {
return
}
console.print_header('lima start')
if !installed()! {
install()!
}
configure()!
start_pre()!
for zprocess in startupcmd()! {
mut sm := startupmanager_get(zprocess.startuptype)!
console.print_debug('starting lima with ${zprocess.startuptype}...')
sm.new(zprocess)!
sm.start(zprocess.name)!
}
start_post()!
for _ in 0 .. 50 {
if self.running()! {
return
}
time.sleep(100 * time.millisecond)
}
return error('lima did not install properly.')
}
pub fn (mut self LimaInstaller) install_start(args InstallArgs) ! {
switch(self.name)
self.install(args)!
self.start()!
}
pub fn (mut self LimaInstaller) stop() ! {
switch(self.name)
stop_pre()!
for zprocess in startupcmd()! {
mut sm := startupmanager_get(zprocess.startuptype)!
sm.stop(zprocess.name)!
}
stop_post()!
}
pub fn (mut self LimaInstaller) restart() ! {
switch(self.name)
self.stop()!
self.start()!
}
pub fn (mut self LimaInstaller) running() !bool {
switch(self.name)
// walk over the generic processes, if not running return
for zprocess in startupcmd()! {
if zprocess.startuptype != .screen {
mut sm := startupmanager_get(zprocess.startuptype)!
r := sm.running(zprocess.name)!
if r == false {
return false
}
}
}
return running()!
}
@[params]
pub struct InstallArgs {
pub mut:
reset bool
}
pub fn (mut self LimaInstaller) install(args InstallArgs) ! {
switch(self.name)
if args.reset || (!installed()!) {
install()!
}
}
pub fn (mut self LimaInstaller) destroy() ! {
switch(self.name)
self.stop() or {}
destroy()!
}
// switch instance to be used for lima
pub fn switch(name string) {
}

View File

@@ -0,0 +1,41 @@
module lima
import freeflowuniverse.herolib.data.paramsparser
import freeflowuniverse.herolib.data.encoderhero
import os
pub const version = '1.2.1'
const singleton = true
const default = true
// THIS THE THE SOURCE OF THE INFORMATION OF THIS FILE, HERE WE HAVE THE CONFIG OBJECT CONFIGURED AND MODELLED
@[heap]
pub struct LimaInstaller {
pub mut:
name string = 'default'
homedir string
extra bool //do we want to extra's
sshkey string //name of the key to use
}
// your checking & initialization code if needed
fn obj_init(mycfg_ LimaInstaller) !LimaInstaller {
mut mycfg := mycfg_
return mycfg
}
// called before start if done
fn configure() ! {
// mut installer := get()!
// mut mycode := $tmpl('templates/atemplate.yaml')
// mut path := pathlib.get_file(path: cfg.configpath, create: true)!
// path.write(mycode)!
// console.print_debug(mycode)
}
/////////////NORMALLY NO NEED TO TOUCH
pub fn heroscript_loads(heroscript string) !LimaInstaller {
mut obj := encoderhero.decode[LimaInstaller](heroscript)!
return obj
}

View File

@@ -0,0 +1,25 @@
# lima
To get started
```v
import freeflowuniverse.herolib.installers.virt.lima as lima_installer
heroscript:="
!!lima.install
"
lima_installer.play(heroscript=heroscript)!
//or we can call the default and do a start with reset
mut installer:= lima_installer.get()!
installer.start(reset:true)!
```

View File

@@ -0,0 +1,5 @@
name: ${cfg.configpath}

View File

@@ -49,9 +49,7 @@ pub fn install_(args_ InstallArgs) ! {
if platform in [.arch, .ubuntu] {
osal.package_install('qemu,libvirt,qemu-common,qemu-img,qemu-system-arm,qemu-system-x86,qemu-tools,libguestfs')!
osal.exec(cmd: 'systemctl start libvirtd && systemctl enable libvirtd')!
} else {
return error('can only install qemu on ubuntu & arch')
}
}
if exists()! {
console.print_header(' - qemu exists check ok.')