-
Notifications
You must be signed in to change notification settings - Fork 131
Improve code readability for beginners by adding comments to clarify complex logic on package main #539
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Improve code readability for beginners by adding comments to clarify complex logic on package main #539
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,6 +11,15 @@ | |
// express or implied. See the License for the specific language governing | ||
// permissions and limitations under the License. | ||
|
||
// Package main provides a Go program for managing snapshots of Firecracker microVMs. | ||
// The program utilizes the Firecracker Go SDK for creating and loading snapshots, | ||
// and it demonstrates how to establish SSH connections to interact with microVMs. | ||
// Comments are provided to explain each function's purpose and usage. | ||
|
||
// In this program, a "snapshot" refers to a point-in-time copy of the state of a Firecracker microVM. | ||
// Snapshots capture the complete memory and state of the microVM, allowing users to save and restore its exact configuration and execution context. | ||
// They enable quick deployment and management of microVM instances with pre-defined configurations and states, which is useful for testing, development, and deployment scenarios. | ||
|
||
package main | ||
|
||
import ( | ||
|
@@ -31,19 +40,21 @@ import ( | |
models "github.com/firecracker-microvm/firecracker-go-sdk/client/models" | ||
) | ||
|
||
// Constants for CNI configuration | ||
const ( | ||
// Using default cache directory to ensure collision avoidance on IP allocations | ||
cniCacheDir = "/var/lib/cni" | ||
networkName = "fcnet" | ||
ifName = "veth0" | ||
cniCacheDir = "/var/lib/cni" // Default cache directory for IP allocations | ||
networkName = "fcnet" // Name of the network | ||
ifName = "veth0" // Interface name | ||
|
||
networkMask string = "/24" | ||
subnet string = "10.168.0.0" + networkMask | ||
networkMask = "/24" // Subnet mask | ||
subnet = "10.168.0.0" + networkMask | ||
|
||
maxRetries int = 10 | ||
backoffTimeMs time.Duration = 500 | ||
maxRetries = 10 // Maximum number of retries for SSH connection | ||
backoffTimeMs = 500 * time.Millisecond // Backoff time for retries | ||
) | ||
|
||
// writeCNIConfWithHostLocalSubnet writes CNI configuration to a file with a host-local subnet | ||
func writeCNIConfWithHostLocalSubnet(path, networkName, subnet string) error { | ||
return ioutil.WriteFile(path, []byte(fmt.Sprintf(`{ | ||
"cniVersion": "0.3.1", | ||
|
@@ -63,14 +74,17 @@ func writeCNIConfWithHostLocalSubnet(path, networkName, subnet string) error { | |
}`, networkName, subnet)), 0644) | ||
} | ||
|
||
// configOpt is a functional option for configuring the Firecracker microVM | ||
type configOpt func(*sdk.Config) | ||
|
||
// withNetworkInterface adds a network interface configuration option to the Firecracker microVM config | ||
func withNetworkInterface(networkInterface sdk.NetworkInterface) configOpt { | ||
return func(c *sdk.Config) { | ||
c.NetworkInterfaces = append(c.NetworkInterfaces, networkInterface) | ||
} | ||
} | ||
|
||
// createNewConfig creates a new Firecracker microVM configuration | ||
func createNewConfig(socketPath string, opts ...configOpt) sdk.Config { | ||
dir, _ := os.Getwd() | ||
fmt.Println(dir) | ||
|
@@ -110,6 +124,7 @@ func createNewConfig(socketPath string, opts ...configOpt) sdk.Config { | |
return cfg | ||
} | ||
|
||
// connectToVM establishes an SSH connection to the Firecracker microVM | ||
func connectToVM(m *sdk.Machine, sshKeyPath string) (*ssh.Client, error) { | ||
key, err := ioutil.ReadFile(sshKeyPath) | ||
if err != nil { | ||
|
@@ -139,6 +154,7 @@ func connectToVM(m *sdk.Machine, sshKeyPath string) (*ssh.Client, error) { | |
return ssh.Dial("tcp", fmt.Sprintf("%s:22", ip), config) | ||
} | ||
|
||
// createSnapshotSSH creates a snapshot of a Firecracker microVM and returns the IP of the VM | ||
func createSnapshotSSH(ctx context.Context, socketPath, memPath, snapPath string) string { | ||
dir, err := os.Getwd() | ||
if err != nil { | ||
|
@@ -246,6 +262,7 @@ func createSnapshotSSH(ctx context.Context, socketPath, memPath, snapPath string | |
return vmIP | ||
} | ||
|
||
// loadSnapshotSSH loads a snapshot of the Firecracker microVM using SSH | ||
func loadSnapshotSSH(ctx context.Context, socketPath, memPath, snapPath, ipToRestore string) { | ||
var ipFreed bool = false | ||
var err error | ||
|
@@ -383,48 +400,57 @@ func loadSnapshotSSH(ctx context.Context, socketPath, memPath, snapPath, ipToRes | |
|
||
func main() { | ||
// Check for kvm and root access | ||
err := unix.Access("/dev/kvm", unix.W_OK) | ||
if err != nil { | ||
err := unix.Access("/dev/kvm", unix.W_OK) // Check if the program has write access to /dev/kvm | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Most of the code here is self-explanatory and/or understandable with a quick search. I would prefer to have more readable code, than annotate every line of code with comments. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks for your kind word. |
||
if err != nil { // If there's an error (e.g., access denied), log and exit | ||
log.Fatal(err) | ||
} | ||
|
||
// Check if the program is running with root privileges | ||
if x, y := 0, os.Getuid(); x != y { | ||
log.Fatal("Root acccess denied") | ||
} | ||
|
||
// Get the current working directory | ||
dir, err := os.Getwd() | ||
if err != nil { | ||
if err != nil { // If there's an error getting the working directory, log and exit | ||
log.Fatal(err) | ||
} | ||
|
||
// Create a directory for CNI configuration files | ||
cniConfDir := filepath.Join(dir, "cni.conf") | ||
err = os.Mkdir(cniConfDir, 0777) | ||
if err != nil { | ||
err = os.Mkdir(cniConfDir, 0777) // Create the directory with full permissions | ||
if err != nil { // If there's an error creating the directory, log and exit | ||
log.Fatal(err) | ||
} | ||
defer os.Remove(cniConfDir) | ||
defer os.Remove(cniConfDir) // Remove the directory when main function exits | ||
|
||
// Setup socket and snapshot + memory paths | ||
tempdir, err := ioutil.TempDir("", "FCGoSDKSnapshotExample") | ||
if err != nil { | ||
// Setup temporary directory and paths for socket, snapshot, and memory files | ||
tempdir, err := ioutil.TempDir("", "FCGoSDKSnapshotExample") // Create a temporary directory | ||
if err != nil { // If there's an error creating the temporary directory, log and exit | ||
log.Fatal(err) | ||
} | ||
defer os.Remove(tempdir) | ||
socketPath := filepath.Join(tempdir, "snapshotssh") | ||
defer os.Remove(tempdir) // Remove the temporary directory when main function exits | ||
socketPath := filepath.Join(tempdir, "snapshotssh") // Create a socket path within the temporary directory | ||
|
||
// Create a directory for snapshot and memory files | ||
snapshotsshPath := filepath.Join(dir, "snapshotssh") | ||
err = os.Mkdir(snapshotsshPath, 0777) | ||
if err != nil && !errors.Is(err, os.ErrExist) { | ||
err = os.Mkdir(snapshotsshPath, 0777) // Create the directory with full permissions | ||
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 | ||
log.Fatal(err) | ||
} | ||
defer os.RemoveAll(snapshotsshPath) | ||
defer os.RemoveAll(snapshotsshPath) // Remove the directory and its contents when main function exits | ||
|
||
// Set paths for snapshot and memory files | ||
snapPath := filepath.Join(snapshotsshPath, "SnapFile") | ||
memPath := filepath.Join(snapshotsshPath, "MemFile") | ||
|
||
// Create a background context | ||
ctx := context.Background() | ||
|
||
// Create a snapshot of the Firecracker microVM and get the IP address to restore | ||
ipToRestore := createSnapshotSSH(ctx, socketPath, memPath, snapPath) | ||
fmt.Println() | ||
|
||
// Load the snapshot of the Firecracker microVM | ||
loadSnapshotSSH(ctx, socketPath, memPath, snapPath, ipToRestore) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
https://github.com/firecracker-microvm/firecracker-go-sdk/blob/main/examples/cmd/snapshotting/README.md will be a better place for this information