1111// express or implied. See the License for the specific language governing
1212// permissions and limitations under the License.
1313
14+ // Package main provides a Go program for managing snapshots of Firecracker microVMs.
15+ // The program utilizes the Firecracker Go SDK for creating and loading snapshots,
16+ // and it demonstrates how to establish SSH connections to interact with microVMs.
17+ // Comments are provided to explain each function's purpose and usage.
18+
19+ // In this program, a "snapshot" refers to a point-in-time copy of the state of a Firecracker microVM.
20+ // Snapshots capture the complete memory and state of the microVM, allowing users to save and restore its exact configuration and execution context.
21+ // They enable quick deployment and management of microVM instances with pre-defined configurations and states, which is useful for testing, development, and deployment scenarios.
22+
1423package main
1524
1625import (
@@ -31,19 +40,21 @@ import (
3140 models "github.com/firecracker-microvm/firecracker-go-sdk/client/models"
3241)
3342
43+ // Constants for CNI configuration
3444const (
3545 // Using default cache directory to ensure collision avoidance on IP allocations
36- cniCacheDir = "/var/lib/cni"
37- networkName = "fcnet"
38- ifName = "veth0"
46+ cniCacheDir = "/var/lib/cni" // Default cache directory for IP allocations
47+ networkName = "fcnet" // Name of the network
48+ ifName = "veth0" // Interface name
3949
40- networkMask string = "/24"
41- subnet string = "10.168.0.0" + networkMask
50+ networkMask = "/24" // Subnet mask
51+ subnet = "10.168.0.0" + networkMask
4252
43- maxRetries int = 10
44- backoffTimeMs time.Duration = 500
53+ maxRetries = 10 // Maximum number of retries for SSH connection
54+ backoffTimeMs = 500 * time .Millisecond // Backoff time for retries
4555)
4656
57+ // writeCNIConfWithHostLocalSubnet writes CNI configuration to a file with a host-local subnet
4758func writeCNIConfWithHostLocalSubnet (path , networkName , subnet string ) error {
4859 return ioutil .WriteFile (path , []byte (fmt .Sprintf (`{
4960 "cniVersion": "0.3.1",
@@ -63,14 +74,17 @@ func writeCNIConfWithHostLocalSubnet(path, networkName, subnet string) error {
6374 }` , networkName , subnet )), 0644 )
6475}
6576
77+ // configOpt is a functional option for configuring the Firecracker microVM
6678type configOpt func (* sdk.Config )
6779
80+ // withNetworkInterface adds a network interface configuration option to the Firecracker microVM config
6881func withNetworkInterface (networkInterface sdk.NetworkInterface ) configOpt {
6982 return func (c * sdk.Config ) {
7083 c .NetworkInterfaces = append (c .NetworkInterfaces , networkInterface )
7184 }
7285}
7386
87+ // createNewConfig creates a new Firecracker microVM configuration
7488func createNewConfig (socketPath string , opts ... configOpt ) sdk.Config {
7589 dir , _ := os .Getwd ()
7690 fmt .Println (dir )
@@ -110,6 +124,7 @@ func createNewConfig(socketPath string, opts ...configOpt) sdk.Config {
110124 return cfg
111125}
112126
127+ // connectToVM establishes an SSH connection to the Firecracker microVM
113128func connectToVM (m * sdk.Machine , sshKeyPath string ) (* ssh.Client , error ) {
114129 key , err := ioutil .ReadFile (sshKeyPath )
115130 if err != nil {
@@ -139,6 +154,7 @@ func connectToVM(m *sdk.Machine, sshKeyPath string) (*ssh.Client, error) {
139154 return ssh .Dial ("tcp" , fmt .Sprintf ("%s:22" , ip ), config )
140155}
141156
157+ // createSnapshotSSH creates a snapshot of a Firecracker microVM and returns the IP of the VM
142158func createSnapshotSSH (ctx context.Context , socketPath , memPath , snapPath string ) string {
143159 dir , err := os .Getwd ()
144160 if err != nil {
@@ -246,6 +262,7 @@ func createSnapshotSSH(ctx context.Context, socketPath, memPath, snapPath string
246262 return vmIP
247263}
248264
265+ // loadSnapshotSSH loads a snapshot of the Firecracker microVM using SSH
249266func loadSnapshotSSH (ctx context.Context , socketPath , memPath , snapPath , ipToRestore string ) {
250267 var ipFreed bool = false
251268 var err error
@@ -383,48 +400,57 @@ func loadSnapshotSSH(ctx context.Context, socketPath, memPath, snapPath, ipToRes
383400
384401func main () {
385402 // Check for kvm and root access
386- err := unix .Access ("/dev/kvm" , unix .W_OK )
387- if err != nil {
403+ err := unix .Access ("/dev/kvm" , unix .W_OK ) // Check if the program has write access to /dev/kvm
404+ if err != nil { // If there's an error (e.g., access denied), log and exit
388405 log .Fatal (err )
389406 }
390407
408+ // Check if the program is running with root privileges
391409 if x , y := 0 , os .Getuid (); x != y {
392410 log .Fatal ("Root acccess denied" )
393411 }
394412
413+ // Get the current working directory
395414 dir , err := os .Getwd ()
396- if err != nil {
415+ if err != nil { // If there's an error getting the working directory, log and exit
397416 log .Fatal (err )
398417 }
399418
419+ // Create a directory for CNI configuration files
400420 cniConfDir := filepath .Join (dir , "cni.conf" )
401- err = os .Mkdir (cniConfDir , 0777 )
402- if err != nil {
421+ err = os .Mkdir (cniConfDir , 0777 ) // Create the directory with full permissions
422+ if err != nil { // If there's an error creating the directory, log and exit
403423 log .Fatal (err )
404424 }
405- defer os .Remove (cniConfDir )
425+ defer os .Remove (cniConfDir ) // Remove the directory when main function exits
406426
407- // Setup socket and snapshot + memory paths
408- tempdir , err := ioutil .TempDir ("" , "FCGoSDKSnapshotExample" )
409- if err != nil {
427+ // Setup temporary directory and paths for socket, snapshot, and memory files
428+ tempdir , err := ioutil .TempDir ("" , "FCGoSDKSnapshotExample" ) // Create a temporary directory
429+ if err != nil { // If there's an error creating the temporary directory, log and exit
410430 log .Fatal (err )
411431 }
412- defer os .Remove (tempdir )
413- socketPath := filepath .Join (tempdir , "snapshotssh" )
432+ defer os .Remove (tempdir ) // Remove the temporary directory when main function exits
433+ socketPath := filepath .Join (tempdir , "snapshotssh" ) // Create a socket path within the temporary directory
414434
435+ // Create a directory for snapshot and memory files
415436 snapshotsshPath := filepath .Join (dir , "snapshotssh" )
416- err = os .Mkdir (snapshotsshPath , 0777 )
417- if err != nil && ! errors .Is (err , os .ErrExist ) {
437+ err = os .Mkdir (snapshotsshPath , 0777 ) // Create the directory with full permissions
438+ if err != nil && ! errors .Is (err , os .ErrExist ) { // If there's an error creating the directory and it's not already exist, log and exit
418439 log .Fatal (err )
419440 }
420- defer os .RemoveAll (snapshotsshPath )
441+ defer os .RemoveAll (snapshotsshPath ) // Remove the directory and its contents when main function exits
421442
443+ // Set paths for snapshot and memory files
422444 snapPath := filepath .Join (snapshotsshPath , "SnapFile" )
423445 memPath := filepath .Join (snapshotsshPath , "MemFile" )
424446
447+ // Create a background context
425448 ctx := context .Background ()
426449
450+ // Create a snapshot of the Firecracker microVM and get the IP address to restore
427451 ipToRestore := createSnapshotSSH (ctx , socketPath , memPath , snapPath )
428452 fmt .Println ()
453+
454+ // Load the snapshot of the Firecracker microVM
429455 loadSnapshotSSH (ctx , socketPath , memPath , snapPath , ipToRestore )
430456}
0 commit comments