Implements automatic ballooning
This commit is contained in:
parent
1184fa3d7e
commit
2dae4eb5a3
11
README.md
11
README.md
@ -66,6 +66,17 @@ Default hotkey to release cursor: ctrl+alt.
|
|||||||
|
|
||||||
$ appvm stop chromium
|
$ appvm stop chromium
|
||||||
|
|
||||||
|
## Automatic ballooning
|
||||||
|
|
||||||
|
Add this command:
|
||||||
|
|
||||||
|
$ appvm autoballoon
|
||||||
|
|
||||||
|
to crontab like that:
|
||||||
|
|
||||||
|
$ crontab -l
|
||||||
|
* * * * * /home/user/dev/go/bin/appvm autoballoon
|
||||||
|
|
||||||
# App description
|
# App description
|
||||||
|
|
||||||
$ cat nix/chromium.nix
|
$ cat nix/chromium.nix
|
||||||
|
59
appvm.go
59
appvm.go
@ -16,11 +16,13 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strconv"
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/digitalocean/go-libvirt"
|
"github.com/digitalocean/go-libvirt"
|
||||||
"github.com/jollheef/go-system"
|
"github.com/jollheef/go-system"
|
||||||
|
"github.com/olekukonko/tablewriter"
|
||||||
kingpin "gopkg.in/alecthomas/kingpin.v2"
|
kingpin "gopkg.in/alecthomas/kingpin.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -239,6 +241,60 @@ func drop(name string) {
|
|||||||
os.RemoveAll(appDataPath)
|
os.RemoveAll(appDataPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func autoBalloon(l *libvirt.Libvirt) {
|
||||||
|
domains, err := l.Domains()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
const memoryMin = 512 * 1024 // 512 MiB
|
||||||
|
|
||||||
|
table := tablewriter.NewWriter(os.Stdout)
|
||||||
|
table.SetHeader([]string{"Application VM", "Used memory", "Current memory", "Max memory", "New memory"})
|
||||||
|
for _, d := range domains {
|
||||||
|
if d.Name[0:5] == "appvm" {
|
||||||
|
name := d.Name[6:]
|
||||||
|
|
||||||
|
memoryUsedRaw, err := ioutil.ReadFile(os.Getenv("HOME") + "/appvm/" + name + "/.memory_used")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
memoryUsedMiB, err := strconv.Atoi(string(memoryUsedRaw[0 : len(memoryUsedRaw)-1]))
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
memoryUsed := memoryUsedMiB * 1024
|
||||||
|
|
||||||
|
_, memoryMax, memoryCurrent, _, _, err := l.DomainGetInfo(d)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
memoryNew := uint64(float64(memoryUsed) * 1.2) // +20%
|
||||||
|
|
||||||
|
if memoryNew > memoryMax {
|
||||||
|
memoryNew = memoryMax - 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if memoryNew < memoryMin {
|
||||||
|
memoryNew = memoryMin
|
||||||
|
}
|
||||||
|
|
||||||
|
err = l.DomainSetMemory(d, memoryNew)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
table.Append([]string{name,
|
||||||
|
fmt.Sprintf("%d", memoryUsed),
|
||||||
|
fmt.Sprintf("%d", memoryCurrent),
|
||||||
|
fmt.Sprintf("%d", memoryMax),
|
||||||
|
fmt.Sprintf("%d", memoryNew)})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
table.Render()
|
||||||
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
c, err := net.DialTimeout("unix", "/var/run/libvirt/libvirt-sock", time.Second)
|
c, err := net.DialTimeout("unix", "/var/run/libvirt/libvirt-sock", time.Second)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -252,6 +308,7 @@ func main() {
|
|||||||
defer l.Disconnect()
|
defer l.Disconnect()
|
||||||
|
|
||||||
kingpin.Command("list", "List applications")
|
kingpin.Command("list", "List applications")
|
||||||
|
kingpin.Command("autoballoon", "Automatically adjust/reduce app vm memory")
|
||||||
startName := kingpin.Command("start", "Start application").Arg("name", "Application name").Required().String()
|
startName := kingpin.Command("start", "Start application").Arg("name", "Application name").Required().String()
|
||||||
stopName := kingpin.Command("stop", "Stop application").Arg("name", "Application name").Required().String()
|
stopName := kingpin.Command("stop", "Stop application").Arg("name", "Application name").Required().String()
|
||||||
dropName := kingpin.Command("drop", "Remove application data").Arg("name", "Application name").Required().String()
|
dropName := kingpin.Command("drop", "Remove application data").Arg("name", "Application name").Required().String()
|
||||||
@ -265,5 +322,7 @@ func main() {
|
|||||||
stop(l, *stopName)
|
stop(l, *stopName)
|
||||||
case "drop":
|
case "drop":
|
||||||
drop(*dropName)
|
drop(*dropName)
|
||||||
|
case "autoballoon":
|
||||||
|
autoBalloon(l)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user