Skip to content

Commit

Permalink
add rng device option
Browse files Browse the repository at this point in the history
  • Loading branch information
mabeett committed Jun 5, 2023
1 parent 71aaac3 commit 3e66773
Show file tree
Hide file tree
Showing 12 changed files with 267 additions and 1 deletion.
2 changes: 2 additions & 0 deletions builder/proxmox/clone/config.hcl2spec.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

62 changes: 61 additions & 1 deletion builder/proxmox/common/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// SPDX-License-Identifier: MPL-2.0

//go:generate packer-sdc struct-markdown
//go:generate packer-sdc mapstructure-to-hcl2 -type Config,NICConfig,diskConfig,vgaConfig,additionalISOsConfig,efiConfig
//go:generate packer-sdc mapstructure-to-hcl2 -type Config,NICConfig,diskConfig,rng0Config,vgaConfig,additionalISOsConfig,efiConfig

package proxmox

Expand Down Expand Up @@ -59,6 +59,7 @@ type Config struct {
EFIConfig efiConfig `mapstructure:"efi_config"`
EFIDisk string `mapstructure:"efidisk"`
Machine string `mapstructure:"machine"`
Rng0 rng0Config `mapstructure:"rng0"`
VGA vgaConfig `mapstructure:"vga"`
NICs []NICConfig `mapstructure:"network_adapters"`
Disks []diskConfig `mapstructure:"disks"`
Expand Down Expand Up @@ -114,6 +115,50 @@ type efiConfig struct {
PreEnrolledKeys bool `mapstructure:"pre_enrolled_keys"`
EFIType string `mapstructure:"efi_type"`
}

// - `rng0` (object): Configure Random Number Generator via VirtIO.
// A virtual hardware-RNG can be used to provide entropy from the host system to a guest VM helping avoid entropy starvation which might cause the guest system slow down.
// The device is sourced from a host device and guest, his use can be limited: `max_bytes` bytes of data will become available on a `period` ms timer.
// [PVE documentation](https://pve.proxmox.com/pve-docs/pve-admin-guide.html) recommends to always use a limiter to avoid guests using too many host resources.
//
// HCL2 example:
//
// ```hcl
// rng0 {
// source = "/dev/urandom"
// max_bytes = 1024
// period = 1000
// }
// ```
//
// JSON example:
//
// ```json
// {
// "rng0": {
// "source": "/dev/urandom",
// "max_bytes": 1024,
// "period": 1000
// }
// }
// ```
type rng0Config struct {
// Device on the host to gather entropy from.
// `/dev/urandom` should be preferred over `/dev/random` as Proxmox PVE documentation suggests.
// `/dev/hwrng` can be used to pass through a hardware RNG.
// Can be one of `/dev/urandom`, `/dev/random`, `/dev/hwrng`.
Source string `mapstructure:"source" required:"true"`
// Maximum bytes of entropy allowed to get injected into the guest every `period` milliseconds.
// Use a lower value when using `/dev/random` since can lead to entropy starvation on the host system.
// `0` disables limiting and according to PVE documentation is potentially dangerous for the host.
// Recommended value: `1024`.
MaxBytes int `mapstructure:"max_bytes" required:"true"`
// Period in milliseconds on which the the entropy-injection quota is reset.
// Can be a positive value.
// Recommended value: `1000`.
Period int `mapstructure:"period" required:"false"`
}

type vgaConfig struct {
Type string `mapstructure:"type"`
Memory int `mapstructure:"memory"`
Expand Down Expand Up @@ -391,6 +436,21 @@ func (c *Config) Prepare(upper interface{}, raws ...interface{}) ([]string, []st
errs = packersdk.MultiErrorAppend(errs, errors.New("efi_storage_pool not set for efi_config"))
}
}
if c.Rng0 != (rng0Config{}) {
if !(c.Rng0.Source == "/dev/urandom" || c.Rng0.Source == "/dev/random" || c.Rng0.Source == "/dev/hwrng") {
errs = packersdk.MultiErrorAppend(errs, errors.New("source must be one of \"/dev/urandom\", \"/dev/random\", \"/dev/hwrng\""))
}
if c.Rng0.MaxBytes < 0 {
errs = packersdk.MultiErrorAppend(errs, errors.New("max_bytes must be greather or equal than 0"))
} else {
if c.Rng0.MaxBytes == 0 {
warnings = append(warnings, "max_bytes is 0: potentially dangerous: this disables limiting the entropy allowed to get injected into the guest")
}
}
if c.Rng0.Period < 0 {
errs = packersdk.MultiErrorAppend(errs, errors.New("period must be greather than 0"))
}
}

if errs != nil && len(errs.Errors) > 0 {
return nil, warnings, errs
Expand Down
29 changes: 29 additions & 0 deletions builder/proxmox/common/config.hcl2spec.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

83 changes: 83 additions & 0 deletions builder/proxmox/common/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,89 @@ func TestAdditionalISOs(t *testing.T) {

}

func TestRng0(t *testing.T) {
Rng0Test := []struct {
name string
rng_config rng0Config
expectFailure bool
}{
{
name: "no error",
expectFailure: false,
rng_config: rng0Config{
Source: "/dev/urandom",
MaxBytes: 1024,
Period: 1000,
},
},
{
name: "empty Source, error",
expectFailure: true,
rng_config: rng0Config{
Source: "",
MaxBytes: 1024,
Period: 1000,
},
},
{
name: "negative Period, error",
expectFailure: true,
rng_config: rng0Config{
Source: "/dev/urandom",
MaxBytes: 1024,
Period: -10,
},
},
{
name: "zero Period, noerror",
expectFailure: false,
rng_config: rng0Config{
Source: "/dev/urandom",
MaxBytes: 1024,
Period: 0,
},
},
{
name: "malformed Source error, error",
expectFailure: true,
rng_config: rng0Config{
Source: "/dev/abcde",
MaxBytes: 1024,
Period: 1000,
},
},
{
name: "negative Period, error",
expectFailure: true,
rng_config: rng0Config{
Source: "/dev/urandom",
MaxBytes: 1024,
Period: -10,
},
},
}

for _, tt := range Rng0Test {
t.Run(tt.name, func(t *testing.T) {
cfg := mandatoryConfig(t)
cfg["rng0"] = &tt.rng_config

var c Config
_, _, err := c.Prepare(&c, cfg)
if err != nil {
if !tt.expectFailure {
t.Fatalf("unexpected failure to prepare config: %s", err)
}
t.Logf("got expected failure: %s", err)
}

if err == nil && tt.expectFailure {
t.Errorf("expected failure, but prepare succeeded")
}
})
}
}

func TestSerials(t *testing.T) {
serialsTest := []struct {
name string
Expand Down
14 changes: 14 additions & 0 deletions builder/proxmox/common/step_start_vm.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ func (s *stepStartVM) Run(ctx context.Context, state multistep.StateBag) multist
Bios: c.BIOS,
EFIDisk: generateProxmoxEfi(c.EFIConfig),
Machine: c.Machine,
RNGDrive: generateProxmoxRng0(c.Rng0),
QemuVga: generateProxmoxVga(c.VGA),
QemuNetworks: generateProxmoxNetworkAdapters(c.NICs),
QemuDisks: generateProxmoxDisks(c.Disks),
Expand Down Expand Up @@ -295,6 +296,19 @@ func generateProxmoxSerials(serials []string) proxmox.QemuDevices {
return devs
}

func generateProxmoxRng0(rng0 rng0Config) proxmox.QemuDevice {
dev := make(proxmox.QemuDevice)
setDeviceParamIfDefined(dev, "source", rng0.Source)

if rng0.MaxBytes >= 0 {
dev["max_bytes"] = rng0.MaxBytes
}
if rng0.Period > 0 {
dev["period"] = rng0.Period
}
return dev
}

func generateProxmoxVga(vga vgaConfig) proxmox.QemuDevice {
dev := make(proxmox.QemuDevice)
setDeviceParamIfDefined(dev, "type", vga.Type)
Expand Down
2 changes: 2 additions & 0 deletions builder/proxmox/iso/config.hcl2spec.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions docs-partials/builder/proxmox/common/Config-not-required.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@

- `machine` (string) - Machine

- `rng0` (rng0Config) - Rng 0

- `vga` (vgaConfig) - VGA

- `network_adapters` ([]NICConfig) - NI Cs
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<!-- Code generated from the comments of the rng0Config struct in builder/proxmox/common/config.go; DO NOT EDIT MANUALLY -->

- `period` (int) - Period in milliseconds on which the the entropy-injection quota is reset.
Can be a positive value.
Recommended value: `1000`.

<!-- End of code generated from the comments of the rng0Config struct in builder/proxmox/common/config.go; -->
13 changes: 13 additions & 0 deletions docs-partials/builder/proxmox/common/rng0Config-required.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!-- Code generated from the comments of the rng0Config struct in builder/proxmox/common/config.go; DO NOT EDIT MANUALLY -->

- `source` (string) - Device on the host to gather entropy from.
`/dev/urandom` should be preferred over `/dev/random` as Proxmox PVE documentation suggests.
`/dev/hwrng` can be used to pass through a hardware RNG.
Can be one of `/dev/urandom`, `/dev/random`, `/dev/hwrng`.

- `max_bytes` (int) - Maximum bytes of entropy allowed to get injected into the guest every `period` milliseconds.
Use a lower value when using `/dev/random` since can lead to entropy starvation on the host system.
`0` disables limiting and according to PVE documentation is potentially dangerous for the host.
Recommended value: `1024`.

<!-- End of code generated from the comments of the rng0Config struct in builder/proxmox/common/config.go; -->
30 changes: 30 additions & 0 deletions docs-partials/builder/proxmox/common/rng0Config.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<!-- Code generated from the comments of the rng0Config struct in builder/proxmox/common/config.go; DO NOT EDIT MANUALLY -->

- `rng0` (object): Configure Random Number Generator via VirtIO.
A virtual hardware-RNG can be used to provide entropy from the host system to a guest VM helping avoid entropy starvation which might cause the guest system slow down.
The device is sourced from a host device and guest, his use can be limited: `max_bytes` bytes of data will become available on a `period` ms timer.
[PVE documentation](https://pve.proxmox.com/pve-docs/pve-admin-guide.html) recommends to always use a limiter to avoid guests using too many host resources.

HCL2 example:

```hcl
rng0 {
source = "/dev/urandom"
max_bytes = 1024
period = 1000
}
```

JSON example:

```json
{
"rng0": {
"source": "/dev/urandom",
"max_bytes": 1024,
"period": 1000
}
}
```

<!-- End of code generated from the comments of the rng0Config struct in builder/proxmox/common/config.go; -->
12 changes: 12 additions & 0 deletions docs/builders/clone.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,18 @@ or responding to pattern `/dev/.+`. Example:

- `machine` - (string) - Set the machine type. Supported values are 'pc' or 'q35'.

#### VirtIO RNG device

@include 'builder/proxmox/common/rng0Config.mdx'

##### Required:

@include 'builder/proxmox/common/rng0Config-required.mdx'

##### Optional:

@include 'builder/proxmox/common/rng0Config-not-required.mdx'

## Example: Cloud-Init enabled Debian

Here is a basic example creating a Debian 10 server image. This assumes
Expand Down
12 changes: 12 additions & 0 deletions docs/builders/iso.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,18 @@ or responding to pattern `/dev/.+`. Example:

- `machine` - (string) - Set the machine type. Supported values are 'pc' or 'q35'.

#### VirtIO RNG device

@include 'builder/proxmox/common/rng0Config.mdx'

##### Required:

@include 'builder/proxmox/common/rng0Config-required.mdx'

##### Optional:

@include 'builder/proxmox/common/rng0Config-not-required.mdx'

## Boot Command

@include 'packer-plugin-sdk/bootcommand/BootConfig.mdx'
Expand Down

0 comments on commit 3e66773

Please sign in to comment.