File: main.go

package info (click to toggle)
lxd 5.0.2%2Bgit20231211.1364ae4-9
  • links: PTS, VCS
  • area: main
  • in suites: sid, trixie
  • size: 25,632 kB
  • sloc: sh: 14,272; ansic: 3,112; python: 432; makefile: 265; ruby: 51; sql: 50; javascript: 9; lisp: 6
file content (147 lines) | stat: -rw-r--r-- 3,844 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
package main

import (
	"os"
	"time"

	"github.com/spf13/cobra"

	"github.com/canonical/lxd/client"
	"github.com/canonical/lxd/lxd-benchmark/benchmark"
	"github.com/canonical/lxd/shared"
	"github.com/canonical/lxd/shared/version"
)

type cmdGlobal struct {
	flagHelp        bool
	flagParallel    int
	flagProject     string
	flagReportFile  string
	flagReportLabel string
	flagVersion     bool

	srv            lxd.ContainerServer
	report         *benchmark.CSVReport
	reportDuration time.Duration
}

func (c *cmdGlobal) Run(cmd *cobra.Command, args []string) error {
	// Connect to LXD
	srv, err := lxd.ConnectLXDUnix("", nil)
	if err != nil {
		return err
	}

	c.srv = srv.UseProject(c.flagProject)

	// Print the initial header
	err = benchmark.PrintServerInfo(srv)
	if err != nil {
		return err
	}

	// Setup report handling
	if c.flagReportFile != "" {
		c.report = &benchmark.CSVReport{Filename: c.flagReportFile}
		if shared.PathExists(c.flagReportFile) {
			err := c.report.Load()
			if err != nil {
				return err
			}
		}
	}

	return nil
}

func (c *cmdGlobal) Teardown(cmd *cobra.Command, args []string) error {
	// Nothing to do with not reporting
	if c.report == nil {
		return nil
	}

	label := cmd.Name()
	if c.flagReportLabel != "" {
		label = c.flagReportLabel
	}

	err := c.report.AddRecord(label, c.reportDuration)
	if err != nil {
		return err
	}

	err = c.report.Write()
	if err != nil {
		return err
	}

	return nil
}

func main() {
	app := &cobra.Command{}
	app.Use = "lxd-benchmark"
	app.Short = "Benchmark performance of LXD"
	app.Long = `Description:
  Benchmark performance of LXD

  This tool lets you benchmark various actions on a local LXD daemon.

  It can be used just to check how fast a given LXD host is, to
  compare performance on different servers or for performance tracking
  when doing changes to the LXD codebase.

  A CSV report can be produced to be consumed by graphing software.
`
	app.Example = `  # Spawn 20 Ubuntu containers in batches of 4
  lxd-benchmark launch --count 20 --parallel 4

  # Create 50 Ubuntu Minimal 22.04 containers in batches of 10
  lxd-benchmark init --count 50 --parallel 10 ubuntu-minimal:22.04

  # Delete all test containers using dynamic batch size
  lxd-benchmark delete`
	app.SilenceUsage = true
	app.CompletionOptions = cobra.CompletionOptions{DisableDefaultCmd: true}

	// Global flags
	globalCmd := cmdGlobal{}
	app.PersistentPreRunE = globalCmd.Run
	app.PersistentPostRunE = globalCmd.Teardown
	app.PersistentFlags().BoolVar(&globalCmd.flagVersion, "version", false, "Print version number")
	app.PersistentFlags().BoolVarP(&globalCmd.flagHelp, "help", "h", false, "Print help")
	app.PersistentFlags().IntVarP(&globalCmd.flagParallel, "parallel", "P", -1, "Number of threads to use"+"``")
	app.PersistentFlags().StringVar(&globalCmd.flagReportFile, "report-file", "", "Path to the CSV report file"+"``")
	app.PersistentFlags().StringVar(&globalCmd.flagReportLabel, "report-label", "", "Label for the new entry in the report [default=ACTION]"+"``")
	app.PersistentFlags().StringVar(&globalCmd.flagProject, "project", "default", "Project to use")

	// Version handling
	app.SetVersionTemplate("{{.Version}}\n")
	app.Version = version.Version

	// init sub-command
	initCmd := cmdInit{global: &globalCmd}
	app.AddCommand(initCmd.Command())

	// launch sub-command
	launchCmd := cmdLaunch{global: &globalCmd, init: &initCmd}
	app.AddCommand(launchCmd.Command())

	// start sub-command
	startCmd := cmdStart{global: &globalCmd}
	app.AddCommand(startCmd.Command())

	// stop sub-command
	stopCmd := cmdStop{global: &globalCmd}
	app.AddCommand(stopCmd.Command())

	// delete sub-command
	deleteCmd := cmdDelete{global: &globalCmd}
	app.AddCommand(deleteCmd.Command())

	// Run the main command and handle errors
	err := app.Execute()
	if err != nil {
		os.Exit(1)
	}
}