mirror of https://github.com/hashicorp/packer
commit
aa9cc919ab
@ -0,0 +1,433 @@
|
||||
package proxmox
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"strings"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// LXC options for the Proxmox API
|
||||
type configLxc struct {
|
||||
Ostemplate string `json:"ostemplate"`
|
||||
Arch string `json:"arch"`
|
||||
BWLimit int `json:"bwlimit,omitempty"`
|
||||
CMode string `json:"cmode"`
|
||||
Console bool `json:"console"`
|
||||
Cores int `json:"cores,omitempty"`
|
||||
CPULimit int `json:"cpulimit"`
|
||||
CPUUnits int `json:"cpuunits"`
|
||||
Description string `json:"description,omitempty"`
|
||||
Features QemuDevice `json:"features,omitempty"`
|
||||
Force bool `json:"force,omitempty"`
|
||||
Hookscript string `json:"hookscript,omitempty"`
|
||||
Hostname string `json:"hostname,omitempty"`
|
||||
IgnoreUnpackErrors bool `json:"ignore-unpack-errors,omitempty"`
|
||||
Lock string `json:"lock,omitempty"`
|
||||
Memory int `json:"memory"`
|
||||
Mountpoints QemuDevices `json:"mountpoints,omitempty"`
|
||||
Nameserver string `json:"nameserver,omitempty"`
|
||||
Networks QemuDevices `json:"networks,omitempty"`
|
||||
OnBoot bool `json:"onboot"`
|
||||
OsType string `json:"ostype,omitempty"`
|
||||
Password string `json:"password,omitempty"`
|
||||
Pool string `json:"pool,omitempty"`
|
||||
Protection bool `json:"protection"`
|
||||
Restore bool `json:"restore,omitempty"`
|
||||
RootFs string `json:"rootfs,omitempty"`
|
||||
SearchDomain string `json:"searchdomain,omitempty"`
|
||||
SSHPublicKeys string `json:"ssh-public-keys,omitempty"`
|
||||
Start bool `json:"start"`
|
||||
Startup string `json:"startup,omitempty"`
|
||||
Storage string `json:"storage"`
|
||||
Swap int `json:"swap"`
|
||||
Template bool `json:"template,omitempty"`
|
||||
Tty int `json:"tty"`
|
||||
Unique bool `json:"unique,omitempty"`
|
||||
Unprivileged bool `json:"unprivileged"`
|
||||
Unused []string `json:"unused,omitempty"`
|
||||
}
|
||||
|
||||
func NewConfigLxc() (configLxc) {
|
||||
return configLxc{
|
||||
Arch: "amd64",
|
||||
CMode: "tty",
|
||||
Console: true,
|
||||
CPULimit: 0,
|
||||
CPUUnits: 1024,
|
||||
Memory: 512,
|
||||
OnBoot: false,
|
||||
Protection: false,
|
||||
Start: false,
|
||||
Storage: "local",
|
||||
Swap: 512,
|
||||
Template: false,
|
||||
Tty: 2,
|
||||
Unprivileged: false,
|
||||
}
|
||||
}
|
||||
|
||||
func NewConfigLxcFromJson(io io.Reader) (config configLxc, err error) {
|
||||
config = NewConfigLxc()
|
||||
err = json.NewDecoder(io).Decode(config)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
return config, err
|
||||
}
|
||||
log.Println(config)
|
||||
return
|
||||
}
|
||||
|
||||
func NewConfigLxcFromApi(vmr *VmRef, client *Client) (config *configLxc, err error) {
|
||||
// prepare json map to receive the information from the api
|
||||
var lxcConfig map[string]interface{}
|
||||
lxcConfig, err = client.GetVmConfig(vmr)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// prepare a new lxc config to store and return\
|
||||
// the information from api
|
||||
newConfig := NewConfigLxc()
|
||||
config = &newConfig
|
||||
|
||||
arch := ""
|
||||
if _, isSet := lxcConfig["arch"]; isSet {
|
||||
arch = lxcConfig["arch"].(string)
|
||||
}
|
||||
cmode := ""
|
||||
if _, isSet := lxcConfig["cmode"]; isSet {
|
||||
cmode = lxcConfig["cmode"].(string)
|
||||
}
|
||||
console := true
|
||||
if _, isSet := lxcConfig["console"]; isSet {
|
||||
console = Itob(int(lxcConfig["console"].(float64)))
|
||||
}
|
||||
cores := 1
|
||||
if _, isSet := lxcConfig["cores"]; isSet {
|
||||
cores = int(lxcConfig["cores"].(float64))
|
||||
}
|
||||
cpulimit := 0
|
||||
if _, isSet := lxcConfig["cpulimit"]; isSet {
|
||||
cpulimit, _ = strconv.Atoi(lxcConfig["cpulimit"].(string))
|
||||
}
|
||||
cpuunits := 1024
|
||||
if _, isSet := lxcConfig["cpuunits"]; isSet {
|
||||
cpuunits = int(lxcConfig["cpuunits"].(float64))
|
||||
}
|
||||
description := ""
|
||||
if _, isSet := lxcConfig["description"]; isSet {
|
||||
description = lxcConfig["description"].(string)
|
||||
}
|
||||
|
||||
// add features, if any
|
||||
if features, isSet := lxcConfig["features"]; isSet {
|
||||
featureList := strings.Split(features.(string), ",")
|
||||
|
||||
// create new device map to store features
|
||||
featureMap := QemuDevice{}
|
||||
// add all features to device map
|
||||
featureMap.readDeviceConfig(featureList)
|
||||
// prepare empty feature map
|
||||
if config.Features == nil {
|
||||
config.Features = QemuDevice{}
|
||||
}
|
||||
// and device config to networks
|
||||
if len(featureMap) > 0 {
|
||||
config.Features = featureMap
|
||||
}
|
||||
}
|
||||
|
||||
hookscript := ""
|
||||
if _, isSet := lxcConfig["hookscript"]; isSet {
|
||||
hookscript = lxcConfig["hookscript"].(string)
|
||||
}
|
||||
hostname := ""
|
||||
if _, isSet := lxcConfig["hostname"]; isSet {
|
||||
hostname = lxcConfig["hostname"].(string)
|
||||
}
|
||||
lock := ""
|
||||
if _, isSet := lxcConfig["lock"]; isSet {
|
||||
lock = lxcConfig["lock"].(string)
|
||||
}
|
||||
memory := 512
|
||||
if _, isSet := lxcConfig["memory"]; isSet {
|
||||
memory = int(lxcConfig["memory"].(float64))
|
||||
}
|
||||
|
||||
// add mountpoints
|
||||
mpNames := []string{}
|
||||
|
||||
for k, _ := range lxcConfig {
|
||||
if mpName:= rxMpName.FindStringSubmatch(k); len(mpName) > 0 {
|
||||
mpNames = append(mpNames, mpName[0])
|
||||
}
|
||||
}
|
||||
|
||||
for _, mpName := range mpNames {
|
||||
mpConfStr := lxcConfig[mpName]
|
||||
mpConfList := strings.Split(mpConfStr.(string), ",")
|
||||
|
||||
id := rxDeviceID.FindStringSubmatch(mpName)
|
||||
mpID, _ := strconv.Atoi(id[0])
|
||||
// add mp id
|
||||
mpConfMap := QemuDevice{
|
||||
"id": mpID,
|
||||
}
|
||||
// add rest of device config
|
||||
mpConfMap.readDeviceConfig(mpConfList)
|
||||
// prepare empty mountpoint map
|
||||
if config.Mountpoints == nil {
|
||||
config.Mountpoints = QemuDevices{}
|
||||
}
|
||||
// and device config to mountpoints
|
||||
if len(mpConfMap) > 0 {
|
||||
config.Mountpoints[mpID] = mpConfMap
|
||||
}
|
||||
}
|
||||
|
||||
nameserver := ""
|
||||
if _, isSet := lxcConfig["nameserver"]; isSet {
|
||||
nameserver = lxcConfig["nameserver"].(string)
|
||||
}
|
||||
|
||||
// add networks
|
||||
nicNames := []string{}
|
||||
|
||||
for k, _ := range lxcConfig {
|
||||
if nicName := rxNicName.FindStringSubmatch(k); len(nicName) > 0 {
|
||||
nicNames = append(nicNames, nicName[0])
|
||||
}
|
||||
}
|
||||
|
||||
for _, nicName := range nicNames {
|
||||
nicConfStr := lxcConfig[nicName]
|
||||
nicConfList := strings.Split(nicConfStr.(string), ",")
|
||||
|
||||
id := rxDeviceID.FindStringSubmatch(nicName)
|
||||
nicID, _ := strconv.Atoi(id[0])
|
||||
// add nic id
|
||||
nicConfMap := QemuDevice{
|
||||
"id": nicID,
|
||||
}
|
||||
// add rest of device config
|
||||
nicConfMap.readDeviceConfig(nicConfList)
|
||||
// prepare empty network map
|
||||
if config.Networks == nil {
|
||||
config.Networks = QemuDevices{}
|
||||
}
|
||||
// and device config to networks
|
||||
if len(nicConfMap) > 0 {
|
||||
config.Networks[nicID] = nicConfMap
|
||||
}
|
||||
}
|
||||
|
||||
onboot := false
|
||||
if _, isSet := lxcConfig["onboot"]; isSet {
|
||||
onboot = Itob(int(lxcConfig["onboot"].(float64)))
|
||||
}
|
||||
ostype := ""
|
||||
if _, isSet := lxcConfig["ostype"]; isSet {
|
||||
ostype = lxcConfig["ostype"].(string)
|
||||
}
|
||||
protection := false
|
||||
if _, isSet := lxcConfig["protection"]; isSet {
|
||||
protection = Itob(int(lxcConfig["protection"].(float64)))
|
||||
}
|
||||
rootfs := ""
|
||||
if _, isSet := lxcConfig["rootfs"]; isSet {
|
||||
rootfs = lxcConfig["rootfs"].(string)
|
||||
}
|
||||
searchdomain := ""
|
||||
if _, isSet := lxcConfig["searchdomain"]; isSet {
|
||||
searchdomain = lxcConfig["searchdomain"].(string)
|
||||
}
|
||||
startup := ""
|
||||
if _, isSet := lxcConfig["startup"]; isSet {
|
||||
startup = lxcConfig["startup"].(string)
|
||||
}
|
||||
swap := 512
|
||||
if _, isSet := lxcConfig["swap"]; isSet {
|
||||
swap = int(lxcConfig["swap"].(float64))
|
||||
}
|
||||
template := false
|
||||
if _, isSet := lxcConfig["template"]; isSet {
|
||||
template = Itob(int(lxcConfig["template"].(float64)))
|
||||
}
|
||||
tty := 2
|
||||
if _, isSet := lxcConfig["tty"]; isSet {
|
||||
tty = int(lxcConfig["tty"].(float64))
|
||||
}
|
||||
unprivileged := false
|
||||
if _, isset := lxcConfig["unprivileged"]; isset {
|
||||
unprivileged = Itob(int(lxcConfig["unprivileged"].(float64)))
|
||||
}
|
||||
var unused []string
|
||||
if _, isset := lxcConfig["unused"]; isset {
|
||||
unused = lxcConfig["unused"].([]string)
|
||||
}
|
||||
|
||||
config.Arch = arch
|
||||
config.CMode = cmode
|
||||
config.Console = console
|
||||
config.Cores = cores
|
||||
config.CPULimit = cpulimit
|
||||
config.CPUUnits = cpuunits
|
||||
config.Description = description
|
||||
config.OnBoot = onboot
|
||||
config.Hookscript = hookscript
|
||||
config.Hostname = hostname
|
||||
config.Lock = lock
|
||||
config.Memory = memory
|
||||
config.Nameserver = nameserver
|
||||
config.OnBoot = onboot
|
||||
config.OsType = ostype
|
||||
config.Protection = protection
|
||||
config.RootFs = rootfs
|
||||
config.SearchDomain = searchdomain
|
||||
config.Startup = startup
|
||||
config.Swap = swap
|
||||
config.Template = template
|
||||
config.Tty = tty
|
||||
config.Unprivileged = unprivileged
|
||||
config.Unused = unused
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// create LXC container using the Proxmox API
|
||||
func (config configLxc) CreateLxc(vmr *VmRef, client *Client) (err error) {
|
||||
vmr.SetVmType("lxc")
|
||||
|
||||
// convert config to map
|
||||
params, _ := json.Marshal(&config)
|
||||
var paramMap map[string]interface{}
|
||||
json.Unmarshal(params, ¶mMap)
|
||||
|
||||
// build list of features
|
||||
// add features as parameter list to lxc parameters
|
||||
// this overwrites the orginal formatting with a
|
||||
// comma separated list of "key=value" pairs
|
||||
featuresParam := QemuDeviceParam{}
|
||||
featuresParam = featuresParam.createDeviceParam(config.Features, nil)
|
||||
paramMap["features"] = strings.Join(featuresParam, ",")
|
||||
|
||||
// build list of mountpoints
|
||||
// this does the same as for the feature list
|
||||
// except that there can be multiple of these mountpoint sets
|
||||
// and each mountpoint set comes with a new id
|
||||
for mpID, mpConfMap := range config.Mountpoints {
|
||||
mpConfParam := QemuDeviceParam{}
|
||||
mpConfParam = mpConfParam.createDeviceParam(mpConfMap, nil)
|
||||
|
||||
// add mp to lxc parameters
|
||||
mpName := fmt.Sprintf("mp%v", mpID)
|
||||
paramMap[mpName] = strings.Join(mpConfParam, ",")
|
||||
}
|
||||
|
||||
// build list of network parameters
|
||||
for nicID, nicConfMap := range config.Networks {
|
||||
nicConfParam := QemuDeviceParam{}
|
||||
nicConfParam = nicConfParam.createDeviceParam(nicConfMap, nil)
|
||||
|
||||
// add nic to lxc parameters
|
||||
nicName := fmt.Sprintf("net%v", nicID)
|
||||
paramMap[nicName] = strings.Join(nicConfParam, ",")
|
||||
}
|
||||
|
||||
// build list of unused volumes for sake of completenes,
|
||||
// even if it is not recommended to change these volumes manually
|
||||
for volID, vol := range config.Unused {
|
||||
// add volume to lxc parameters
|
||||
volName := fmt.Sprintf("unused%v", volID)
|
||||
paramMap[volName] = vol
|
||||
}
|
||||
|
||||
// now that we concatenated the key value parameter
|
||||
// list for the networks, mountpoints and unused volumes,
|
||||
// remove the original keys, since the Proxmox API does
|
||||
// not know how to handle this key
|
||||
delete(paramMap, "networks")
|
||||
delete(paramMap, "mountpoints")
|
||||
delete(paramMap, "unused")
|
||||
|
||||
// amend vmid
|
||||
paramMap["vmid"] = vmr.vmId
|
||||
|
||||
exitStatus, err := client.CreateLxcContainer(vmr.node, paramMap)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error creating LXC container: %v, error status: %s (params: %v)", err, exitStatus, params)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (config configLxc) UpdateConfig(vmr *VmRef, client *Client) (err error) {
|
||||
// convert config to map
|
||||
params, _ := json.Marshal(&config)
|
||||
var paramMap map[string]interface{}
|
||||
json.Unmarshal(params, ¶mMap)
|
||||
|
||||
// build list of features
|
||||
// add features as parameter list to lxc parameters
|
||||
// this overwrites the orginal formatting with a
|
||||
// comma separated list of "key=value" pairs
|
||||
featuresParam := QemuDeviceParam{}
|
||||
featuresParam = featuresParam.createDeviceParam(config.Features, nil)
|
||||
paramMap["features"] = strings.Join(featuresParam, ",")
|
||||
|
||||
// build list of mountpoints
|
||||
// this does the same as for the feature list
|
||||
// except that there can be multiple of these mountpoint sets
|
||||
// and each mountpoint set comes with a new id
|
||||
for mpID, mpConfMap := range config.Mountpoints {
|
||||
mpConfParam := QemuDeviceParam{}
|
||||
mpConfParam = mpConfParam.createDeviceParam(mpConfMap, nil)
|
||||
|
||||
// add mp to lxc parameters
|
||||
mpName := fmt.Sprintf("mp%v", mpID)
|
||||
paramMap[mpName] = strings.Join(mpConfParam, ",")
|
||||
}
|
||||
|
||||
// build list of network parameters
|
||||
for nicID, nicConfMap := range config.Networks {
|
||||
nicConfParam := QemuDeviceParam{}
|
||||
nicConfParam = nicConfParam.createDeviceParam(nicConfMap, nil)
|
||||
|
||||
// add nic to lxc parameters
|
||||
nicName := fmt.Sprintf("net%v", nicID)
|
||||
paramMap[nicName] = strings.Join(nicConfParam, ",")
|
||||
}
|
||||
|
||||
// build list of unused volumes for sake of completenes,
|
||||
// even if it is not recommended to change these volumes manually
|
||||
for volID, vol := range config.Unused {
|
||||
// add volume to lxc parameters
|
||||
volName := fmt.Sprintf("unused%v", volID)
|
||||
paramMap[volName] = vol
|
||||
}
|
||||
|
||||
// now that we concatenated the key value parameter
|
||||
// list for the networks, mountpoints and unused volumes,
|
||||
// remove the original keys, since the Proxmox API does
|
||||
// not know how to handle this key
|
||||
delete(paramMap, "networks")
|
||||
delete(paramMap, "mountpoints")
|
||||
delete(paramMap, "unused")
|
||||
|
||||
// delete parameters wich are not supported in updated operations
|
||||
delete(paramMap, "pool")
|
||||
delete(paramMap, "storage")
|
||||
delete(paramMap, "password")
|
||||
delete(paramMap, "ostemplate")
|
||||
delete(paramMap, "start")
|
||||
// even though it is listed as a PUT option in the API documentation
|
||||
// we remove it here because "it should not be modified manually";
|
||||
// also, error "500 unable to modify read-only option: 'unprivileged'"
|
||||
delete(paramMap, "unprivileged")
|
||||
|
||||
_, err = client.SetLxcConfig(vmr, paramMap)
|
||||
return err
|
||||
}
|
||||
Loading…
Reference in new issue