Skip to content

Commit 15722d3

Browse files
committed
Change vm db structure
Allow remove tags from VM
1 parent 7206689 commit 15722d3

File tree

7 files changed

+133
-44
lines changed

7 files changed

+133
-44
lines changed

cmd/tag.go

+6-4
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,17 @@ import (
2626
// tagCmd represents the tag command
2727
var tagCmd = &cobra.Command{
2828
Use: "tag",
29-
Short: "Tag a VM",
30-
Long: `Tag a VM
29+
Short: "Add or remove tag to a VM",
30+
Long: `Add or remove tag to a VM
3131
You can tag a VM as many times as you want
3232
`,
3333
Run: func(cmd *cobra.Command, args []string) {
3434
vmName := args[0]
3535
tag := args[1]
3636

37-
err := vms.Tag(vmName, tag)
37+
remove, _ := cmd.Flags().GetBool("remove")
38+
39+
err := vms.Tag(vmName, tag, remove)
3840
if err != nil {
3941
fmt.Println(err)
4042
os.Exit(1)
@@ -63,5 +65,5 @@ func init() {
6365

6466
// Cobra supports local flags which will only run when this command
6567
// is called directly, e.g.:
66-
//tagCmd.Flags().BoolP("purge", "p", false, "Purge the IP cache")
68+
tagCmd.Flags().BoolP("remove", "r", false, "remove tag")
6769
}

db/db.go

-31
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,11 @@
11
package db
22

33
import (
4-
"io/ioutil"
54
"log"
65
"os"
7-
"strings"
86
)
97

108
const (
11-
image = "image"
12-
tags = "tags"
139
Username = "vermin"
1410
)
1511

@@ -32,33 +28,6 @@ func GetVMPath(vm string) string {
3228
return VMsBaseDir + string(os.PathSeparator) + vm
3329
}
3430

35-
// ----
36-
func WriteTag(vmName string, tag string) error {
37-
return appendToFile(GetVMPath(vmName)+"/"+tags, []byte(tag+"\n"), 0755)
38-
}
39-
40-
func ReadTags(vmName string) (string, error) {
41-
content, err := readFromFile(vmName, tags)
42-
if err != nil {
43-
return "", err
44-
}
45-
return strings.TrimSuffix(strings.ReplaceAll(content, "\n", ", "), ", "), nil
46-
}
47-
48-
// ----
49-
50-
func WriteImageData(vmName string, imageName string) error {
51-
return ioutil.WriteFile(GetVMPath(vmName)+"/"+image, []byte(imageName), 0755)
52-
}
53-
54-
func ReadImageData(vmName string) (string, error) {
55-
content, err := readFromFile(vmName, image)
56-
if err != nil {
57-
return "", err
58-
}
59-
return strings.ReplaceAll(content, "\n", ""), nil
60-
}
61-
6231
func getVerminDir() string {
6332
dir, err := os.UserHomeDir()
6433
if err != nil {

db/vmdb.go

+115
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
package db
2+
3+
import (
4+
"encoding/gob"
5+
"io"
6+
"io/ioutil"
7+
"os"
8+
"strings"
9+
)
10+
11+
// Decided to use gob package instead of protobuf after reading this https://blog.golang.org/gob
12+
13+
const vmdbFilename = "vmdb"
14+
15+
type VMDB struct {
16+
Image string
17+
Tags []string
18+
}
19+
20+
func Load(vm string) (VMDB, error) {
21+
migrate(vm)
22+
file, err := os.Open(GetVMPath(vm) + "/" + vmdbFilename)
23+
if err != nil {
24+
return VMDB{}, err
25+
}
26+
defer file.Close()
27+
28+
return load(file)
29+
}
30+
31+
func SetImage(vm string, image string) error {
32+
migrate(vm)
33+
return override(vm, func(vmdb *VMDB) {
34+
vmdb.Image = image
35+
})
36+
}
37+
38+
func AddTag(vm string, tag string) error {
39+
migrate(vm)
40+
return override(vm, func(vmdb *VMDB) {
41+
vmdb.Tags = append(vmdb.Tags, tag)
42+
})
43+
}
44+
45+
func RemoveTag(vm string, tag string) error {
46+
migrate(vm)
47+
return override(vm, func(vmdb *VMDB) {
48+
for i, v := range vmdb.Tags {
49+
if v == tag {
50+
vmdb.Tags = append(vmdb.Tags[:i], vmdb.Tags[i+1:]...)
51+
break
52+
}
53+
}
54+
})
55+
}
56+
57+
// Override the VMDB for the vm passed as the first parameter
58+
// by applying the fn function on the data loaded from disk
59+
// and then write back to the disk
60+
func override(vm string, fn func(vmdb *VMDB)) error {
61+
file, err := os.OpenFile(GetVMPath(vm)+"/"+vmdbFilename, os.O_RDWR|os.O_CREATE, 0755)
62+
if err != nil {
63+
return err
64+
}
65+
defer file.Close()
66+
67+
vmdb, err := load(file)
68+
if err != nil {
69+
return err
70+
}
71+
72+
fn(&vmdb)
73+
74+
// clear the file before save
75+
if err := file.Truncate(0); err != nil {
76+
return err
77+
}
78+
if _, err := file.Seek(0, 0); err != nil {
79+
return err
80+
}
81+
// serialize
82+
if err := gob.NewEncoder(file).Encode(vmdb); err != nil {
83+
return err
84+
}
85+
86+
return nil
87+
}
88+
89+
func load(file *os.File) (VMDB, error) {
90+
var vmdb VMDB
91+
if err := gob.NewDecoder(file).Decode(&vmdb); err != nil && io.EOF != err {
92+
return VMDB{}, err
93+
}
94+
return vmdb, nil
95+
}
96+
97+
// --- migrate old db structure
98+
func migrate(vm string) {
99+
if _, err := os.Stat(GetVMPath(vm) + "/" + vmdbFilename); err == nil {
100+
return // already migrated
101+
}
102+
_ = override(vm, func(vmdb *VMDB) {
103+
b, err := ioutil.ReadFile(GetVMPath(vm) + "/image")
104+
if err == nil {
105+
vmdb.Image = string(b)
106+
}
107+
108+
b, err = ioutil.ReadFile(GetVMPath(vm) + "/tags")
109+
if err == nil {
110+
tags := string(b)
111+
split := strings.Split(tags, "\n")
112+
vmdb.Tags = split[:len(split)-1]
113+
}
114+
})
115+
}

vms/create.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ func Create(imageName string, script string, cpus int, mem int) (string, error)
3434
return "", err
3535
}
3636

37-
if err = db.WriteImageData(vmName, imageName); err != nil {
37+
if err = db.SetImage(vmName, imageName); err != nil {
3838
return "", err
3939
}
4040

vms/list.go

+3-4
Original file line numberDiff line numberDiff line change
@@ -173,15 +173,14 @@ func getVMInfo(vm string) vmInfo {
173173

174174
box, _ := db.GetBoxInfo(vm)
175175
disk := getDiskSizeInGB(vm, box.HDLocation)
176-
image, _ := db.ReadImageData(vm)
177-
tags, _ := db.ReadTags(vm)
176+
vmdb, _ := db.Load(vm)
178177

179178
return vmInfo{
180179
name: vm,
181-
image: image,
180+
image: vmdb.Image,
182181
box: *box,
183182
disk: disk,
184-
tags: tags,
183+
tags: strings.Join(vmdb.Tags, ", "),
185184
}
186185
}
187186

vms/mount.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,12 @@ func Mount(vmName string, hostPath string) error {
1515
return err
1616
}
1717

18-
image, err := db.ReadImageData(vmName)
18+
vmdb, err := db.Load(vmName)
1919
if err != nil {
2020
return err
2121
}
2222

23-
if err = images.CheckCanMount(image); err != nil {
23+
if err = images.CheckCanMount(vmdb.Image); err != nil {
2424
return err
2525
}
2626

vms/vms.go

+6-2
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,15 @@ import (
1313
"strings"
1414
)
1515

16-
func Tag(vmName string, tag string) error {
16+
func Tag(vmName string, tag string, remove bool) error {
1717
if err := checkVM(vmName); err != nil {
1818
return err
1919
}
20-
return db.WriteTag(vmName, tag)
20+
if remove {
21+
return db.RemoveTag(vmName, tag)
22+
} else {
23+
return db.AddTag(vmName, tag)
24+
}
2125
}
2226

2327
func Start(vmName string) error {

0 commit comments

Comments
 (0)