packer-cn/vendor/github.com/Telmate/proxmox-api-go/proxmox/config_lxc.go

436 lines
13 KiB
Go

package proxmox
import (
"encoding/json"
"fmt"
"io"
"log"
"strconv"
"strings"
)
// 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, &paramMap)
// 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)
if len(featuresParam) > 0 {
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, &paramMap)
// 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
}