Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
lima-vm
GitHub Repository: lima-vm/lima
Path: blob/master/cmd/limactl/snapshot.go
2621 views
1
// SPDX-FileCopyrightText: Copyright The Lima Authors
2
// SPDX-License-Identifier: Apache-2.0
3
4
package main
5
6
import (
7
"errors"
8
"fmt"
9
"strings"
10
11
"github.com/sirupsen/logrus"
12
"github.com/spf13/cobra"
13
14
"github.com/lima-vm/lima/v2/pkg/snapshot"
15
"github.com/lima-vm/lima/v2/pkg/store"
16
)
17
18
func newSnapshotCommand() *cobra.Command {
19
snapshotCmd := &cobra.Command{
20
Use: "snapshot",
21
Short: "Manage instance snapshots",
22
Example: ` List all snapshots of an instance:
23
$ limactl snapshot list default
24
25
Create a snapshot:
26
$ limactl snapshot create default --tag snap1
27
28
Apply (restore) a snapshot:
29
$ limactl snapshot apply default --tag snap1
30
31
Delete a snapshot:
32
$ limactl snapshot delete default --tag snap1
33
`,
34
PersistentPreRun: func(*cobra.Command, []string) {
35
logrus.Warn("`limactl snapshot` is experimental")
36
},
37
GroupID: advancedCommand,
38
}
39
snapshotCmd.AddCommand(newSnapshotApplyCommand())
40
snapshotCmd.AddCommand(newSnapshotCreateCommand())
41
snapshotCmd.AddCommand(newSnapshotDeleteCommand())
42
snapshotCmd.AddCommand(newSnapshotListCommand())
43
44
return snapshotCmd
45
}
46
47
func newSnapshotCreateCommand() *cobra.Command {
48
createCmd := &cobra.Command{
49
Use: "create INSTANCE",
50
Aliases: []string{"save"},
51
Short: "Create (save) a snapshot",
52
Example: ` Create a snapshot of an instance:
53
$ limactl snapshot create default --tag snap1
54
`,
55
Args: cobra.MinimumNArgs(1),
56
RunE: snapshotCreateAction,
57
ValidArgsFunction: snapshotBashComplete,
58
}
59
createCmd.Flags().String("tag", "", "Name of the snapshot")
60
61
return createCmd
62
}
63
64
func snapshotCreateAction(cmd *cobra.Command, args []string) error {
65
ctx := cmd.Context()
66
instName := args[0]
67
68
inst, err := store.Inspect(ctx, instName)
69
if err != nil {
70
return err
71
}
72
73
tag, err := cmd.Flags().GetString("tag")
74
if err != nil {
75
return err
76
}
77
78
if tag == "" {
79
return errors.New("expected tag")
80
}
81
82
return snapshot.Save(ctx, inst, tag)
83
}
84
85
func newSnapshotDeleteCommand() *cobra.Command {
86
deleteCmd := &cobra.Command{
87
Use: "delete INSTANCE",
88
Aliases: []string{"del"},
89
Short: "Delete (del) a snapshot",
90
Example: ` Delete a snapshot:
91
$ limactl snapshot delete default --tag snap1
92
`,
93
Args: cobra.MinimumNArgs(1),
94
RunE: snapshotDeleteAction,
95
ValidArgsFunction: snapshotBashComplete,
96
}
97
deleteCmd.Flags().String("tag", "", "Name of the snapshot")
98
99
return deleteCmd
100
}
101
102
func snapshotDeleteAction(cmd *cobra.Command, args []string) error {
103
ctx := cmd.Context()
104
instName := args[0]
105
106
inst, err := store.Inspect(ctx, instName)
107
if err != nil {
108
return err
109
}
110
111
tag, err := cmd.Flags().GetString("tag")
112
if err != nil {
113
return err
114
}
115
116
if tag == "" {
117
return errors.New("expected tag")
118
}
119
120
return snapshot.Del(ctx, inst, tag)
121
}
122
123
func newSnapshotApplyCommand() *cobra.Command {
124
applyCmd := &cobra.Command{
125
Use: "apply INSTANCE",
126
Aliases: []string{"load"},
127
Short: "Apply (load) a snapshot",
128
Example: ` Apply (restore) a snapshot:
129
$ limactl snapshot apply default --tag snap1
130
`,
131
Args: cobra.MinimumNArgs(1),
132
RunE: snapshotApplyAction,
133
ValidArgsFunction: snapshotBashComplete,
134
}
135
applyCmd.Flags().String("tag", "", "Name of the snapshot")
136
137
return applyCmd
138
}
139
140
func snapshotApplyAction(cmd *cobra.Command, args []string) error {
141
ctx := cmd.Context()
142
instName := args[0]
143
144
inst, err := store.Inspect(ctx, instName)
145
if err != nil {
146
return err
147
}
148
149
tag, err := cmd.Flags().GetString("tag")
150
if err != nil {
151
return err
152
}
153
154
if tag == "" {
155
return errors.New("expected tag")
156
}
157
158
return snapshot.Load(ctx, inst, tag)
159
}
160
161
func newSnapshotListCommand() *cobra.Command {
162
listCmd := &cobra.Command{
163
Use: "list INSTANCE",
164
Aliases: []string{"ls"},
165
Short: "List existing snapshots",
166
Example: ` List all snapshots of an instance:
167
$ limactl snapshot list default
168
169
List only snapshot tags:
170
$ limactl snapshot list default --quiet
171
`,
172
Args: cobra.MinimumNArgs(1),
173
RunE: snapshotListAction,
174
ValidArgsFunction: snapshotBashComplete,
175
}
176
listCmd.Flags().BoolP("quiet", "q", false, "Only show tags")
177
178
return listCmd
179
}
180
181
func snapshotListAction(cmd *cobra.Command, args []string) error {
182
ctx := cmd.Context()
183
instName := args[0]
184
185
inst, err := store.Inspect(ctx, instName)
186
if err != nil {
187
return err
188
}
189
190
quiet, err := cmd.Flags().GetBool("quiet")
191
if err != nil {
192
return err
193
}
194
out, err := snapshot.List(ctx, inst)
195
if err != nil {
196
return err
197
}
198
if quiet {
199
for i, line := range strings.Split(out, "\n") {
200
// "ID", "TAG", "VM SIZE", "DATE", "VM CLOCK", "ICOUNT"
201
fields := strings.Fields(line)
202
if i == 0 && len(fields) > 1 && fields[1] != "TAG" {
203
// make sure that output matches the expected
204
return fmt.Errorf("unknown header: %s", line)
205
}
206
if i == 0 || line == "" {
207
// skip header and empty line after using split
208
continue
209
}
210
tag := fields[1]
211
fmt.Fprintf(cmd.OutOrStdout(), "%s\n", tag)
212
}
213
return nil
214
}
215
fmt.Fprint(cmd.OutOrStdout(), out)
216
return nil
217
}
218
219
func snapshotBashComplete(cmd *cobra.Command, _ []string, _ string) ([]string, cobra.ShellCompDirective) {
220
return bashCompleteInstanceNames(cmd)
221
}
222
223