guest import from libvirt (#11)

* import servers from libvirt

* dep add libvirt-go-xml

* fix code

* fix code
This commit is contained in:
wanyaoqi
2019-04-01 23:07:41 +08:00
committed by Yousong Zhou
parent dc25febb16
commit f0810bbe88
39 changed files with 9512 additions and 214 deletions

9
Gopkg.lock generated
View File

@@ -851,6 +851,14 @@
revision = "db8e3cd836b82e82e0a9c8edc6896967dd31374f"
version = "v1.1.3"
[[projects]]
branch = "master"
digest = "1:74e674486930998805335f2b2f0af5fd3b183c755973e53f532363a56831b7a3"
name = "github.com/libvirt/libvirt-go-xml"
packages = ["."]
pruneopts = "UT"
revision = "4b6d354bfe8a0c85cebc68f0f7e45f7d5a37de7b"
[[projects]]
digest = "1:4e878df5f4e9fd625bf9c9aac77ef7cbfa4a74c01265505527c23470c0e40300"
name = "github.com/marstr/guid"
@@ -1827,6 +1835,7 @@
"github.com/json-iterator/go",
"github.com/koding/websocketproxy",
"github.com/kr/pty",
"github.com/libvirt/libvirt-go-xml",
"github.com/mholt/caddy",
"github.com/mholt/caddy/startupshutdown",
"github.com/miekg/dns",

View File

@@ -206,4 +206,7 @@
[[constraint]]
name="github.com/ceph/go-ceph"
branch = "master"
branch = "master"
[[constraint]]
branch = "master"
name = "github.com/libvirt/libvirt-go-xml"

View File

@@ -15,6 +15,7 @@
package shell
import (
"encoding/json"
"fmt"
"io/ioutil"
"os"
@@ -23,6 +24,7 @@ import (
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/mcclient/modules"
"yunion.io/x/onecloud/pkg/mcclient/options"
@@ -806,4 +808,33 @@ func init() {
}
return nil
})
type ServersImportFromLibvirtOptions struct {
CONFIG_FILE string `help:"JSON file describing servers from libvirt, e.g. {'hosts': [{'servers': [{'uuid': 'id', 'mac_ip': {'mac1': 'ip1', ...}}]]}}"`
}
R(&ServersImportFromLibvirtOptions{}, "servers-import-from-libvirt", "Import servers from libvrt", func(s *mcclient.ClientSession, args *ServersImportFromLibvirtOptions) error {
rawConfig, err := ioutil.ReadFile(args.CONFIG_FILE)
if err != nil {
return fmt.Errorf("Read file error: %s", err)
}
config := &compute.SLibvirtImportConfig{}
err = json.Unmarshal(rawConfig, config)
if err != nil {
return fmt.Errorf("Parse config error %s", err)
}
params, err := jsonutils.Marshal(config.Hosts).GetArray()
if err != nil {
return err
}
for i := 0; i < len(params); i++ {
val := jsonutils.NewDict()
val.Set(modules.Servers.KeywordPlural, params[i])
params[i] = val
}
results := modules.Servers.BatchPerformClassAction(s, "import-from-libvirt", params)
printBatchResults(results, modules.Servers.GetColumns(s))
return nil
})
}

View File

@@ -104,6 +104,9 @@ const (
VM_ADMIN = "admin"
VM_IMPORT = "import"
VM_IMPORT_FAILED = "import_fail"
SHUTDOWN_STOP = "stop"
SHUTDOWN_TERMINATE = "terminate"

View File

@@ -0,0 +1,71 @@
package compute
type SImportNic struct {
Index int `json:"index"`
Bridge string `json:"bridge"`
Domain string `json:"domain"`
Ip string `json:"ip"`
Vlan int `json:"vlan"`
Driver string `json:"driver"`
Masklen int `json:"masklen"`
Virtual bool `json:"virtual"`
Manual bool `json:"manual"`
WireId string `json:"wire_id"`
NetId string `json:"net_id"`
Mac string `json:"mac"`
BandWidth int `json:"bw"`
Dns string `json:"dns"`
Net string `json:"net"`
Interface string `json:"interface"`
Gateway string `json:"gateway"`
Ifname string `json:"ifname"`
}
type SImportDisk struct {
Index int `json:"index"`
DiskId string `json:"disk_id"`
Driver string `json:"driver"`
CacheMode string `json:"cache_mode"`
AioMode string `json:"aio_mode"`
SizeMb int `json:"size"`
Format string `json:"format"`
Fs string `json:"fs"`
Mountpoint string `json:"mountpoint"`
Dev string `json:"dev"`
TemplateId string `json:"template_id"`
AccessPath string `json:"AccessPath"`
Backend string `json:"Backend"`
}
type SImportGuestDesc struct {
Id string `json:"uuid"`
Name string `json:"name"`
Nics []SImportNic `json:"nics"`
Disks []SImportDisk `json:"disks"`
Metadata map[string]string `json:"metadata"`
MemSizeMb int `json:"mem"`
Cpu int `json:"cpu"`
TemplateId string `json:"template_id"`
ImagePath string `json:"image_path"`
Vdi string `json:"vdi"`
Hypervisor string `json:"hypervisor"`
HostId string `json:"host"`
BootOrder string `json:"boot_order"`
IsSystem bool `json:"is_system"`
Description string `json:"description"`
}
type SLibvirtServerConfig struct {
Uuid string `json:"uuid"`
MacIp map[string]string `json:"mac_ip"`
}
type SLibvirtHostConfig struct {
Servers []SLibvirtServerConfig `json:"servers"`
XmlFilePath string `json:"xml_file_path"`
HostIp string `json:"host_ip"`
}
type SLibvirtImportConfig struct {
Hosts []SLibvirtHostConfig `json:"hosts"`
}

View File

@@ -188,6 +188,11 @@ const (
ACT_RECYCLE_PREPAID = "recycle_prepaid"
ACT_UNDO_RECYCLE_PREPAID = "undo_recycle_prepaid"
ACT_HOST_IMPORT_LIBVIRT_SERVERS = "host_import_libvirt_servers"
ACT_HOST_IMPORT_LIBVIRT_SERVERS_FAIL = "host_import_libvirt_servers_fail"
ACT_GUEST_CREATE_FROM_IMPORT_SUCC = "guest_create_from_import_succ"
ACT_GUEST_CREATE_FROM_IMPORT_FAIL = "guest_create_from_import_fail"
)
type SOpsLogManager struct {

View File

@@ -2781,91 +2781,9 @@ func (man *SGuestManager) AllowPerformImport(ctx context.Context, userCred mccli
return db.IsAdminAllowClassPerform(userCred, man, "import")
}
type SImportNic struct {
Index int `json:"index"`
Bridge string `json:"bridge"`
Domain string `json:"domain"`
Ip string `json:"ip"`
Vlan int `json:"vlan"`
Driver string `json:"driver"`
Masklen int `json:"masklen"`
Virtual bool `json:"virtual"`
Manual bool `json:"manual"`
WireId string `json:"wire_id"`
NetId string `json:"net_id"`
Mac string `json:"mac"`
BandWidth int `json:"bw"`
Dns string `json:"dns"`
Net string `json:"net"`
Interface string `json:"interface"`
Gateway string `json:"gateway"`
Ifname string `json:"ifname"`
}
func (n SImportNic) ToNetConfig(net *SNetwork) *api.NetworkConfig {
return &api.NetworkConfig{
Network: net.Id,
Wire: net.WireId,
Address: n.Ip,
Mac: n.Mac,
Driver: n.Driver,
BwLimit: n.BandWidth,
}
}
type SImportDisk struct {
Index int `json:"index"`
DiskId string `json:"disk_id"`
Driver string `json:"driver"`
CacheMode string `json:"cache_mode"`
AioMode string `json:"aio_mode"`
SizeMb int `json:"size"`
Format string `json:"format"`
Fs string `json:"fs"`
Mountpoint string `json:"mountpoint"`
Dev string `json:"dev"`
TemplateId string `json:"template_id"`
}
func (d SImportDisk) ToDiskConfig() *api.DiskConfig {
ret := &api.DiskConfig{
SizeMb: d.SizeMb,
ImageId: d.TemplateId,
Format: d.Format,
Driver: d.Driver,
DiskId: d.DiskId,
Cache: d.CacheMode,
}
if len(d.Mountpoint) > 0 {
ret.Mountpoint = d.Mountpoint
}
if len(d.Fs) > 0 {
ret.Fs = d.Fs
}
return ret
}
type SImportGuestDesc struct {
Id string `json:"uuid"`
Name string `json:"name"`
Nics []SImportNic `json:"nics"`
Disks []SImportDisk `json:"disks"`
Metadata map[string]string `json:"metadata"`
MemSizeMb int `json:"mem"`
Cpu int `json:"cpu"`
TemplateId string `json:"template_id"`
ImagePath string `json:"image_path"`
Vdi string `json:"vdi"`
Hypervisor string `json:"hypervisor"`
HostId string `json:"host"`
BootOrder string `json:"boot_order"`
IsSystem bool `json:"is_system"`
Description string `json:"description"`
}
func (man *SGuestManager) PerformImport(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
desc := SImportGuestDesc{}
if err := data.Unmarshal(&desc); err != nil {
desc := &api.SImportGuestDesc{}
if err := data.Unmarshal(desc); err != nil {
return nil, httperrors.NewInputParameterError("Invalid desc: %s", data.String())
}
if len(desc.Id) == 0 {
@@ -2885,6 +2803,16 @@ func (man *SGuestManager) PerformImport(ctx context.Context, userCred mcclient.T
} else {
desc.HostId = hostObj.GetId()
}
guset, err := man.DoImport(ctx, userCred, desc)
if err != nil {
return nil, err
}
return jsonutils.Marshal(guset), nil
}
func (man *SGuestManager) DoImport(
ctx context.Context, userCred mcclient.TokenCredential, desc *api.SImportGuestDesc,
) (*SGuest, error) {
// 1. create import guest on host
gst, err := man.createImportGuest(ctx, userCred, desc)
if err != nil {
@@ -2902,10 +2830,10 @@ func (man *SGuestManager) PerformImport(ctx context.Context, userCred mcclient.T
for k, v := range desc.Metadata {
gst.SetMetadata(ctx, k, v, userCred)
}
return jsonutils.Marshal(gst), nil
return gst, nil
}
func (man *SGuestManager) createImportGuest(ctx context.Context, userCred mcclient.TokenCredential, desc SImportGuestDesc) (*SGuest, error) {
func (man *SGuestManager) createImportGuest(ctx context.Context, userCred mcclient.TokenCredential, desc *api.SImportGuestDesc) (*SGuest, error) {
model, err := db.NewModelObject(man)
if err != nil {
return nil, httperrors.NewGeneralError(err)
@@ -2919,7 +2847,7 @@ func (man *SGuestManager) createImportGuest(ctx context.Context, userCred mcclie
gst.Id = desc.Id
gst.Name = desc.Name
gst.HostId = desc.HostId
gst.Status = "import"
gst.Status = api.VM_IMPORT
gst.Hypervisor = desc.Hypervisor
gst.VmemSize = desc.MemSizeMb
gst.VcpuCount = int8(desc.Cpu)
@@ -2929,7 +2857,18 @@ func (man *SGuestManager) createImportGuest(ctx context.Context, userCred mcclie
return gst, err
}
func (self *SGuest) importNics(ctx context.Context, userCred mcclient.TokenCredential, nics []SImportNic) error {
func ToNetConfig(n *api.SImportNic, net *SNetwork) *api.NetworkConfig {
return &api.NetworkConfig{
Network: net.Id,
Wire: net.WireId,
Address: n.Ip,
Mac: n.Mac,
Driver: n.Driver,
BwLimit: n.BandWidth,
}
}
func (self *SGuest) importNics(ctx context.Context, userCred mcclient.TokenCredential, nics []api.SImportNic) error {
if len(nics) == 0 {
return httperrors.NewInputParameterError("Empty import nics")
}
@@ -2938,7 +2877,7 @@ func (self *SGuest) importNics(ctx context.Context, userCred mcclient.TokenCrede
if err != nil {
return httperrors.NewNotFoundError("Not found network by ip %s", nic.Ip)
}
_, err = self.attach2NetworkDesc(ctx, userCred, self.GetHost(), nic.ToNetConfig(net), nil)
_, err = self.attach2NetworkDesc(ctx, userCred, self.GetHost(), ToNetConfig(&nic, net), nil)
if err != nil {
return err
}
@@ -2946,12 +2885,31 @@ func (self *SGuest) importNics(ctx context.Context, userCred mcclient.TokenCrede
return nil
}
func (self *SGuest) importDisks(ctx context.Context, userCred mcclient.TokenCredential, disks []SImportDisk) error {
func ToDiskConfig(d *api.SImportDisk) *api.DiskConfig {
ret := &api.DiskConfig{
SizeMb: d.SizeMb,
ImageId: d.TemplateId,
Format: d.Format,
Driver: d.Driver,
DiskId: d.DiskId,
Cache: d.CacheMode,
Backend: d.Backend,
}
if len(d.Mountpoint) > 0 {
ret.Mountpoint = d.Mountpoint
}
if len(d.Fs) > 0 {
ret.Fs = d.Fs
}
return ret
}
func (self *SGuest) importDisks(ctx context.Context, userCred mcclient.TokenCredential, disks []api.SImportDisk) error {
if len(disks) == 0 {
return httperrors.NewInputParameterError("Empty import disks")
}
for _, disk := range disks {
disk, err := self.createDiskOnHost(ctx, userCred, self.GetHost(), disk.ToDiskConfig(), nil, true, true, nil)
disk, err := self.createDiskOnHost(ctx, userCred, self.GetHost(), ToDiskConfig(&disk), nil, true, true, nil)
if err != nil {
return err
}
@@ -2959,3 +2917,35 @@ func (self *SGuest) importDisks(ctx context.Context, userCred mcclient.TokenCred
}
return nil
}
func (manager *SGuestManager) AllowPerformImportFromLibvirt(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
return db.IsAdminAllowClassPerform(userCred, manager, "import-from-libvirt")
}
func (manager *SGuestManager) PerformImportFromLibvirt(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
host := &api.SLibvirtHostConfig{}
if err := data.Unmarshal(host); err != nil {
return nil, httperrors.NewInputParameterError("Unmarshal data error %s", err)
}
if len(host.XmlFilePath) == 0 {
return nil, httperrors.NewInputParameterError("Some host config missing xml_file_path")
}
if len(host.HostIp) == 0 {
return nil, httperrors.NewInputParameterError("Some host config missing host ip")
}
sHost, err := HostManager.GetHostByIp(host.HostIp)
if err != nil {
return nil, httperrors.NewInputParameterError("Invalid host ip %s", host.HostIp)
}
taskData := jsonutils.NewDict()
taskData.Set("xml_file_path", jsonutils.NewString(host.XmlFilePath))
taskData.Set("servers", jsonutils.Marshal(host.Servers))
task, err := taskman.TaskManager.NewTask(ctx, "HostImportLibvirtServersTask", sHost, userCred,
taskData, "", "", nil)
if err != nil {
return nil, httperrors.NewInternalServerError("NewTask error: %s", err)
}
task.ScheduleRun(nil)
return nil, nil
}

View File

@@ -2647,7 +2647,7 @@ func (self *SGuest) createDiskOnStorage(ctx context.Context, userCred mcclient.T
}
func (self *SGuest) ChooseHostStorage(host *SHost, backend string, candidate *schedapi.CandidateDisk) *SStorage {
log.Errorf("==========candidate %#v", candidate)
log.Infof("==========candidate %#v", candidate)
if candidate == nil {
return self.GetDriver().ChooseHostStorage(host, backend)
}

View File

@@ -223,100 +223,6 @@ func (zone *SZone) getNetworkCount() int {
return getNetworkCount(nil, zone)
}
/*def host_count(self, status=None, host_status=None, enabled=None, host_type=None, is_baremetal=None):
from hosts import Hosts
q = Hosts.query().filter(Hosts.zone_id==self.id)
if status is not None:
q = q.filter(Hosts.status==status)
if host_status is not None:
q = q.filter(Hosts.host_status==host_status)
if enabled is not None:
q = q.filter(Hosts.enabled==enabled)
if host_type is not None:
q = q.filter(Hosts.host_type==host_type)
if is_baremetal is not None:
q = q.filter(Hosts.is_baremetal==is_baremetal)
return q.count()
def wire_count(self):
from wires import Wires
q = Wires.query().filter(Wires.zone_id==self.id)
return q.count()
*/
/*
@classmethod
def get_resident_zones_of_tenant(cls, tenant_id):
from guests import Guests
from hosts import Hosts
q = Zones.query(Zones.id, func.count('*')) \
.join(Hosts, and_(Hosts.zone_id==Zones.id,
Hosts.deleted==False,
Hosts.enabled==True,
Hosts.host_status==Hosts.HOST_ONLINE)) \
.join(Guests, and_(Guests.host_id==Hosts.id,
Guests.deleted==False)) \
.filter(Guests.tenant_id==tenant_id) \
.group_by(Zones.id)
ret = []
for (zone_id, guest_cnt) in q.all():
ret.append((Zones.fetch(zone_id), guest_cnt))
return ret
@classmethod
def get_default_schedule_zone_of_tenant(cls, user_cred, tenant_id, params,
count=1):
from guests import Guests
zones = cls.get_resident_zones_of_tenant(tenant_id)
if len(zones) == 0:
if options.default_zone is not None:
zone = Zones.fetch(options.default_zone)
ret = Guests.check_resource_limit(user_cred, params, count,
range_obj=zone)
if len(ret) > 0:
logging.error('Default zone out of resources')
return None
else:
return zone
else:
sel_z = None
max_cnt = 0
for (z, gcnt) in zones:
ret = Guests.check_resource_limit(user_cred, params, count,
range_obj=z)
if len(ret) == 0:
if max_cnt < gcnt:
sel_z = z
max_cnt = gcnt
return sel_z
def get_wires(self):
from wires import Wires
q = Wires.query().filter(Wires.zone_id==self.id)
return q.all()
def get_name_cn(self):
return self.name_cn or self.name
def get_more_details(self):
ret = {}
ret.update(self.general_usage(None))
return ret
def get_customize_columns(self, user_cred, kwargs):
ret = super(Zones, self).get_customize_columns(user_cred, kwargs)
ret.update(self.get_more_details())
return ret
def get_details(self, user_cred, kwargs):
ret = super(Zones, self).get_details(user_cred, kwargs)
ret.update(self.get_more_details())
return ret
*/
func zoneExtra(zone *SZone, extra *jsonutils.JSONDict) *jsonutils.JSONDict {
usage := zone.GeneralUsage()
extra.Update(jsonutils.Marshal(usage))

View File

@@ -0,0 +1,222 @@
package tasks
import (
"context"
"fmt"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/pkg/util/stringutils"
"yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
"yunion.io/x/onecloud/pkg/compute/models"
"yunion.io/x/onecloud/pkg/util/logclient"
)
func init() {
taskman.RegisterTask(HostImportLibvirtServersTask{})
taskman.RegisterTask(CreateImportedLibvirtGuestTask{})
}
type HostImportLibvirtServersTask struct {
taskman.STask
}
func (self *HostImportLibvirtServersTask) OnInit(
ctx context.Context, obj db.IStandaloneModel, body jsonutils.JSONObject,
) {
host := obj.(*models.SHost)
self.SetStage("OnRequestHostPrepareImport", nil)
self.RequestHostPrepareImport(ctx, host)
}
func (self *HostImportLibvirtServersTask) RequestHostPrepareImport(
ctx context.Context, host *models.SHost,
) {
header := self.GetTaskRequestHeader()
if _, err := host.Request(ctx, self.UserCred, "POST",
"/servers/prepare-import-from-libvirt", header, self.Params); err != nil {
self.TaskFailed(ctx, host, err.Error())
}
}
func (self *HostImportLibvirtServersTask) OnRequestHostPrepareImport(
ctx context.Context, host *models.SHost, body jsonutils.JSONObject,
) {
serversNotMatch, _ := body.GetArray("servers_not_match")
if len(serversNotMatch) > 0 {
db.OpsLog.LogEvent(host, db.ACT_HOST_IMPORT_LIBVIRT_SERVERS,
fmt.Sprintf("Servers %s not match host xml description", serversNotMatch), self.UserCred)
logclient.AddActionLogWithContext(ctx, host, logclient.ACT_HOST_IMPORT_LIBVIRT_SERVERS,
fmt.Sprintf("Servers %s not match host xml description", serversNotMatch), self.UserCred, false)
}
serversMatched, _ := body.Get("servers_matched")
if serversMatched == nil {
self.TaskFailed(ctx, host, "No matched server found")
return
}
guestsDesc := []compute.SImportGuestDesc{}
if err := serversMatched.Unmarshal(&guestsDesc); err != nil {
self.TaskFailed(ctx, host, fmt.Sprintf("Unmarshal matched servers failed: %s", err))
return
}
self.StartImportServers(ctx, host, guestsDesc)
}
func (self *HostImportLibvirtServersTask) StartImportServers(
ctx context.Context, host *models.SHost, guestsDesc []compute.SImportGuestDesc,
) {
var (
note string
success bool
)
for i := 0; i < len(guestsDesc); i++ {
self.FillLibvirtGuestDesc(ctx, host, &guestsDesc[i])
guest, err := models.GuestManager.DoImport(ctx, self.UserCred, &guestsDesc[i])
if err != nil {
note = fmt.Sprintf("Guest %s import failed: %s", guestsDesc[i].Id, err)
success = false
goto end
}
if err := self.CreateImportedLibvirtGuestOnHost(ctx, host, guest, &guestsDesc[i]); err != nil {
note = fmt.Sprintf("Guest %s create on host failed: %s", guestsDesc[i].Id, err)
success = false
goto end
}
note = fmt.Sprintf("Guest %s import success, started create on host", guestsDesc[i].Id)
success = true
end:
if success {
db.OpsLog.LogEvent(host, db.ACT_HOST_IMPORT_LIBVIRT_SERVERS, note, self.UserCred)
} else {
log.Errorln(note)
db.OpsLog.LogEvent(host, db.ACT_HOST_IMPORT_LIBVIRT_SERVERS_FAIL, note, self.UserCred)
}
logclient.AddActionLogWithContext(ctx, host,
logclient.ACT_HOST_IMPORT_LIBVIRT_SERVERS, note, self.UserCred, success)
}
self.SetStageComplete(ctx, nil)
}
func (self *HostImportLibvirtServersTask) FillLibvirtGuestDesc(
ctx context.Context, host *models.SHost, guestDesc *compute.SImportGuestDesc,
) {
// Generate new uuid for guest to prevent duplicate
guestDesc.Id = stringutils.UUID4()
guestDesc.HostId = host.Id
g, _ := models.GuestManager.FetchByName(self.UserCred, guestDesc.Name)
if g != nil {
guestDesc.Name = db.GenerateName(models.GuestManager, self.UserCred.GetProjectId(), guestDesc.Name)
}
for i := 0; i < len(guestDesc.Disks); i++ {
guestDesc.Disks[i].DiskId = stringutils.UUID4()
if len(guestDesc.Disks[i].Backend) == 0 {
guestDesc.Disks[i].Backend = models.STORAGE_LOCAL
}
}
}
// Create sub task to create guest on host, and feedback disk real access path
func (self *HostImportLibvirtServersTask) CreateImportedLibvirtGuestOnHost(
ctx context.Context, host *models.SHost, guest *models.SGuest, guestDesc *compute.SImportGuestDesc,
) error {
task, err := taskman.TaskManager.NewTask(
ctx, "CreateImportedLibvirtGuestTask", guest, self.UserCred, nil, "", "", nil)
if err != nil {
return err
}
disksPath := jsonutils.NewDict()
for _, disk := range guestDesc.Disks {
disksPath.Set(disk.DiskId, jsonutils.NewString(disk.AccessPath))
}
body := jsonutils.NewDict()
body.Set("desc", guest.GetJsonDescAtHypervisor(ctx, host))
body.Set("disks_path", disksPath)
_, err = host.Request(ctx, self.UserCred, "POST",
fmt.Sprintf("/servers/%s/create-from-libvirt", guest.Id),
task.GetTaskRequestHeader(), body)
return err
}
func (self *HostImportLibvirtServersTask) TaskFailed(
ctx context.Context, host *models.SHost, reason string,
) {
self.SetStageFailed(ctx, reason)
db.OpsLog.LogEvent(host, db.ACT_HOST_IMPORT_LIBVIRT_SERVERS_FAIL, reason, self.UserCred)
logclient.AddActionLogWithContext(ctx, host,
logclient.ACT_HOST_IMPORT_LIBVIRT_SERVERS, reason, self.UserCred, false)
}
type CreateImportedLibvirtGuestTask struct {
taskman.STask
}
func (self *CreateImportedLibvirtGuestTask) OnInit(
ctx context.Context, obj db.IStandaloneModel, body jsonutils.JSONObject,
) {
guest := obj.(*models.SGuest)
disksPath, err := body.GetMap("disks_path")
if err != nil {
self.TaskFailed(ctx, guest, "guest create on host no disk access path feedback")
}
guestDisks := guest.GetDisks()
for i := 0; i < len(guestDisks); i++ {
disk := guestDisks[i].GetDisk()
if accessPath, ok := disksPath[disk.Id]; !ok {
self.TaskFailed(ctx, guest, fmt.Sprintf("Guest missing disk %s access path", disk.Id))
return
} else {
_, err := db.Update(disk, func() error {
disk.AccessPath = accessPath.String()
if guestDisks[i].Index == 0 {
disk.DiskType = models.DISK_TYPE_SYS
}
return nil
})
if err != nil {
self.TaskFailed(ctx, guest, fmt.Sprintf("Guest set disk access path error %s", err))
return
}
}
}
self.SetStage("OnGuestSync", nil)
guest.StartSyncTask(ctx, self.UserCred, false, self.GetTaskId())
}
func (self *CreateImportedLibvirtGuestTask) OnGuestSync(
ctx context.Context, guest *models.SGuest, body jsonutils.JSONObject,
) {
db.OpsLog.LogEvent(guest, db.ACT_GUEST_CREATE_FROM_IMPORT_SUCC, "", self.UserCred)
logclient.AddActionLogWithContext(ctx, guest,
logclient.ACT_GUEST_CREATE_FROM_IMPORT, "", self.UserCred, true)
self.SetStageComplete(ctx, nil)
}
func (self *CreateImportedLibvirtGuestTask) OnGuestSyncFailed(
ctx context.Context, guest *models.SGuest, body jsonutils.JSONObject,
) {
self.TaskFailed(ctx, guest, body.String())
}
func (self *CreateImportedLibvirtGuestTask) OnInitFailed(
ctx context.Context, guest *models.SGuest, body jsonutils.JSONObject,
) {
self.TaskFailed(ctx, guest, body.String())
}
func (self *CreateImportedLibvirtGuestTask) TaskFailed(
ctx context.Context, guest *models.SGuest, reason string,
) {
guest.SetStatus(self.UserCred, compute.VM_IMPORT_FAILED, reason)
db.OpsLog.LogEvent(guest, db.ACT_GUEST_CREATE_FROM_IMPORT_FAIL, reason, self.UserCred)
logclient.AddActionLogWithContext(ctx, guest,
logclient.ACT_GUEST_CREATE_FROM_IMPORT, reason, self.UserCred, false)
self.SetStageFailed(ctx, reason)
}

View File

@@ -23,12 +23,14 @@ import (
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/appsrv"
"yunion.io/x/onecloud/pkg/hostman/guestman"
"yunion.io/x/onecloud/pkg/hostman/hostutils"
"yunion.io/x/onecloud/pkg/hostman/storageman"
"yunion.io/x/onecloud/pkg/httperrors"
"yunion.io/x/onecloud/pkg/mcclient/auth"
"yunion.io/x/onecloud/pkg/util/fileutils2"
)
type strDict map[string]string
@@ -56,8 +58,9 @@ var (
"live-migrate": guestLiveMigrate,
"resume": guestResume,
// "start-nbd-server": guestStartNbdServer,
"drive-mirror": guestDriveMirror,
"hotplug-cpu-mem": guestHotplugCpuMem,
"drive-mirror": guestDriveMirror,
"hotplug-cpu-mem": guestHotplugCpuMem,
"create-from-libvirt": guestCreateFromLibvirt,
}
)
@@ -71,6 +74,10 @@ func AddGuestTaskHandler(prefix string, app *appsrv.Application) {
fmt.Sprintf("%s/%s/cpu-node-balance", prefix, keyWord),
auth.Authenticate(cpusetBalance))
app.AddHandler("POST",
fmt.Sprintf("%s/%s/prepare-import-from-libvirt", prefix, keyWord),
auth.Authenticate(guestPrepareImportFormLibvirt))
app.AddHandler("POST",
fmt.Sprintf("%s/%s/<sid>/<action>", prefix, keyWord),
auth.Authenticate(guestActions))
@@ -114,6 +121,33 @@ func cpusetBalance(ctx context.Context, w http.ResponseWriter, r *http.Request)
hostutils.ResponseOk(ctx, w)
}
func guestPrepareImportFormLibvirt(ctx context.Context, w http.ResponseWriter, r *http.Request) {
_, _, body := appsrv.FetchEnv(ctx, w, r)
config := &compute.SLibvirtHostConfig{}
err := body.Unmarshal(config)
if err != nil {
hostutils.Response(ctx, w, httperrors.NewInputParameterError("Parse params to libvirt config error %s", err))
return
}
if len(config.XmlFilePath) == 0 {
hostutils.Response(ctx, w, httperrors.NewMissingParameterError("xml_file_path"))
return
}
if !fileutils2.Exists(config.XmlFilePath) {
hostutils.Response(ctx, w,
httperrors.NewBadRequestError("xml_file_path %s not found", config.XmlFilePath))
return
}
if len(config.Servers) == 0 {
hostutils.Response(ctx, w, httperrors.NewMissingParameterError("servers"))
return
}
hostutils.DelayTask(ctx, guestman.GetGuestManager().PrepareImportFromLibvirt, config)
hostutils.ResponseOk(ctx, w)
}
func deleteGuest(ctx context.Context, w http.ResponseWriter, r *http.Request) {
params, _, body := appsrv.FetchEnv(ctx, w, r)
var sid = params["<sid>"]
@@ -351,6 +385,35 @@ func guestHotplugCpuMem(ctx context.Context, sid string, body jsonutils.JSONObje
return nil, nil
}
func guestCreateFromLibvirt(ctx context.Context, sid string, body jsonutils.JSONObject) (interface{}, error) {
err := guestman.GetGuestManager().PrepareCreate(sid)
if err != nil {
return nil, err
}
iGuestDesc, err := body.Get("desc")
if err != nil {
return nil, httperrors.NewMissingParameterError("desc")
}
guestDesc, ok := iGuestDesc.(*jsonutils.JSONDict)
if !ok {
return nil, httperrors.NewInputParameterError("desc is not dict")
}
iDisksPath, err := body.Get("disks_path")
if err != nil {
return nil, httperrors.NewMissingParameterError("disks_path")
}
disksPath, ok := iDisksPath.(*jsonutils.JSONDict)
if !ok {
return nil, httperrors.NewInputParameterError("disks_path is not dict")
}
hostutils.DelayTask(ctx, guestman.GetGuestManager().GuestCreateFromLibvirt,
&guestman.SGuestCreateFromLibvirt{sid, guestDesc, disksPath})
return nil, nil
}
func guestReloadDiskSnapshot(ctx context.Context, sid string, body jsonutils.JSONObject) (interface{}, error) {
if !guestman.GetGuestManager().IsGuestExist(sid) {
return nil, httperrors.NewNotFoundError("Guest %s not found", sid)

View File

@@ -87,3 +87,19 @@ type SDeleteDiskSnapshot struct {
ConvertSnapshot string
PendingDelete bool
}
type SLibvirtServer struct {
Uuid string
MacIp map[string]string
}
type SLibvirtDomainImportConfig struct {
LibvritDomainXmlDir string
Servers []SLibvirtServer
}
type SGuestCreateFromLibvirt struct {
Sid string
GuestDesc *jsonutils.JSONDict
DisksPath *jsonutils.JSONDict
}

View File

@@ -0,0 +1,263 @@
package guestman
import (
"context"
"fmt"
"io/ioutil"
"path"
"unicode"
libvirtxml "github.com/libvirt/libvirt-go-xml"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/hostman/hostutils"
"yunion.io/x/onecloud/pkg/hostman/storageman"
"yunion.io/x/onecloud/pkg/util/procutils"
"yunion.io/x/onecloud/pkg/util/qemuimg"
)
func (m *SGuestManager) GuestCreateFromLibvirt(
ctx context.Context, params interface{},
) (jsonutils.JSONObject, error) {
createConfig, ok := params.(*SGuestCreateFromLibvirt)
if !ok {
return nil, hostutils.ParamsError
}
disks, err := createConfig.GuestDesc.GetArray("disks")
if err != nil {
return nil, err
}
disksPath := jsonutils.NewDict()
for _, disk := range disks {
diskId, _ := disk.GetString("disk_id")
diskPath, err := createConfig.DisksPath.GetString(diskId)
if err != nil {
return nil, fmt.Errorf("Disks path missing disk %s", diskId)
}
storageId, _ := disk.GetString("storage_id")
storage := storageman.GetManager().GetStorage(storageId)
if storage == nil {
return nil, fmt.Errorf("Host has no stroage %s", storageId)
}
iDisk := storage.CreateDisk(diskId)
output, err := procutils.NewCommand("mv", diskPath, iDisk.GetPath()).Run()
if err != nil {
return nil, fmt.Errorf("Mv disk from %s to %s error %s", diskPath, iDisk.GetPath(), output)
}
disksPath.Set(diskId, jsonutils.NewString(iDisk.GetPath()))
}
guest := m.Servers[createConfig.Sid]
if err = guest.SaveDesc(createConfig.GuestDesc); err != nil {
return nil, err
}
ret := jsonutils.NewDict()
ret.Set("disks_path", disksPath)
return ret, nil
}
func (m *SGuestManager) PrepareImportFromLibvirt(
ctx context.Context, params interface{},
) (jsonutils.JSONObject, error) {
libvirtConfig, ok := params.(*compute.SLibvirtHostConfig)
if !ok {
return nil, hostutils.ParamsError
}
guestDescs, err := m.GenerateDescFromXml(libvirtConfig)
if err != nil {
return nil, err
}
return guestDescs, nil
}
func setAttributeFromLibvirtConfig(guestConfig *compute.SImportGuestDesc, libvirtConfig *compute.SLibvirtHostConfig) error {
for _, server := range libvirtConfig.Servers {
if server.Uuid != guestConfig.Id {
continue
}
for idx, nic := range guestConfig.Nics {
if ip, ok := server.MacIp[nic.Mac]; ok {
guestConfig.Nics[idx].Ip = ip
} else {
log.Errorf("Guest %s can't find mac address %s in import config", server.Uuid, nic.Mac)
return fmt.Errorf("Guest %s Mac Address %s Not Found", server.Uuid, nic.Mac)
}
}
log.Infof("Import guest %s ", server.Uuid)
return nil
}
return fmt.Errorf("No guest %s found in import config", guestConfig.Id)
}
func (m *SGuestManager) GenerateDescFromXml(libvirtConfig *compute.SLibvirtHostConfig) (jsonutils.JSONObject, error) {
xmlFiles, err := ioutil.ReadDir(libvirtConfig.XmlFilePath)
if err != nil {
log.Errorf("Read dir %s error: %s", libvirtConfig.XmlFilePath, err)
return nil, err
}
libvirtServers := []*compute.SImportGuestDesc{}
for _, f := range xmlFiles {
if !f.Mode().IsRegular() {
continue
}
xmlContent, err := ioutil.ReadFile(path.Join(libvirtConfig.XmlFilePath, f.Name()))
if err != nil {
log.Errorf("Read file %s error: %s", f.Name(), err)
continue
}
domain := &libvirtxml.Domain{}
err = domain.Unmarshal(string(xmlContent))
if err != nil {
log.Errorf("Unmarshal xml file %s error %s", f.Name(), err)
continue
}
guestConfig, err := m.LibvirtDomainToGuestDesc(domain)
if err != nil {
log.Errorf("Parse libvirt domain failed %s", err)
continue
}
if err = setAttributeFromLibvirtConfig(guestConfig, libvirtConfig); err != nil {
log.Errorf("Import guest %s error %s", guestConfig.Id, err)
continue
}
libvirtServers = append(libvirtServers, guestConfig)
}
var (
serverInImports = func(uuid string) bool {
for _, s := range libvirtServers {
if s.Id == uuid {
return true
}
}
return false
}
serversNotMatch = []string{}
)
for _, server := range libvirtConfig.Servers {
if !serverInImports(server.Uuid) {
serversNotMatch = append(serversNotMatch, server.Uuid)
}
}
ret := jsonutils.NewDict()
ret.Set("servers_not_match", jsonutils.NewStringArray(serversNotMatch))
ret.Set("servers_matched", jsonutils.Marshal(libvirtServers))
return ret, nil
}
// Read key infomation from domain xml
func (m *SGuestManager) LibvirtDomainToGuestDesc(domain *libvirtxml.Domain) (*compute.SImportGuestDesc, error) {
if nil == domain {
return nil, fmt.Errorf("Libvirt domain is nil")
}
if nil == domain.VCPU {
return nil, fmt.Errorf("Libvirt domain missing VCPU config")
}
if nil == domain.CurrentMemory {
return nil, fmt.Errorf("Libvirt domain missing CurrentMemory config")
}
if 0 == len(domain.CurrentMemory.Unit) {
return nil, fmt.Errorf("Libvirt Memory config missing unit")
}
if nil == domain.Devices {
return nil, fmt.Errorf("Libvirt domain missing Devices config")
}
if 0 == len(domain.Devices.Disks) {
return nil, fmt.Errorf("Livbirt domain has no Disks")
}
if 0 == len(domain.Devices.Interfaces) {
return nil, fmt.Errorf("Libvirt domain has no network Interfaces")
}
var memSizeMb uint
switch unicode.ToLower(rune(domain.CurrentMemory.Unit[0])) {
case 'k':
memSizeMb = domain.CurrentMemory.Value / 1024
if domain.CurrentMemory.Value%1024 > 0 {
memSizeMb += 1
}
case 'm':
memSizeMb = domain.CurrentMemory.Value
case 'g':
memSizeMb = domain.CurrentMemory.Value * 1024
case 'b':
memSizeMb = domain.CurrentMemory.Value / 1024 / 1024
if domain.CurrentMemory.Value%(1024*1024) > 0 {
memSizeMb += 1
}
default:
return nil, fmt.Errorf("Unknown memory unit %s", domain.CurrentMemory.Unit)
}
disksConfig, err := m.LibvirtDomainDiskToDiskConfig(domain.Devices.Disks)
if err != nil {
return nil, err
}
nicsConfig, err := m.LibvirtDomainInterfaceToNicConfig(domain.Devices.Interfaces)
if err != nil {
return nil, err
}
return &compute.SImportGuestDesc{
Id: domain.UUID,
Name: domain.Name,
Cpu: domain.VCPU.Value,
MemSizeMb: int(memSizeMb),
Disks: disksConfig,
Nics: nicsConfig,
}, nil
}
func (m *SGuestManager) LibvirtDomainDiskToDiskConfig(
domainDisks []libvirtxml.DomainDisk) ([]compute.SImportDisk, error) {
var diskConfigs = []compute.SImportDisk{}
for _, disk := range domainDisks {
if disk.Source == nil || disk.Source.File == nil {
return nil, fmt.Errorf("Domain disk missing source file ?")
}
if disk.Target == nil {
return nil, fmt.Errorf("Domain disk missing target config")
}
// XXX: Ignore backing file
var diskConfig = compute.SImportDisk{
AccessPath: disk.Source.File.File,
Index: int(disk.Source.Index),
}
if disk.Target.Bus != "virtio" {
diskConfig.Driver = "scsi"
} else {
diskConfig.Driver = disk.Target.Bus
}
if img, err := qemuimg.NewQemuImage(diskConfig.AccessPath); err != nil {
return nil, fmt.Errorf("Domain disk %s open failed: %s", diskConfig.AccessPath, err)
} else {
diskConfig.SizeMb = img.GetSizeMB()
diskConfig.Format = img.Format.String()
}
diskConfigs = append(diskConfigs, diskConfig)
}
return diskConfigs, nil
}
func (m *SGuestManager) LibvirtDomainInterfaceToNicConfig(
domainInterfaces []libvirtxml.DomainInterface) ([]compute.SImportNic, error) {
var nicConfigs = []compute.SImportNic{}
for idx, nic := range domainInterfaces {
if nic.MAC == nil {
return nil, fmt.Errorf("Domain interface %#v missing mac address", nic)
}
nicConfigs = append(nicConfigs, compute.SImportNic{Index: idx, Mac: nic.MAC.Address})
}
return nicConfigs, nil
}

View File

@@ -201,9 +201,7 @@ func (d *SKVMGuestDisk) connectionPrecheck() {
}
func (d *SKVMGuestDisk) LvmDisconnectNotify() {
if lvmTool.GetPathType(d.rootBackingFilePath()) == LVM_PATH {
lvmTool.Signal(d.rootBackingFilePath())
}
lvmTool.Signal(d.rootBackingFilePath())
}
func (d *SKVMGuestDisk) setupLVMS() (bool, error) {

View File

@@ -198,7 +198,7 @@ func (this *BaseManager) _submit(session *mcclient.ClientSession, method httputi
type SubmitResult struct {
Status int
Id string
Id interface{}
Data jsonutils.JSONObject
}
@@ -207,7 +207,7 @@ func SubmitResults2JSON(results []SubmitResult) jsonutils.JSONObject {
for _, r := range results {
obj := jsonutils.NewDict()
obj.Add(jsonutils.NewInt(int64(r.Status)), "status")
obj.Add(jsonutils.NewString(r.Id), "id")
obj.Add(jsonutils.Marshal(r.Id), "id")
obj.Add(r.Data, "data")
arr.Add(obj)
}
@@ -233,31 +233,51 @@ func (this *BaseManager) _batch(session *mcclient.ClientSession, method httputil
})
}
func BatchDo(ids []string, do func(id string) (jsonutils.JSONObject, error)) []SubmitResult {
results := make(chan SubmitResult, len(ids))
for _, id := range ids {
go func(id string) {
r, e := do(id)
if e != nil {
ecls, ok := e.(*httputils.JSONClientError)
if ok {
results <- SubmitResult{Status: ecls.Code, Id: id, Data: jsonutils.Marshal(ecls)}
} else {
results <- SubmitResult{Status: 400, Id: id, Data: jsonutils.NewString(e.Error())}
}
} else {
results <- SubmitResult{Status: 200, Id: id, Data: r}
}
}(id)
func addResult(results chan SubmitResult, id interface{}, r jsonutils.JSONObject, e error) {
if e != nil {
ecls, ok := e.(*httputils.JSONClientError)
if ok {
results <- SubmitResult{Status: ecls.Code, Id: id, Data: jsonutils.Marshal(ecls)}
} else {
results <- SubmitResult{Status: 400, Id: id, Data: jsonutils.NewString(e.Error())}
}
} else {
results <- SubmitResult{Status: 200, Id: id, Data: r}
}
ret := make([]SubmitResult, len(ids))
for i := 0; i < len(ids); i++ {
}
func waitResults(results chan SubmitResult, length int) []SubmitResult {
ret := make([]SubmitResult, length)
for i := 0; i < length; i++ {
ret[i] = <-results
}
close(results)
return ret
}
func BatchDo(ids []string, do func(id string) (jsonutils.JSONObject, error)) []SubmitResult {
results := make(chan SubmitResult, len(ids))
for i := 0; i < len(ids); i++ {
go func(id string) {
r, e := do(id)
addResult(results, id, r, e)
}(ids[i])
}
return waitResults(results, len(ids))
}
func BatchDoClassAction(
batchParams []jsonutils.JSONObject, do func(jsonutils.JSONObject) (jsonutils.JSONObject, error),
) []SubmitResult {
results := make(chan SubmitResult, len(batchParams))
for i := 0; i < len(batchParams); i++ {
go func(params jsonutils.JSONObject) {
r, e := do(params)
addResult(results, params, r, e)
}(batchParams[i])
}
return waitResults(results, len(batchParams))
}
func (this *BaseManager) _get(session *mcclient.ClientSession, path string, respKey string) (jsonutils.JSONObject, error) {
/* _, body, err := this.jsonRequest(session, "GET", path, nil, nil)
if err != nil {

View File

@@ -477,6 +477,16 @@ func (this *ResourceManager) PerformClassActionInContexts(session *mcclient.Clie
return this._post(session, path, params, this.KeywordPlural)
}
func (this *ResourceManager) BatchPerformClassAction(session *mcclient.ClientSession, action string, batchParams []jsonutils.JSONObject) []SubmitResult {
return this.BatchPerformClassActionInContexts(session, action, batchParams, nil)
}
func (this *ResourceManager) BatchPerformClassActionInContexts(session *mcclient.ClientSession, action string, batchParams []jsonutils.JSONObject, ctxs []ManagerContext) []SubmitResult {
return BatchDoClassAction(batchParams, func(params jsonutils.JSONObject) (jsonutils.JSONObject, error) {
return this.PerformClassActionInContexts(session, action, params, ctxs)
})
}
func (this *ResourceManager) BatchPerformAction(session *mcclient.ClientSession, idlist []string, action string, params jsonutils.JSONObject) []SubmitResult {
return this.BatchPerformActionInContexts(session, idlist, action, params, nil)
}

View File

@@ -113,6 +113,9 @@ const (
ACT_FETCH = "下载密钥"
ACT_VM_CHANGE_NIC = "更改网卡配置"
ACT_HOST_IMPORT_LIBVIRT_SERVERS = "libvirt托管虚拟机导入"
ACT_GUEST_CREATE_FROM_IMPORT = "导入虚拟机创建"
)
// golang 不支持 const 的string array, http://t.cn/EzAvbw8

View File

@@ -180,7 +180,7 @@ func PrintJSONBatchResults(results []modules.SubmitResult, columns []string) {
} else {
err := jsonutils.NewDict()
err.Add(jsonutils.NewInt(int64(r.Status)), "status")
err.Add(jsonutils.NewString(r.Id), "id")
err.Add(jsonutils.Marshal(r.Id), "id")
err.Add(r.Data, "error")
errs = append(errs, err)
}

4
vendor/github.com/libvirt/libvirt-go-xml/.gitignore generated vendored Normal file
View File

@@ -0,0 +1,4 @@
*~
*.bak
.\#*
testdata/

0
vendor/github.com/libvirt/libvirt-go-xml/.gitmodules generated vendored Normal file
View File

4
vendor/github.com/libvirt/libvirt-go-xml/.gitpublish generated vendored Normal file
View File

@@ -0,0 +1,4 @@
[gitpublishprofile "default"]
base = master
to = libvir-list@redhat.com
prefix = go-xml PATCH

13
vendor/github.com/libvirt/libvirt-go-xml/.travis.yml generated vendored Normal file
View File

@@ -0,0 +1,13 @@
language: go
os: linux
dist: trusty
go:
- 1.5
- 1.6
- 1.7
- 1.8
- 1.9
script:
go test -timeout 10m -tags xmlroundtrip -v

19
vendor/github.com/libvirt/libvirt-go-xml/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,19 @@
The MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

67
vendor/github.com/libvirt/libvirt-go-xml/README.md generated vendored Normal file
View File

@@ -0,0 +1,67 @@
# libvirt-go-xml [![Build Status](https://travis-ci.org/libvirt/libvirt-go-xml.svg?branch=master)](https://travis-ci.org/libvirt/libvirt-go-xml) [![GoDoc](https://godoc.org/github.com/libvirt/libvirt-go-xml?status.svg)](https://godoc.org/github.com/libvirt/libvirt-go-xml)
Go API for manipulating libvirt XML documents
This package provides a Go API that defines a set of structs, annotated for use
with "encoding/xml", that can represent libvirt XML documents. There is no
dependancy on the libvirt library itself, so this can be used regardless of
the way in which the application talks to libvirt.
## Documentation
* [API documentation for the bindings](https://godoc.org/github.com/libvirt/libvirt-go-xml)
* [Libvirt XML schema documentation](https://libvirt.org/format.html):
* [capabilities](https://libvirt.org/formatcaps.html)
* [domain](https://libvirt.org/formatdomain.html)
* [domain capabilities](https://libvirt.org/formatdomaincaps.html)
* [domain snapshot](https://libvirt.org/formatsnapshot.html)
* [network](https://libvirt.org/formatnetwork.html)
* [node device](https://libvirt.org/formatnode.html)
* [nwfilter](https://libvirt.org/formatnwfilter.html)
* [secret](https://libvirt.org/formatsecret.html)
* [storage](https://libvirt.org/formatstorage.html)
* [storage encryption](https://libvirt.org/formatstorageencryption.html)
## Contributing
The libvirt project aims to add support for new APIs to libvirt-go
as soon as they are added to the main libvirt C library. If you
are submitting changes to the libvirt C library API, please submit
a libvirt-go change at the same time.
Bug fixes and other improvements to the libvirt-go library are
welcome at any time. The preferred submission method is to use
git send-email to submit patches to the libvir-list@redhat.com
mailing list. eg. to send a single patch
```
# git send-email --to libvir-list@redhat.com --subject-prefix "PATCH go-xml" \
--smtp-server=$HOSTNAME -1
```
Or to send all patches on the current branch, against master
```
$ git send-email --to libvir-list@redhat.com --subject-prefix "PATCH go-xml" \
--smtp-server=$HOSTNAME --no-chain-reply-to --cover-letter --annotate \
master..
```
Note the master GIT repository is at
```
http://libvirt.org/git/?p=libvirt-go.git;a=summary
```
The following automatic read-only mirrors are available as a
convenience to allow contributors to "fork" the repository:
```
https://gitlab.com/libvirt/libvirt-go
https://github.com/libvirt/libvirt-go
```
While you can send pull-requests to these mirrors, they will be
re-submitted via emai to the mailing list for review before
being merged, unless they are trivial/obvious bug fixes.

View File

@@ -0,0 +1,326 @@
/*
* This file is part of the libvirt-go-xml project
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* Copyright (C) 2016 Red Hat, Inc.
*
*/
package libvirtxml
import (
"encoding/xml"
)
type CapsHostCPUTopology struct {
Sockets int `xml:"sockets,attr"`
Cores int `xml:"cores,attr"`
Threads int `xml:"threads,attr"`
}
type CapsHostCPUFeatureFlag struct {
Name string `xml:"name,attr"`
}
type CapsHostCPUPageSize struct {
Size int `xml:"size,attr"`
Unit string `xml:"unit,attr"`
}
type CapsHostCPUMicrocode struct {
Version int `xml:"version,attr"`
}
type CapsHostCPU struct {
XMLName xml.Name `xml:"cpu"`
Arch string `xml:"arch,omitempty"`
Model string `xml:"model,omitempty"`
Vendor string `xml:"vendor,omitempty"`
Topology *CapsHostCPUTopology `xml:"topology"`
FeatureFlags []CapsHostCPUFeatureFlag `xml:"feature"`
Features *CapsHostCPUFeatures `xml:"features"`
PageSizes []CapsHostCPUPageSize `xml:"pages"`
Microcode *CapsHostCPUMicrocode `xml:"microcode"`
}
type CapsHostCPUFeature struct {
}
type CapsHostCPUFeatures struct {
PAE *CapsHostCPUFeature `xml:"pae"`
NonPAE *CapsHostCPUFeature `xml:"nonpae"`
SVM *CapsHostCPUFeature `xml:"svm"`
VMX *CapsHostCPUFeature `xml:"vmx"`
}
type CapsHostNUMAMemory struct {
Size uint64 `xml:",chardata"`
Unit string `xml:"unit,attr"`
}
type CapsHostNUMAPageInfo struct {
Size int `xml:"size,attr"`
Unit string `xml:"unit,attr"`
Count uint64 `xml:",chardata"`
}
type CapsHostNUMACPU struct {
ID int `xml:"id,attr"`
SocketID *int `xml:"socket_id,attr"`
CoreID *int `xml:"core_id,attr"`
Siblings string `xml:"siblings,attr,omitempty"`
}
type CapsHostNUMASibling struct {
ID int `xml:"id,attr"`
Value int `xml:"value,attr"`
}
type CapsHostNUMACell struct {
ID int `xml:"id,attr"`
Memory *CapsHostNUMAMemory `xml:"memory"`
PageInfo []CapsHostNUMAPageInfo `xml:"pages"`
Distances *CapsHostNUMADistances `xml:"distances"`
CPUS *CapsHostNUMACPUs `xml:"cpus"`
}
type CapsHostNUMADistances struct {
Siblings []CapsHostNUMASibling `xml:"sibling"`
}
type CapsHostNUMACPUs struct {
Num uint `xml:"num,attr,omitempty"`
CPUs []CapsHostNUMACPU `xml:"cpu"`
}
type CapsHostNUMATopology struct {
Cells *CapsHostNUMACells `xml:"cells"`
}
type CapsHostNUMACells struct {
Num uint `xml:"num,attr,omitempty"`
Cells []CapsHostNUMACell `xml:"cell"`
}
type CapsHostSecModelLabel struct {
Type string `xml:"type,attr"`
Value string `xml:",chardata"`
}
type CapsHostSecModel struct {
Name string `xml:"model"`
DOI string `xml:"doi"`
Labels []CapsHostSecModelLabel `xml:"baselabel"`
}
type CapsHostMigrationFeatures struct {
Live *CapsHostMigrationLive `xml:"live"`
URITransports *CapsHostMigrationURITransports `xml:"uri_transports"`
}
type CapsHostMigrationLive struct {
}
type CapsHostMigrationURITransports struct {
URI []string `xml:"uri_transport"`
}
type CapsHost struct {
UUID string `xml:"uuid,omitempty"`
CPU *CapsHostCPU `xml:"cpu"`
PowerManagement *CapsHostPowerManagement `xml:"power_management"`
IOMMU *CapsHostIOMMU `xml:"iommu"`
MigrationFeatures *CapsHostMigrationFeatures `xml:"migration_features"`
NUMA *CapsHostNUMATopology `xml:"topology"`
Cache *CapsHostCache `xml:"cache"`
MemoryBandwidth *CapsHostMemoryBandwidth `xml:"memory_bandwidth"`
SecModel []CapsHostSecModel `xml:"secmodel"`
}
type CapsHostPowerManagement struct {
SuspendMem *CapsHostPowerManagementMode `xml:"suspend_mem"`
SuspendDisk *CapsHostPowerManagementMode `xml:"suspend_disk"`
SuspendHybrid *CapsHostPowerManagementMode `xml:"suspend_hybrid"`
}
type CapsHostPowerManagementMode struct {
}
type CapsHostIOMMU struct {
Support string `xml:"support,attr"`
}
type CapsHostCache struct {
Banks []CapsHostCacheBank `xml:"bank"`
Monitor *CapsHostCacheMonitor `xml:"monitor"`
}
type CapsHostCacheBank struct {
ID uint `xml:"id,attr"`
Level uint `xml:"level,attr"`
Type string `xml:"type,attr"`
Size uint `xml:"size,attr"`
Unit string `xml:"unit,attr"`
CPUs string `xml:"cpus,attr"`
Control []CapsHostCacheControl `xml:"control"`
}
type CapsHostCacheMonitor struct {
Level uint `xml:"level,attr,omitempty"`
ResueThreshold uint `xml:"reuseThreshold,attr,omitempty"`
MaxMonitors uint `xml:"maxMonitors,attr"`
Features []CapsHostCacheMonitorFeature `xml:"feature"`
}
type CapsHostCacheMonitorFeature struct {
Name string `xml:"name,attr"`
}
type CapsHostCacheControl struct {
Granularity uint `xml:"granularity,attr"`
Min uint `xml:"min,attr,omitempty"`
Unit string `xml:"unit,attr"`
Type string `xml:"type,attr"`
MaxAllows uint `xml:"maxAllocs,attr"`
}
type CapsHostMemoryBandwidth struct {
Nodes []CapsHostMemoryBandwidthNode `xml:"node"`
Monitor *CapsHostMemoryBandwidthMonitor `xml:"monitor"`
}
type CapsHostMemoryBandwidthNode struct {
ID uint `xml:"id,attr"`
CPUs string `xml:"cpus,attr"`
Control *CapsHostMemoryBandwidthNodeControl `xml:"control"`
}
type CapsHostMemoryBandwidthNodeControl struct {
Granularity uint `xml:"granularity,attr"`
Min uint `xml:"min,attr"`
MaxAllocs uint `xml:"maxAllocs,attr"`
}
type CapsHostMemoryBandwidthMonitor struct {
MaxMonitors uint `xml:"maxMonitors,attr"`
Features []CapsHostMemoryBandwidthMonitorFeature `xml:"feature"`
}
type CapsHostMemoryBandwidthMonitorFeature struct {
Name string `xml:"name,attr"`
}
type CapsGuestMachine struct {
Name string `xml:",chardata"`
MaxCPUs int `xml:"maxCpus,attr,omitempty"`
Canonical string `xml:"canonical,attr,omitempty"`
}
type CapsGuestDomain struct {
Type string `xml:"type,attr"`
Emulator string `xml:"emulator,omitempty"`
Machines []CapsGuestMachine `xml:"machine"`
}
type CapsGuestArch struct {
Name string `xml:"name,attr"`
WordSize string `xml:"wordsize"`
Emulator string `xml:"emulator"`
Loader string `xml:"loader,omitempty"`
Machines []CapsGuestMachine `xml:"machine"`
Domains []CapsGuestDomain `xml:"domain"`
}
type CapsGuestFeatureCPUSelection struct {
}
type CapsGuestFeatureDeviceBoot struct {
}
type CapsGuestFeaturePAE struct {
}
type CapsGuestFeatureNonPAE struct {
}
type CapsGuestFeatureDiskSnapshot struct {
Default string `xml:"default,attr,omitempty"`
Toggle string `xml:"toggle,attr,omitempty"`
}
type CapsGuestFeatureAPIC struct {
Default string `xml:"default,attr,omitempty"`
Toggle string `xml:"toggle,attr,omitempty"`
}
type CapsGuestFeatureACPI struct {
Default string `xml:"default,attr,omitempty"`
Toggle string `xml:"toggle,attr,omitempty"`
}
type CapsGuestFeatureIA64BE struct {
}
type CapsGuestFeatures struct {
CPUSelection *CapsGuestFeatureCPUSelection `xml:"cpuselection"`
DeviceBoot *CapsGuestFeatureDeviceBoot `xml:"deviceboot"`
DiskSnapshot *CapsGuestFeatureDiskSnapshot `xml:"disksnapshot"`
PAE *CapsGuestFeaturePAE `xml:"pae"`
NonPAE *CapsGuestFeatureNonPAE `xml:"nonpae"`
APIC *CapsGuestFeatureAPIC `xml:"apic"`
ACPI *CapsGuestFeatureACPI `xml:"acpi"`
IA64BE *CapsGuestFeatureIA64BE `xml:"ia64_be"`
}
type CapsGuest struct {
OSType string `xml:"os_type"`
Arch CapsGuestArch `xml:"arch"`
Features *CapsGuestFeatures `xml:"features"`
}
type Caps struct {
XMLName xml.Name `xml:"capabilities"`
Host CapsHost `xml:"host"`
Guests []CapsGuest `xml:"guest"`
}
func (c *CapsHostCPU) Unmarshal(doc string) error {
return xml.Unmarshal([]byte(doc), c)
}
func (c *CapsHostCPU) Marshal() (string, error) {
doc, err := xml.MarshalIndent(c, "", " ")
if err != nil {
return "", err
}
return string(doc), nil
}
func (c *Caps) Unmarshal(doc string) error {
return xml.Unmarshal([]byte(doc), c)
}
func (c *Caps) Marshal() (string, error) {
doc, err := xml.MarshalIndent(c, "", " ")
if err != nil {
return "", err
}
return string(doc), nil
}

62
vendor/github.com/libvirt/libvirt-go-xml/doc.go generated vendored Normal file
View File

@@ -0,0 +1,62 @@
/*
* This file is part of the libvirt-go-xml project
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* Copyright (C) 2017 Red Hat, Inc.
*
*/
// Package libvirt-go-xml defines structs for parsing libvirt XML schemas
//
// The libvirt API uses XML schemas/documents to describe the configuration
// of many of its managed objects. Thus when using the libvirt-go package,
// it is often neccessary to either parse or format XML documents. This
// package defines a set of Go structs which have been annotated for use
// with the encoding/xml API to manage libvirt XML documents.
//
// Example creating a domain XML document from configuration:
//
// import (
// "github.com/libvirt/libvirt-go-xml"
// )
//
// domcfg := &libvirtxml.Domain{Type: "kvm", Name: "demo",
// UUID: "8f99e332-06c4-463a-9099-330fb244e1b3",
// ....}
// xmldoc, err := domcfg.Marshal()
//
// Example parsing a domainXML document, in combination with libvirt-go
//
// import (
// "github.com/libvirt/libvirt-go"
// "github.com/libvirt/libvirt-go-xml"
// "fmt"
// )
//
// conn, err := libvirt.NewConnect("qemu:///system")
// dom := conn.LookupDomainByName("demo")
// xmldoc, err := dom.GetXMLDesc(0)
//
// domcfg := &libvirtxml.Domain{}
// err := domcfg.Unmarshal(xmldoc)
//
// fmt.Printf("Virt type %s", domcfg.Type)
//
package libvirtxml

6
vendor/github.com/libvirt/libvirt-go-xml/document.go generated vendored Normal file
View File

@@ -0,0 +1,6 @@
package libvirtxml
type Document interface {
Unmarshal(doc string) error
Marshal() (string, error)
}

5218
vendor/github.com/libvirt/libvirt-go-xml/domain.go generated vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,141 @@
/*
* This file is part of the libvirt-go-xml project
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* Copyright (C) 2016 Red Hat, Inc.
*
*/
package libvirtxml
import (
"encoding/xml"
)
type DomainCaps struct {
XMLName xml.Name `xml:"domainCapabilities"`
Path string `xml:"path"`
Domain string `xml:"domain"`
Machine string `xml:"machine,omitempty"`
Arch string `xml:"arch"`
VCPU *DomainCapsVCPU `xml:"vcpu"`
IOThreads *DomainCapsIOThreads `xml:"iothreads"`
OS *DomainCapsOS `xml:"os"`
CPU *DomainCapsCPU `xml:"cpu"`
Devices *DomainCapsDevices `xml:"devices"`
Features *DomainCapsFeatures `xml:"features"`
}
type DomainCapsVCPU struct {
Max uint `xml:"max,attr"`
}
type DomainCapsOS struct {
Supported string `xml:"supported,attr"`
Loader *DomainCapsOSLoader `xml:"loader"`
}
type DomainCapsOSLoader struct {
Supported string `xml:"supported,attr"`
Values []string `xml:"value"`
Enums []DomainCapsEnum `xml:"enum"`
}
type DomainCapsIOThreads struct {
Supported string `xml:"supported,attr"`
}
type DomainCapsCPU struct {
Modes []DomainCapsCPUMode `xml:"mode"`
}
type DomainCapsCPUMode struct {
Name string `xml:"name,attr"`
Supported string `xml:"supported,attr"`
Models []DomainCapsCPUModel `xml:"model"`
Vendor string `xml:"vendor,omitempty"`
Features []DomainCapsCPUFeature `xml:"feature"`
}
type DomainCapsCPUModel struct {
Name string `xml:",chardata"`
Usable string `xml:"usable,attr,omitempty"`
Fallback string `xml:"fallback,attr,omitempty"`
}
type DomainCapsCPUFeature struct {
Policy string `xml:"policy,attr,omitempty"`
Name string `xml:"name,attr"`
}
type DomainCapsEnum struct {
Name string `xml:"name,attr"`
Values []string `xml:"value"`
}
type DomainCapsDevices struct {
Disk *DomainCapsDevice `xml:"disk"`
Graphics *DomainCapsDevice `xml:"graphics"`
Video *DomainCapsDevice `xml:"video"`
HostDev *DomainCapsDevice `xml:"hostdev"`
}
type DomainCapsDevice struct {
Supported string `xml:"supported,attr"`
Enums []DomainCapsEnum `xml:"enum"`
}
type DomainCapsFeatures struct {
GIC *DomainCapsFeatureGIC `xml:"gic"`
VMCoreInfo *DomainCapsFeatureVMCoreInfo `xml:"vmcoreinfo"`
GenID *DomainCapsFeatureGenID `xml:"genid"`
SEV *DomainCapsFeatureSEV `xml:"sev"`
}
type DomainCapsFeatureGIC struct {
Supported string `xml:"supported,attr"`
Enums []DomainCapsEnum `xml:"enum"`
}
type DomainCapsFeatureVMCoreInfo struct {
Supported string `xml:"supported,attr"`
}
type DomainCapsFeatureGenID struct {
Supported string `xml:"supported,attr"`
}
type DomainCapsFeatureSEV struct {
Supported string `xml:"supported,attr"`
CBitPos uint `xml:"cbitpos,omitempty"`
ReducedPhysBits uint `xml:"reducedPhysBits,omitempty"`
}
func (c *DomainCaps) Unmarshal(doc string) error {
return xml.Unmarshal([]byte(doc), c)
}
func (c *DomainCaps) Marshal() (string, error) {
doc, err := xml.MarshalIndent(c, "", " ")
if err != nil {
return "", err
}
return string(doc), nil
}

View File

@@ -0,0 +1,134 @@
/*
* This file is part of the libvirt-go-xml project
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* Copyright (C) 2017 Red Hat, Inc.
*
*/
package libvirtxml
import "encoding/xml"
type DomainSnapshotDiskDriver struct {
Type string `xml:"type,attr,omitempty"`
}
type DomainSnapshotDisk struct {
Name string `xml:"name,attr"`
Snapshot string `xml:"snapshot,attr,omitempty"`
Driver *DomainSnapshotDiskDriver `xml:"driver"`
Source *DomainDiskSource `xml:"source"`
}
type DomainSnapshotDisks struct {
Disks []DomainSnapshotDisk `xml:"disk"`
}
type DomainSnapshotMemory struct {
Snapshot string `xml:"snapshot,attr"`
File string `xml:"file,attr,omitempty"`
}
type DomainSnapshotParent struct {
Name string `xml:"name"`
}
type DomainSnapshot struct {
XMLName xml.Name `xml:"domainsnapshot"`
Name string `xml:"name,omitempty"`
Description string `xml:"description,omitempty"`
State string `xml:"state,omitempty"`
CreationTime string `xml:"creationTime,omitempty"`
Parent *DomainSnapshotParent `xml:"parent"`
Memory *DomainSnapshotMemory `xml:"memory"`
Disks *DomainSnapshotDisks `xml:"disks"`
Domain *Domain `xml:"domain"`
Active *uint `xml:"active"`
}
type domainSnapshotDisk DomainSnapshotDisk
func (a *DomainSnapshotDisk) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
start.Name.Local = "disk"
if a.Source != nil {
if a.Source.File != nil {
start.Attr = append(start.Attr, xml.Attr{
xml.Name{Local: "type"}, "file",
})
} else if a.Source.Block != nil {
start.Attr = append(start.Attr, xml.Attr{
xml.Name{Local: "type"}, "block",
})
} else if a.Source.Dir != nil {
start.Attr = append(start.Attr, xml.Attr{
xml.Name{Local: "type"}, "dir",
})
} else if a.Source.Network != nil {
start.Attr = append(start.Attr, xml.Attr{
xml.Name{Local: "type"}, "network",
})
} else if a.Source.Volume != nil {
start.Attr = append(start.Attr, xml.Attr{
xml.Name{Local: "type"}, "volume",
})
}
}
disk := domainSnapshotDisk(*a)
return e.EncodeElement(disk, start)
}
func (a *DomainSnapshotDisk) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
typ, ok := getAttr(start.Attr, "type")
if !ok {
typ = "file"
}
a.Source = &DomainDiskSource{}
if typ == "file" {
a.Source.File = &DomainDiskSourceFile{}
} else if typ == "block" {
a.Source.Block = &DomainDiskSourceBlock{}
} else if typ == "network" {
a.Source.Network = &DomainDiskSourceNetwork{}
} else if typ == "dir" {
a.Source.Dir = &DomainDiskSourceDir{}
} else if typ == "volume" {
a.Source.Volume = &DomainDiskSourceVolume{}
}
disk := domainSnapshotDisk(*a)
err := d.DecodeElement(&disk, &start)
if err != nil {
return err
}
*a = DomainSnapshotDisk(disk)
return nil
}
func (s *DomainSnapshot) Unmarshal(doc string) error {
return xml.Unmarshal([]byte(doc), s)
}
func (s *DomainSnapshot) Marshal() (string, error) {
doc, err := xml.MarshalIndent(s, "", " ")
if err != nil {
return "", err
}
return string(doc), nil
}

150
vendor/github.com/libvirt/libvirt-go-xml/interface.go generated vendored Normal file
View File

@@ -0,0 +1,150 @@
/*
* This file is part of the libvirt-go-xml project
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* Copyright (C) 2017 Lian Duan <blazeblue@gmail.com>
*
*/
package libvirtxml
import (
"encoding/xml"
)
type Interface struct {
XMLName xml.Name `xml:"interface"`
Name string `xml:"name,attr,omitempty"`
Start *InterfaceStart `xml:"start"`
MTU *InterfaceMTU `xml:"mtu"`
Protocol []InterfaceProtocol `xml:"protocol"`
Link *InterfaceLink `xml:"link"`
MAC *InterfaceMAC `xml:"mac"`
Bond *InterfaceBond `xml:"bond"`
Bridge *InterfaceBridge `xml:"bridge"`
VLAN *InterfaceVLAN `xml:"vlan"`
}
type InterfaceStart struct {
Mode string `xml:"mode,attr"`
}
type InterfaceMTU struct {
Size uint `xml:"size,attr"`
}
type InterfaceProtocol struct {
Family string `xml:"family,attr,omitempty"`
AutoConf *InterfaceAutoConf `xml:"autoconf"`
DHCP *InterfaceDHCP `xml:"dhcp"`
IPs []InterfaceIP `xml:"ip"`
Route []InterfaceRoute `xml:"route"`
}
type InterfaceAutoConf struct {
}
type InterfaceDHCP struct {
PeerDNS string `xml:"peerdns,attr,omitempty"`
}
type InterfaceIP struct {
Address string `xml:"address,attr"`
Prefix uint `xml:"prefix,attr,omitempty"`
}
type InterfaceRoute struct {
Gateway string `xml:"gateway,attr"`
}
type InterfaceLink struct {
Speed uint `xml:"speed,attr,omitempty"`
State string `xml:"state,attr,omitempty"`
}
type InterfaceMAC struct {
Address string `xml:"address,attr"`
}
type InterfaceBond struct {
Mode string `xml:"mode,attr,omitempty"`
ARPMon *InterfaceBondARPMon `xml:"arpmon"`
MIIMon *InterfaceBondMIIMon `xml:"miimon"`
Interfaces []Interface `xml:"interface"`
}
type InterfaceBondARPMon struct {
Interval uint `xml:"interval,attr,omitempty"`
Target string `xml:"target,attr,omitempty"`
Validate string `xml:"validate,attr,omitempty"`
}
type InterfaceBondMIIMon struct {
Freq uint `xml:"freq,attr,omitempty"`
UpDelay uint `xml:"updelay,attr,omitempty"`
Carrier string `xml:"carrier,attr,omitempty"`
}
type InterfaceBridge struct {
STP string `xml:"stp,attr,omitempty"`
Delay *float64 `xml:"delay,attr"`
Interfaces []Interface `xml:"interface"`
}
type InterfaceVLAN struct {
Tag *uint `xml:"tag,attr"`
Interface *Interface `xml:"interface"`
}
type interfaceDup Interface
func (s *Interface) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
start.Name.Local = "interface"
typ := "ethernet"
if s.Bond != nil {
typ = "bond"
} else if s.Bridge != nil {
typ = "bridge"
} else if s.VLAN != nil {
typ = "vlan"
}
start.Attr = append(start.Attr, xml.Attr{
Name: xml.Name{Local: "type"},
Value: typ,
})
i := interfaceDup(*s)
return e.EncodeElement(i, start)
}
func (s *Interface) Unmarshal(doc string) error {
return xml.Unmarshal([]byte(doc), s)
}
func (s *Interface) Marshal() (string, error) {
doc, err := xml.MarshalIndent(s, "", " ")
if err != nil {
return "", err
}
return string(doc), nil
}

538
vendor/github.com/libvirt/libvirt-go-xml/network.go generated vendored Normal file
View File

@@ -0,0 +1,538 @@
/*
* This file is part of the libvirt-go-xml project
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* Copyright (C) 2017 Lian Duan <blazeblue@gmail.com>
*
*/
package libvirtxml
import (
"encoding/xml"
)
type NetworkBridge struct {
Name string `xml:"name,attr,omitempty"`
STP string `xml:"stp,attr,omitempty"`
Delay string `xml:"delay,attr,omitempty"`
MACTableManager string `xml:"macTableManager,attr,omitempty"`
Zone string `xml:"zone,attr,omitempty"`
}
type NetworkVirtualPort struct {
Params *NetworkVirtualPortParams `xml:"parameters"`
}
type NetworkVirtualPortParams struct {
Any *NetworkVirtualPortParamsAny `xml:"-"`
VEPA8021QBG *NetworkVirtualPortParamsVEPA8021QBG `xml:"-"`
VNTag8011QBH *NetworkVirtualPortParamsVNTag8021QBH `xml:"-"`
OpenVSwitch *NetworkVirtualPortParamsOpenVSwitch `xml:"-"`
MidoNet *NetworkVirtualPortParamsMidoNet `xml:"-"`
}
type NetworkVirtualPortParamsAny struct {
ManagerID *uint `xml:"managerid,attr"`
TypeID *uint `xml:"typeid,attr"`
TypeIDVersion *uint `xml:"typeidversion,attr"`
InstanceID string `xml:"instanceid,attr,omitempty"`
ProfileID string `xml:"profileid,attr,omitempty"`
InterfaceID string `xml:"interfaceid,attr,omitempty"`
}
type NetworkVirtualPortParamsVEPA8021QBG struct {
ManagerID *uint `xml:"managerid,attr"`
TypeID *uint `xml:"typeid,attr"`
TypeIDVersion *uint `xml:"typeidversion,attr"`
InstanceID string `xml:"instanceid,attr,omitempty"`
}
type NetworkVirtualPortParamsVNTag8021QBH struct {
ProfileID string `xml:"profileid,attr,omitempty"`
}
type NetworkVirtualPortParamsOpenVSwitch struct {
InterfaceID string `xml:"interfaceid,attr,omitempty"`
ProfileID string `xml:"profileid,attr,omitempty"`
}
type NetworkVirtualPortParamsMidoNet struct {
InterfaceID string `xml:"interfaceid,attr,omitempty"`
}
type NetworkDomain struct {
Name string `xml:"name,attr,omitempty"`
LocalOnly string `xml:"localOnly,attr,omitempty"`
}
type NetworkForwardNATAddress struct {
Start string `xml:"start,attr"`
End string `xml:"end,attr"`
}
type NetworkForwardNATPort struct {
Start uint `xml:"start,attr"`
End uint `xml:"end,attr"`
}
type NetworkForwardNAT struct {
Addresses []NetworkForwardNATAddress `xml:"address"`
Ports []NetworkForwardNATPort `xml:"port"`
}
type NetworkForward struct {
Mode string `xml:"mode,attr,omitempty"`
Dev string `xml:"dev,attr,omitempty"`
Managed string `xml:"managed,attr,omitempty"`
Driver *NetworkForwardDriver `xml:"driver"`
PFs []NetworkForwardPF `xml:"pf"`
NAT *NetworkForwardNAT `xml:"nat"`
Interfaces []NetworkForwardInterface `xml:"interface"`
Addresses []NetworkForwardAddress `xml:"address"`
}
type NetworkForwardDriver struct {
Name string `xml:"name,attr"`
}
type NetworkForwardPF struct {
Dev string `xml:"dev,attr"`
}
type NetworkForwardAddress struct {
PCI *NetworkForwardAddressPCI `xml:"-"`
}
type NetworkForwardAddressPCI struct {
Domain *uint `xml:"domain,attr"`
Bus *uint `xml:"bus,attr"`
Slot *uint `xml:"slot,attr"`
Function *uint `xml:"function,attr"`
}
type NetworkForwardInterface struct {
XMLName xml.Name `xml:"interface"`
Dev string `xml:"dev,attr,omitempty"`
}
type NetworkMAC struct {
Address string `xml:"address,attr,omitempty"`
}
type NetworkDHCPRange struct {
XMLName xml.Name `xml:"range"`
Start string `xml:"start,attr,omitempty"`
End string `xml:"end,attr,omitempty"`
}
type NetworkDHCPHost struct {
XMLName xml.Name `xml:"host"`
ID string `xml:"id,attr,omitempty"`
MAC string `xml:"mac,attr,omitempty"`
Name string `xml:"name,attr,omitempty"`
IP string `xml:"ip,attr,omitempty"`
}
type NetworkBootp struct {
File string `xml:"file,attr,omitempty"`
Server string `xml:"server,attr,omitempty"`
}
type NetworkDHCP struct {
Ranges []NetworkDHCPRange `xml:"range"`
Hosts []NetworkDHCPHost `xml:"host"`
Bootp []NetworkBootp `xml:"bootp"`
}
type NetworkIP struct {
Address string `xml:"address,attr,omitempty"`
Family string `xml:"family,attr,omitempty"`
Netmask string `xml:"netmask,attr,omitempty"`
Prefix uint `xml:"prefix,attr,omitempty"`
LocalPtr string `xml:"localPtr,attr,omitempty"`
DHCP *NetworkDHCP `xml:"dhcp"`
TFTP *NetworkTFTP `xml:"tftp"`
}
type NetworkTFTP struct {
Root string `xml:"root,attr,omitempty"`
}
type NetworkRoute struct {
Family string `xml:"family,attr,omitempty"`
Address string `xml:"address,attr,omitempty"`
Netmask string `xml:"netmask,attr,omitempty"`
Prefix uint `xml:"prefix,attr,omitempty"`
Gateway string `xml:"gateway,attr,omitempty"`
Metric string `xml:"metric,attr,omitempty"`
}
type NetworkDNSForwarder struct {
Domain string `xml:"domain,attr,omitempty"`
Addr string `xml:"addr,attr,omitempty"`
}
type NetworkDNSTXT struct {
XMLName xml.Name `xml:"txt"`
Name string `xml:"name,attr"`
Value string `xml:"value,attr"`
}
type NetworkDNSHostHostname struct {
Hostname string `xml:",chardata"`
}
type NetworkDNSHost struct {
XMLName xml.Name `xml:"host"`
IP string `xml:"ip,attr"`
Hostnames []NetworkDNSHostHostname `xml:"hostname"`
}
type NetworkDNSSRV struct {
XMLName xml.Name `xml:"srv"`
Service string `xml:"service,attr,omitempty"`
Protocol string `xml:"protocol,attr,omitempty"`
Target string `xml:"target,attr,omitempty"`
Port uint `xml:"port,attr,omitempty"`
Priority uint `xml:"priority,attr,omitempty"`
Weight uint `xml:"weight,attr,omitempty"`
Domain string `xml:"domain,attr,omitempty"`
}
type NetworkDNS struct {
Enable string `xml:"enable,attr,omitempty"`
ForwardPlainNames string `xml:"forwardPlainNames,attr,omitempty"`
Forwarders []NetworkDNSForwarder `xml:"forwarder"`
TXTs []NetworkDNSTXT `xml:"txt"`
Host []NetworkDNSHost `xml:"host"`
SRVs []NetworkDNSSRV `xml:"srv"`
}
type NetworkMetadata struct {
XML string `xml:",innerxml"`
}
type NetworkMTU struct {
Size uint `xml:"size,attr"`
}
type Network struct {
XMLName xml.Name `xml:"network"`
IPv6 string `xml:"ipv6,attr,omitempty"`
TrustGuestRxFilters string `xml:"trustGuestRxFilters,attr,omitempty"`
Name string `xml:"name,omitempty"`
UUID string `xml:"uuid,omitempty"`
Metadata *NetworkMetadata `xml:"metadata"`
Forward *NetworkForward `xml:"forward"`
Bridge *NetworkBridge `xml:"bridge"`
MTU *NetworkMTU `xml:"mtu"`
MAC *NetworkMAC `xml:"mac"`
Domain *NetworkDomain `xml:"domain"`
DNS *NetworkDNS `xml:"dns"`
VLAN *NetworkVLAN `xml:"vlan"`
Bandwidth *NetworkBandwidth `xml:"bandwidth"`
IPs []NetworkIP `xml:"ip"`
Routes []NetworkRoute `xml:"route"`
VirtualPort *NetworkVirtualPort `xml:"virtualport"`
PortGroups []NetworkPortGroup `xml:"portgroup"`
}
type NetworkPortGroup struct {
XMLName xml.Name `xml:"portgroup"`
Name string `xml:"name,attr,omitempty"`
Default string `xml:"default,attr,omitempty"`
TrustGuestRxFilters string `xml:"trustGuestRxFilters,attr,omitempty"`
VLAN *NetworkVLAN `xml:"vlan"`
VirtualPort *NetworkVirtualPort `xml:"virtualport"`
}
type NetworkVLAN struct {
Trunk string `xml:"trunk,attr,omitempty"`
Tags []NetworkVLANTag `xml:"tag"`
}
type NetworkVLANTag struct {
ID uint `xml:"id,attr"`
NativeMode string `xml:"nativeMode,attr,omitempty"`
}
type NetworkBandwidthParams struct {
Average *uint `xml:"average,attr"`
Peak *uint `xml:"peak,attr"`
Burst *uint `xml:"burst,attr"`
Floor *uint `xml:"floor,attr"`
}
type NetworkBandwidth struct {
Inbound *NetworkBandwidthParams `xml:"inbound"`
Outbound *NetworkBandwidthParams `xml:"outbound"`
}
func (a *NetworkVirtualPortParams) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
start.Name.Local = "parameters"
if a.Any != nil {
return e.EncodeElement(a.Any, start)
} else if a.VEPA8021QBG != nil {
return e.EncodeElement(a.VEPA8021QBG, start)
} else if a.VNTag8011QBH != nil {
return e.EncodeElement(a.VNTag8011QBH, start)
} else if a.OpenVSwitch != nil {
return e.EncodeElement(a.OpenVSwitch, start)
} else if a.MidoNet != nil {
return e.EncodeElement(a.MidoNet, start)
}
return nil
}
func (a *NetworkVirtualPortParams) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
if a.Any != nil {
return d.DecodeElement(a.Any, &start)
} else if a.VEPA8021QBG != nil {
return d.DecodeElement(a.VEPA8021QBG, &start)
} else if a.VNTag8011QBH != nil {
return d.DecodeElement(a.VNTag8011QBH, &start)
} else if a.OpenVSwitch != nil {
return d.DecodeElement(a.OpenVSwitch, &start)
} else if a.MidoNet != nil {
return d.DecodeElement(a.MidoNet, &start)
}
return nil
}
type networkVirtualPort NetworkVirtualPort
func (a *NetworkVirtualPort) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
start.Name.Local = "virtualport"
if a.Params != nil {
if a.Params.Any != nil {
/* no type attr wanted */
} else if a.Params.VEPA8021QBG != nil {
start.Attr = append(start.Attr, xml.Attr{
xml.Name{Local: "type"}, "802.1Qbg",
})
} else if a.Params.VNTag8011QBH != nil {
start.Attr = append(start.Attr, xml.Attr{
xml.Name{Local: "type"}, "802.1Qbh",
})
} else if a.Params.OpenVSwitch != nil {
start.Attr = append(start.Attr, xml.Attr{
xml.Name{Local: "type"}, "openvswitch",
})
} else if a.Params.MidoNet != nil {
start.Attr = append(start.Attr, xml.Attr{
xml.Name{Local: "type"}, "midonet",
})
}
}
vp := networkVirtualPort(*a)
return e.EncodeElement(&vp, start)
}
func (a *NetworkVirtualPort) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
typ, ok := getAttr(start.Attr, "type")
a.Params = &NetworkVirtualPortParams{}
if !ok {
var any NetworkVirtualPortParamsAny
a.Params.Any = &any
} else if typ == "802.1Qbg" {
var vepa NetworkVirtualPortParamsVEPA8021QBG
a.Params.VEPA8021QBG = &vepa
} else if typ == "802.1Qbh" {
var vntag NetworkVirtualPortParamsVNTag8021QBH
a.Params.VNTag8011QBH = &vntag
} else if typ == "openvswitch" {
var ovs NetworkVirtualPortParamsOpenVSwitch
a.Params.OpenVSwitch = &ovs
} else if typ == "midonet" {
var mido NetworkVirtualPortParamsMidoNet
a.Params.MidoNet = &mido
}
vp := networkVirtualPort(*a)
err := d.DecodeElement(&vp, &start)
if err != nil {
return err
}
*a = NetworkVirtualPort(vp)
return nil
}
func (a *NetworkForwardAddressPCI) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
marshalUintAttr(&start, "domain", a.Domain, "0x%04x")
marshalUintAttr(&start, "bus", a.Bus, "0x%02x")
marshalUintAttr(&start, "slot", a.Slot, "0x%02x")
marshalUintAttr(&start, "function", a.Function, "0x%x")
e.EncodeToken(start)
e.EncodeToken(start.End())
return nil
}
func (a *NetworkForwardAddressPCI) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
for _, attr := range start.Attr {
if attr.Name.Local == "domain" {
if err := unmarshalUintAttr(attr.Value, &a.Domain, 0); err != nil {
return err
}
} else if attr.Name.Local == "bus" {
if err := unmarshalUintAttr(attr.Value, &a.Bus, 0); err != nil {
return err
}
} else if attr.Name.Local == "slot" {
if err := unmarshalUintAttr(attr.Value, &a.Slot, 0); err != nil {
return err
}
} else if attr.Name.Local == "function" {
if err := unmarshalUintAttr(attr.Value, &a.Function, 0); err != nil {
return err
}
}
}
d.Skip()
return nil
}
func (a *NetworkForwardAddress) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
if a.PCI != nil {
start.Attr = append(start.Attr, xml.Attr{
xml.Name{Local: "type"}, "pci",
})
return e.EncodeElement(a.PCI, start)
} else {
return nil
}
}
func (a *NetworkForwardAddress) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
var typ string
for _, attr := range start.Attr {
if attr.Name.Local == "type" {
typ = attr.Value
break
}
}
if typ == "" {
d.Skip()
return nil
}
if typ == "pci" {
a.PCI = &NetworkForwardAddressPCI{}
return d.DecodeElement(a.PCI, &start)
}
return nil
}
func (s *NetworkDHCPHost) Unmarshal(doc string) error {
return xml.Unmarshal([]byte(doc), s)
}
func (s *NetworkDHCPHost) Marshal() (string, error) {
doc, err := xml.MarshalIndent(s, "", " ")
if err != nil {
return "", err
}
return string(doc), nil
}
func (s *NetworkDNSHost) Unmarshal(doc string) error {
return xml.Unmarshal([]byte(doc), s)
}
func (s *NetworkDNSHost) Marshal() (string, error) {
doc, err := xml.MarshalIndent(s, "", " ")
if err != nil {
return "", err
}
return string(doc), nil
}
func (s *NetworkPortGroup) Unmarshal(doc string) error {
return xml.Unmarshal([]byte(doc), s)
}
func (s *NetworkPortGroup) Marshal() (string, error) {
doc, err := xml.MarshalIndent(s, "", " ")
if err != nil {
return "", err
}
return string(doc), nil
}
func (s *NetworkDNSTXT) Unmarshal(doc string) error {
return xml.Unmarshal([]byte(doc), s)
}
func (s *NetworkDNSTXT) Marshal() (string, error) {
doc, err := xml.MarshalIndent(s, "", " ")
if err != nil {
return "", err
}
return string(doc), nil
}
func (s *NetworkDNSSRV) Unmarshal(doc string) error {
return xml.Unmarshal([]byte(doc), s)
}
func (s *NetworkDNSSRV) Marshal() (string, error) {
doc, err := xml.MarshalIndent(s, "", " ")
if err != nil {
return "", err
}
return string(doc), nil
}
func (s *NetworkDHCPRange) Unmarshal(doc string) error {
return xml.Unmarshal([]byte(doc), s)
}
func (s *NetworkDHCPRange) Marshal() (string, error) {
doc, err := xml.MarshalIndent(s, "", " ")
if err != nil {
return "", err
}
return string(doc), nil
}
func (s *NetworkForwardInterface) Unmarshal(doc string) error {
return xml.Unmarshal([]byte(doc), s)
}
func (s *NetworkForwardInterface) Marshal() (string, error) {
doc, err := xml.MarshalIndent(s, "", " ")
if err != nil {
return "", err
}
return string(doc), nil
}
func (s *Network) Unmarshal(doc string) error {
return xml.Unmarshal([]byte(doc), s)
}
func (s *Network) Marshal() (string, error) {
doc, err := xml.MarshalIndent(s, "", " ")
if err != nil {
return "", err
}
return string(doc), nil
}

761
vendor/github.com/libvirt/libvirt-go-xml/node_device.go generated vendored Normal file
View File

@@ -0,0 +1,761 @@
/*
* This file is part of the libvirt-go-xml project
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* Copyright (C) 2017 Red Hat, Inc.
*
*/
package libvirtxml
import (
"encoding/xml"
"fmt"
"io"
"strconv"
"strings"
)
type NodeDevice struct {
XMLName xml.Name `xml:"device"`
Name string `xml:"name"`
Path string `xml:"path,omitempty"`
DevNodes []NodeDeviceDevNode `xml:"devnode"`
Parent string `xml:"parent,omitempty"`
Driver *NodeDeviceDriver `xml:"driver"`
Capability NodeDeviceCapability `xml:"capability"`
}
type NodeDeviceDevNode struct {
Type string `xml:"type,attr,omitempty"`
Path string `xml:",chardata"`
}
type NodeDeviceDriver struct {
Name string `xml:"name"`
}
type NodeDeviceCapability struct {
System *NodeDeviceSystemCapability
PCI *NodeDevicePCICapability
USB *NodeDeviceUSBCapability
USBDevice *NodeDeviceUSBDeviceCapability
Net *NodeDeviceNetCapability
SCSIHost *NodeDeviceSCSIHostCapability
SCSITarget *NodeDeviceSCSITargetCapability
SCSI *NodeDeviceSCSICapability
Storage *NodeDeviceStorageCapability
DRM *NodeDeviceDRMCapability
CCW *NodeDeviceCCWCapability
MDev *NodeDeviceMDevCapability
}
type NodeDeviceIDName struct {
ID string `xml:"id,attr"`
Name string `xml:",chardata"`
}
type NodeDevicePCIExpress struct {
Links []NodeDevicePCIExpressLink `xml:"link"`
}
type NodeDevicePCIExpressLink struct {
Validity string `xml:"validity,attr,omitempty"`
Speed float64 `xml:"speed,attr,omitempty"`
Port *uint `xml:"port,attr"`
Width *uint `xml:"width,attr"`
}
type NodeDeviceIOMMUGroup struct {
Number int `xml:"number,attr"`
Address []NodeDevicePCIAddress `xml:"address"`
}
type NodeDeviceNUMA struct {
Node int `xml:"node,attr"`
}
type NodeDevicePCICapability struct {
Class string `xml:"class,omitempty"`
Domain *uint `xml:"domain"`
Bus *uint `xml:"bus"`
Slot *uint `xml:"slot"`
Function *uint `xml:"function"`
Product NodeDeviceIDName `xml:"product,omitempty"`
Vendor NodeDeviceIDName `xml:"vendor,omitempty"`
IOMMUGroup *NodeDeviceIOMMUGroup `xml:"iommuGroup"`
NUMA *NodeDeviceNUMA `xml:"numa"`
PCIExpress *NodeDevicePCIExpress `xml:"pci-express"`
Capabilities []NodeDevicePCISubCapability `xml:"capability"`
}
type NodeDevicePCIAddress struct {
Domain *uint `xml:"domain,attr"`
Bus *uint `xml:"bus,attr"`
Slot *uint `xml:"slot,attr"`
Function *uint `xml:"function,attr"`
}
type NodeDevicePCISubCapability struct {
VirtFunctions *NodeDevicePCIVirtFunctionsCapability
PhysFunction *NodeDevicePCIPhysFunctionCapability
MDevTypes *NodeDevicePCIMDevTypesCapability
Bridge *NodeDevicePCIBridgeCapability
}
type NodeDevicePCIVirtFunctionsCapability struct {
Address []NodeDevicePCIAddress `xml:"address,omitempty"`
MaxCount int `xml:"maxCount,attr,omitempty"`
}
type NodeDevicePCIPhysFunctionCapability struct {
Address NodeDevicePCIAddress `xml:"address,omitempty"`
}
type NodeDevicePCIMDevTypesCapability struct {
Types []NodeDevicePCIMDevType `xml:"type"`
}
type NodeDevicePCIMDevType struct {
ID string `xml:"id,attr"`
Name string `xml:"name"`
DeviceAPI string `xml:"deviceAPI"`
AvailableInstances uint `xml:"availableInstances"`
}
type NodeDevicePCIBridgeCapability struct {
}
type NodeDeviceSystemHardware struct {
Vendor string `xml:"vendor"`
Version string `xml:"version"`
Serial string `xml:"serial"`
UUID string `xml:"uuid"`
}
type NodeDeviceSystemFirmware struct {
Vendor string `xml:"vendor"`
Version string `xml:"version"`
ReleaseData string `xml:"release_date"`
}
type NodeDeviceSystemCapability struct {
Product string `xml:"product,omitempty"`
Hardware *NodeDeviceSystemHardware `xml:"hardware"`
Firmware *NodeDeviceSystemFirmware `xml:"firmware"`
}
type NodeDeviceUSBDeviceCapability struct {
Bus int `xml:"bus"`
Device int `xml:"device"`
Product NodeDeviceIDName `xml:"product,omitempty"`
Vendor NodeDeviceIDName `xml:"vendor,omitempty"`
}
type NodeDeviceUSBCapability struct {
Number int `xml:"number"`
Class int `xml:"class"`
Subclass int `xml:"subclass"`
Protocol int `xml:"protocol"`
Description string `xml:"description,omitempty"`
}
type NodeDeviceNetOffloadFeatures struct {
Name string `xml:"name,attr"`
}
type NodeDeviceNetLink struct {
State string `xml:"state,attr"`
Speed string `xml:"speed,attr,omitempty"`
}
type NodeDeviceNetSubCapability struct {
Wireless80211 *NodeDeviceNet80211Capability
Ethernet80203 *NodeDeviceNet80203Capability
}
type NodeDeviceNet80211Capability struct {
}
type NodeDeviceNet80203Capability struct {
}
type NodeDeviceNetCapability struct {
Interface string `xml:"interface"`
Address string `xml:"address"`
Link *NodeDeviceNetLink `xml:"link"`
Features []NodeDeviceNetOffloadFeatures `xml:"feature,omitempty"`
Capability []NodeDeviceNetSubCapability `xml:"capability"`
}
type NodeDeviceSCSIVPortOpsCapability struct {
VPorts int `xml:"vports,omitempty"`
MaxVPorts int `xml:"maxvports,omitempty"`
}
type NodeDeviceSCSIFCHostCapability struct {
WWNN string `xml:"wwnn,omitempty"`
WWPN string `xml:"wwpn,omitempty"`
FabricWWN string `xml:"fabric_wwn,omitempty"`
}
type NodeDeviceSCSIHostSubCapability struct {
VPortOps *NodeDeviceSCSIVPortOpsCapability
FCHost *NodeDeviceSCSIFCHostCapability
}
type NodeDeviceSCSIHostCapability struct {
Host uint `xml:"host"`
UniqueID *uint `xml:"unique_id"`
Capability []NodeDeviceSCSIHostSubCapability `xml:"capability"`
}
type NodeDeviceSCSITargetCapability struct {
Target string `xml:"target"`
Capability []NodeDeviceSCSITargetSubCapability `xml:"capability"`
}
type NodeDeviceSCSITargetSubCapability struct {
FCRemotePort *NodeDeviceSCSIFCRemotePortCapability
}
type NodeDeviceSCSIFCRemotePortCapability struct {
RPort string `xml:"rport"`
WWPN string `xml:"wwpn"`
}
type NodeDeviceSCSICapability struct {
Host int `xml:"host"`
Bus int `xml:"bus"`
Target int `xml:"target"`
Lun int `xml:"lun"`
Type string `xml:"type"`
}
type NodeDeviceStorageSubCapability struct {
Removable *NodeDeviceStorageRemovableCapability
}
type NodeDeviceStorageRemovableCapability struct {
MediaAvailable *uint `xml:"media_available"`
MediaSize *uint `xml:"media_size"`
MediaLabel string `xml:"media_label,omitempty"`
LogicalBlockSize *uint `xml:"logical_block_size"`
NumBlocks *uint `xml:"num_blocks"`
}
type NodeDeviceStorageCapability struct {
Block string `xml:"block,omitempty"`
Bus string `xml:"bus,omitempty"`
DriverType string `xml:"drive_type,omitempty"`
Model string `xml:"model,omitempty"`
Vendor string `xml:"vendor,omitempty"`
Serial string `xml:"serial,omitempty"`
Size *uint `xml:"size"`
LogicalBlockSize *uint `xml:"logical_block_size"`
NumBlocks *uint `xml:"num_blocks"`
Capability []NodeDeviceStorageSubCapability `xml:"capability"`
}
type NodeDeviceDRMCapability struct {
Type string `xml:"type"`
}
type NodeDeviceCCWCapability struct {
CSSID *uint `xml:"cssid"`
SSID *uint `xml:"ssid"`
DevNo *uint `xml:"devno"`
}
type NodeDeviceMDevCapability struct {
Type *NodeDeviceMDevCapabilityType `xml:"type"`
IOMMUGroup *NodeDeviceIOMMUGroup `xml:"iommuGroup"`
}
type NodeDeviceMDevCapabilityType struct {
ID string `xml:"id,attr"`
}
func (a *NodeDevicePCIAddress) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
marshalUintAttr(&start, "domain", a.Domain, "0x%04x")
marshalUintAttr(&start, "bus", a.Bus, "0x%02x")
marshalUintAttr(&start, "slot", a.Slot, "0x%02x")
marshalUintAttr(&start, "function", a.Function, "0x%x")
e.EncodeToken(start)
e.EncodeToken(start.End())
return nil
}
func (a *NodeDevicePCIAddress) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
for _, attr := range start.Attr {
if attr.Name.Local == "domain" {
if err := unmarshalUintAttr(attr.Value, &a.Domain, 0); err != nil {
return err
}
} else if attr.Name.Local == "bus" {
if err := unmarshalUintAttr(attr.Value, &a.Bus, 0); err != nil {
return err
}
} else if attr.Name.Local == "slot" {
if err := unmarshalUintAttr(attr.Value, &a.Slot, 0); err != nil {
return err
}
} else if attr.Name.Local == "function" {
if err := unmarshalUintAttr(attr.Value, &a.Function, 0); err != nil {
return err
}
}
}
d.Skip()
return nil
}
func (c *NodeDeviceCCWCapability) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
e.EncodeToken(start)
if c.CSSID != nil {
cssid := xml.StartElement{
Name: xml.Name{Local: "cssid"},
}
e.EncodeToken(cssid)
e.EncodeToken(xml.CharData(fmt.Sprintf("0x%x", *c.CSSID)))
e.EncodeToken(cssid.End())
}
if c.SSID != nil {
ssid := xml.StartElement{
Name: xml.Name{Local: "ssid"},
}
e.EncodeToken(ssid)
e.EncodeToken(xml.CharData(fmt.Sprintf("0x%x", *c.SSID)))
e.EncodeToken(ssid.End())
}
if c.DevNo != nil {
devno := xml.StartElement{
Name: xml.Name{Local: "devno"},
}
e.EncodeToken(devno)
e.EncodeToken(xml.CharData(fmt.Sprintf("0x%04x", *c.DevNo)))
e.EncodeToken(devno.End())
}
e.EncodeToken(start.End())
return nil
}
func (c *NodeDeviceCCWCapability) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
for {
tok, err := d.Token()
if err == io.EOF {
break
}
if err != nil {
return err
}
switch tok := tok.(type) {
case xml.StartElement:
cdata, err := d.Token()
if err != nil {
return err
}
if tok.Name.Local != "cssid" &&
tok.Name.Local != "ssid" &&
tok.Name.Local != "devno" {
continue
}
chardata, ok := cdata.(xml.CharData)
if !ok {
return fmt.Errorf("Expected text for CCW '%s'", tok.Name.Local)
}
valstr := strings.TrimPrefix(string(chardata), "0x")
val, err := strconv.ParseUint(valstr, 16, 64)
if err != nil {
return err
}
vali := uint(val)
if tok.Name.Local == "cssid" {
c.CSSID = &vali
} else if tok.Name.Local == "ssid" {
c.SSID = &vali
} else if tok.Name.Local == "devno" {
c.DevNo = &vali
}
}
}
return nil
}
func (c *NodeDevicePCISubCapability) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
typ, ok := getAttr(start.Attr, "type")
if !ok {
return fmt.Errorf("Missing node device capability type")
}
switch typ {
case "virt_functions":
var virtFuncCaps NodeDevicePCIVirtFunctionsCapability
if err := d.DecodeElement(&virtFuncCaps, &start); err != nil {
return err
}
c.VirtFunctions = &virtFuncCaps
case "phys_function":
var physFuncCaps NodeDevicePCIPhysFunctionCapability
if err := d.DecodeElement(&physFuncCaps, &start); err != nil {
return err
}
c.PhysFunction = &physFuncCaps
case "mdev_types":
var mdevTypeCaps NodeDevicePCIMDevTypesCapability
if err := d.DecodeElement(&mdevTypeCaps, &start); err != nil {
return err
}
c.MDevTypes = &mdevTypeCaps
case "pci-bridge":
var bridgeCaps NodeDevicePCIBridgeCapability
if err := d.DecodeElement(&bridgeCaps, &start); err != nil {
return err
}
c.Bridge = &bridgeCaps
}
d.Skip()
return nil
}
func (c *NodeDevicePCISubCapability) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
if c.VirtFunctions != nil {
start.Attr = append(start.Attr, xml.Attr{
xml.Name{Local: "type"}, "virt_functions",
})
return e.EncodeElement(c.VirtFunctions, start)
} else if c.PhysFunction != nil {
start.Attr = append(start.Attr, xml.Attr{
xml.Name{Local: "type"}, "phys_function",
})
return e.EncodeElement(c.PhysFunction, start)
} else if c.MDevTypes != nil {
start.Attr = append(start.Attr, xml.Attr{
xml.Name{Local: "type"}, "mdev_types",
})
return e.EncodeElement(c.MDevTypes, start)
} else if c.Bridge != nil {
start.Attr = append(start.Attr, xml.Attr{
xml.Name{Local: "type"}, "pci-bridge",
})
return e.EncodeElement(c.Bridge, start)
}
return nil
}
func (c *NodeDeviceSCSITargetSubCapability) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
typ, ok := getAttr(start.Attr, "type")
if !ok {
return fmt.Errorf("Missing node device capability type")
}
switch typ {
case "fc_remote_port":
var fcCaps NodeDeviceSCSIFCRemotePortCapability
if err := d.DecodeElement(&fcCaps, &start); err != nil {
return err
}
c.FCRemotePort = &fcCaps
}
d.Skip()
return nil
}
func (c *NodeDeviceSCSITargetSubCapability) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
if c.FCRemotePort != nil {
start.Attr = append(start.Attr, xml.Attr{
xml.Name{Local: "type"}, "fc_remote_port",
})
return e.EncodeElement(c.FCRemotePort, start)
}
return nil
}
func (c *NodeDeviceSCSIHostSubCapability) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
typ, ok := getAttr(start.Attr, "type")
if !ok {
return fmt.Errorf("Missing node device capability type")
}
switch typ {
case "fc_host":
var fcCaps NodeDeviceSCSIFCHostCapability
if err := d.DecodeElement(&fcCaps, &start); err != nil {
return err
}
c.FCHost = &fcCaps
case "vport_ops":
var vportCaps NodeDeviceSCSIVPortOpsCapability
if err := d.DecodeElement(&vportCaps, &start); err != nil {
return err
}
c.VPortOps = &vportCaps
}
d.Skip()
return nil
}
func (c *NodeDeviceSCSIHostSubCapability) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
if c.FCHost != nil {
start.Attr = append(start.Attr, xml.Attr{
xml.Name{Local: "type"}, "fc_host",
})
return e.EncodeElement(c.FCHost, start)
} else if c.VPortOps != nil {
start.Attr = append(start.Attr, xml.Attr{
xml.Name{Local: "type"}, "vport_ops",
})
return e.EncodeElement(c.VPortOps, start)
}
return nil
}
func (c *NodeDeviceStorageSubCapability) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
typ, ok := getAttr(start.Attr, "type")
if !ok {
return fmt.Errorf("Missing node device capability type")
}
switch typ {
case "removable":
var removeCaps NodeDeviceStorageRemovableCapability
if err := d.DecodeElement(&removeCaps, &start); err != nil {
return err
}
c.Removable = &removeCaps
}
d.Skip()
return nil
}
func (c *NodeDeviceStorageSubCapability) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
if c.Removable != nil {
start.Attr = append(start.Attr, xml.Attr{
xml.Name{Local: "type"}, "removable",
})
return e.EncodeElement(c.Removable, start)
}
return nil
}
func (c *NodeDeviceNetSubCapability) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
typ, ok := getAttr(start.Attr, "type")
if !ok {
return fmt.Errorf("Missing node device capability type")
}
switch typ {
case "80211":
var wlanCaps NodeDeviceNet80211Capability
if err := d.DecodeElement(&wlanCaps, &start); err != nil {
return err
}
c.Wireless80211 = &wlanCaps
case "80203":
var ethCaps NodeDeviceNet80203Capability
if err := d.DecodeElement(&ethCaps, &start); err != nil {
return err
}
c.Ethernet80203 = &ethCaps
}
d.Skip()
return nil
}
func (c *NodeDeviceNetSubCapability) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
if c.Wireless80211 != nil {
start.Attr = append(start.Attr, xml.Attr{
xml.Name{Local: "type"}, "80211",
})
return e.EncodeElement(c.Wireless80211, start)
} else if c.Ethernet80203 != nil {
start.Attr = append(start.Attr, xml.Attr{
xml.Name{Local: "type"}, "80203",
})
return e.EncodeElement(c.Ethernet80203, start)
}
return nil
}
func (c *NodeDeviceCapability) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
typ, ok := getAttr(start.Attr, "type")
if !ok {
return fmt.Errorf("Missing node device capability type")
}
switch typ {
case "pci":
var pciCaps NodeDevicePCICapability
if err := d.DecodeElement(&pciCaps, &start); err != nil {
return err
}
c.PCI = &pciCaps
case "system":
var systemCaps NodeDeviceSystemCapability
if err := d.DecodeElement(&systemCaps, &start); err != nil {
return err
}
c.System = &systemCaps
case "usb_device":
var usbdevCaps NodeDeviceUSBDeviceCapability
if err := d.DecodeElement(&usbdevCaps, &start); err != nil {
return err
}
c.USBDevice = &usbdevCaps
case "usb":
var usbCaps NodeDeviceUSBCapability
if err := d.DecodeElement(&usbCaps, &start); err != nil {
return err
}
c.USB = &usbCaps
case "net":
var netCaps NodeDeviceNetCapability
if err := d.DecodeElement(&netCaps, &start); err != nil {
return err
}
c.Net = &netCaps
case "scsi_host":
var scsiHostCaps NodeDeviceSCSIHostCapability
if err := d.DecodeElement(&scsiHostCaps, &start); err != nil {
return err
}
c.SCSIHost = &scsiHostCaps
case "scsi_target":
var scsiTargetCaps NodeDeviceSCSITargetCapability
if err := d.DecodeElement(&scsiTargetCaps, &start); err != nil {
return err
}
c.SCSITarget = &scsiTargetCaps
case "scsi":
var scsiCaps NodeDeviceSCSICapability
if err := d.DecodeElement(&scsiCaps, &start); err != nil {
return err
}
c.SCSI = &scsiCaps
case "storage":
var storageCaps NodeDeviceStorageCapability
if err := d.DecodeElement(&storageCaps, &start); err != nil {
return err
}
c.Storage = &storageCaps
case "drm":
var drmCaps NodeDeviceDRMCapability
if err := d.DecodeElement(&drmCaps, &start); err != nil {
return err
}
c.DRM = &drmCaps
case "ccw":
var ccwCaps NodeDeviceCCWCapability
if err := d.DecodeElement(&ccwCaps, &start); err != nil {
return err
}
c.CCW = &ccwCaps
case "mdev":
var mdevCaps NodeDeviceMDevCapability
if err := d.DecodeElement(&mdevCaps, &start); err != nil {
return err
}
c.MDev = &mdevCaps
}
d.Skip()
return nil
}
func (c *NodeDeviceCapability) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
if c.PCI != nil {
start.Attr = append(start.Attr, xml.Attr{
xml.Name{Local: "type"}, "pci",
})
return e.EncodeElement(c.PCI, start)
} else if c.System != nil {
start.Attr = append(start.Attr, xml.Attr{
xml.Name{Local: "type"}, "system",
})
return e.EncodeElement(c.System, start)
} else if c.USB != nil {
start.Attr = append(start.Attr, xml.Attr{
xml.Name{Local: "type"}, "usb",
})
return e.EncodeElement(c.USB, start)
} else if c.USBDevice != nil {
start.Attr = append(start.Attr, xml.Attr{
xml.Name{Local: "type"}, "usb_device",
})
return e.EncodeElement(c.USBDevice, start)
} else if c.Net != nil {
start.Attr = append(start.Attr, xml.Attr{
xml.Name{Local: "type"}, "net",
})
return e.EncodeElement(c.Net, start)
} else if c.SCSI != nil {
start.Attr = append(start.Attr, xml.Attr{
xml.Name{Local: "type"}, "scsi",
})
return e.EncodeElement(c.SCSI, start)
} else if c.SCSIHost != nil {
start.Attr = append(start.Attr, xml.Attr{
xml.Name{Local: "type"}, "scsi_host",
})
return e.EncodeElement(c.SCSIHost, start)
} else if c.SCSITarget != nil {
start.Attr = append(start.Attr, xml.Attr{
xml.Name{Local: "type"}, "scsi_target",
})
return e.EncodeElement(c.SCSITarget, start)
} else if c.Storage != nil {
start.Attr = append(start.Attr, xml.Attr{
xml.Name{Local: "type"}, "storage",
})
return e.EncodeElement(c.Storage, start)
} else if c.DRM != nil {
start.Attr = append(start.Attr, xml.Attr{
xml.Name{Local: "type"}, "drm",
})
return e.EncodeElement(c.DRM, start)
} else if c.CCW != nil {
start.Attr = append(start.Attr, xml.Attr{
xml.Name{Local: "type"}, "ccw",
})
return e.EncodeElement(c.CCW, start)
} else if c.MDev != nil {
start.Attr = append(start.Attr, xml.Attr{
xml.Name{Local: "type"}, "mdev",
})
return e.EncodeElement(c.MDev, start)
}
return nil
}
func (c *NodeDevice) Unmarshal(doc string) error {
return xml.Unmarshal([]byte(doc), c)
}
func (c *NodeDevice) Marshal() (string, error) {
doc, err := xml.MarshalIndent(c, "", " ")
if err != nil {
return "", err
}
return string(doc), nil
}

514
vendor/github.com/libvirt/libvirt-go-xml/nwfilter.go generated vendored Normal file
View File

@@ -0,0 +1,514 @@
/*
* This file is part of the libvirt-go-xml project
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* Copyright (C) 2017 Lian Duan <blazeblue@gmail.com>
*
*/
package libvirtxml
import (
"encoding/xml"
"fmt"
"io"
"strconv"
"strings"
)
type NWFilter struct {
XMLName xml.Name `xml:"filter"`
Name string `xml:"name,attr"`
UUID string `xml:"uuid,omitempty"`
Chain string `xml:"chain,attr,omitempty"`
Priority int `xml:"priority,attr,omitempty"`
Entries []NWFilterEntry
}
type NWFilterEntry struct {
Rule *NWFilterRule
Ref *NWFilterRef
}
type NWFilterRef struct {
Filter string `xml:"filter,attr"`
Parameters []NWFilterParameter `xml:"parameter"`
}
type NWFilterParameter struct {
Name string `xml:"name,attr"`
Value string `xml:"value,attr"`
}
type NWFilterField struct {
Var string
Str string
Uint *uint
}
type NWFilterRule struct {
Action string `xml:"action,attr,omitempty"`
Direction string `xml:"direction,attr,omitempty"`
Priority int `xml:"priority,attr,omitempty"`
StateMatch string `xml:"statematch,attr,omitempty"`
ARP *NWFilterRuleARP `xml:"arp"`
RARP *NWFilterRuleRARP `xml:"rarp"`
MAC *NWFilterRuleMAC `xml:"mac"`
VLAN *NWFilterRuleVLAN `xml:"vlan"`
STP *NWFilterRuleSTP `xml:"stp"`
IP *NWFilterRuleIP `xml:"ip"`
IPv6 *NWFilterRuleIPv6 `xml:"ipv6"`
TCP *NWFilterRuleTCP `xml:"tcp"`
UDP *NWFilterRuleUDP `xml:"udp"`
UDPLite *NWFilterRuleUDPLite `xml:"udplite"`
ESP *NWFilterRuleESP `xml:"esp"`
AH *NWFilterRuleAH `xml:"ah"`
SCTP *NWFilterRuleSCTP `xml:"sctp"`
ICMP *NWFilterRuleICMP `xml:"icmp"`
All *NWFilterRuleAll `xml:"all"`
IGMP *NWFilterRuleIGMP `xml:"igmp"`
TCPIPv6 *NWFilterRuleTCPIPv6 `xml:"tcp-ipv6"`
UDPIPv6 *NWFilterRuleUDPIPv6 `xml:"udp-ipv6"`
UDPLiteIPv6 *NWFilterRuleUDPLiteIPv6 `xml:"udplite-ipv6"`
ESPIPv6 *NWFilterRuleESPIPv6 `xml:"esp-ipv6"`
AHIPv6 *NWFilterRuleAHIPv6 `xml:"ah-ipv6"`
SCTPIPv6 *NWFilterRuleSCTPIPv6 `xml:"sctp-ipv6"`
ICMPv6 *NWFilterRuleICMPIPv6 `xml:"icmpv6"`
AllIPv6 *NWFilterRuleAllIPv6 `xml:"all-ipv6"`
}
type NWFilterRuleCommonMAC struct {
SrcMACAddr NWFilterField `xml:"srcmacaddr,attr,omitempty"`
SrcMACMask NWFilterField `xml:"srcmacmask,attr,omitempty"`
DstMACAddr NWFilterField `xml:"dstmacaddr,attr,omitempty"`
DstMACMask NWFilterField `xml:"dstmacmask,attr,omitempty"`
}
type NWFilterRuleCommonIP struct {
SrcMACAddr NWFilterField `xml:"srcmacaddr,attr,omitempty"`
SrcIPAddr NWFilterField `xml:"srcipaddr,attr,omitempty"`
SrcIPMask NWFilterField `xml:"srcipmask,attr,omitempty"`
DstIPAddr NWFilterField `xml:"dstipaddr,attr,omitempty"`
DstIPMask NWFilterField `xml:"dstipmask,attr,omitempty"`
SrcIPFrom NWFilterField `xml:"srcipfrom,attr,omitempty"`
SrcIPTo NWFilterField `xml:"srcipto,attr,omitempty"`
DstIPFrom NWFilterField `xml:"dstipfrom,attr,omitempty"`
DstIPTo NWFilterField `xml:"dstipto,attr,omitempty"`
DSCP NWFilterField `xml:"dscp,attr"`
ConnLimitAbove NWFilterField `xml:"connlimit-above,attr"`
State NWFilterField `xml:"state,attr,omitempty"`
IPSet NWFilterField `xml:"ipset,attr,omitempty"`
IPSetFlags NWFilterField `xml:"ipsetflags,attr,omitempty"`
}
type NWFilterRuleCommonPort struct {
SrcPortStart NWFilterField `xml:"srcportstart,attr"`
SrcPortEnd NWFilterField `xml:"srcportend,attr"`
DstPortStart NWFilterField `xml:"dstportstart,attr"`
DstPortEnd NWFilterField `xml:"dstportend,attr"`
}
type NWFilterRuleARP struct {
Match string `xml:"match,attr,omitempty"`
NWFilterRuleCommonMAC
HWType NWFilterField `xml:"hwtype,attr"`
ProtocolType NWFilterField `xml:"protocoltype,attr"`
OpCode NWFilterField `xml:"opcode,attr,omitempty"`
ARPSrcMACAddr NWFilterField `xml:"arpsrcmacaddr,attr,omitempty"`
ARPDstMACAddr NWFilterField `xml:"arpdstmacaddr,attr,omitempty"`
ARPSrcIPAddr NWFilterField `xml:"arpsrcipaddr,attr,omitempty"`
ARPSrcIPMask NWFilterField `xml:"arpsrcipmask,attr,omitempty"`
ARPDstIPAddr NWFilterField `xml:"arpdstipaddr,attr,omitempty"`
ARPDstIPMask NWFilterField `xml:"arpdstipmask,attr,omitempty"`
Gratuitous NWFilterField `xml:"gratuitous,attr,omitempty"`
Comment string `xml:"comment,attr,omitempty"`
}
type NWFilterRuleRARP struct {
Match string `xml:"match,attr,omitempty"`
NWFilterRuleCommonMAC
HWType NWFilterField `xml:"hwtype,attr"`
ProtocolType NWFilterField `xml:"protocoltype,attr"`
OpCode NWFilterField `xml:"opcode,attr,omitempty"`
ARPSrcMACAddr NWFilterField `xml:"arpsrcmacaddr,attr,omitempty"`
ARPDstMACAddr NWFilterField `xml:"arpdstmacaddr,attr,omitempty"`
ARPSrcIPAddr NWFilterField `xml:"arpsrcipaddr,attr,omitempty"`
ARPSrcIPMask NWFilterField `xml:"arpsrcipmask,attr,omitempty"`
ARPDstIPAddr NWFilterField `xml:"arpdstipaddr,attr,omitempty"`
ARPDstIPMask NWFilterField `xml:"arpdstipmask,attr,omitempty"`
Gratuitous NWFilterField `xml:"gratuitous,attr,omitempty"`
Comment string `xml:"comment,attr,omitempty"`
}
type NWFilterRuleMAC struct {
Match string `xml:"match,attr,omitempty"`
NWFilterRuleCommonMAC
ProtocolID NWFilterField `xml:"protocolid,attr,omitempty"`
Comment string `xml:"comment,attr,omitempty"`
}
type NWFilterRuleVLAN struct {
Match string `xml:"match,attr,omitempty"`
NWFilterRuleCommonMAC
VLANID NWFilterField `xml:"vlanid,attr,omitempty"`
EncapProtocol NWFilterField `xml:"encap-protocol,attr,omitempty"`
Comment string `xml:"comment,attr,omitempty"`
}
type NWFilterRuleSTP struct {
Match NWFilterField `xml:"match,attr,omitempty"`
SrcMACAddr NWFilterField `xml:"srcmacaddr,attr,omitempty"`
SrcMACMask NWFilterField `xml:"srcmacmask,attr,omitempty"`
Type NWFilterField `xml:"type,attr"`
Flags NWFilterField `xml:"flags,attr"`
RootPriority NWFilterField `xml:"root-priority,attr"`
RootPriorityHi NWFilterField `xml:"root-priority-hi,attr"`
RootAddress NWFilterField `xml:"root-address,attr,omitempty"`
RootAddressMask NWFilterField `xml:"root-address-mask,attr,omitempty"`
RootCost NWFilterField `xml:"root-cost,attr"`
RootCostHi NWFilterField `xml:"root-cost-hi,attr"`
SenderPriority NWFilterField `xml:"sender-priority,attr"`
SenderPriorityHi NWFilterField `xml:"sender-priority-hi,attr"`
SenderAddress NWFilterField `xml:"sender-address,attr,omitempty"`
SenderAddressMask NWFilterField `xml:"sender-address-mask,attr,omitempty"`
Port NWFilterField `xml:"port,attr"`
PortHi NWFilterField `xml:"port-hi,attr"`
Age NWFilterField `xml:"age,attr"`
AgeHi NWFilterField `xml:"age-hi,attr"`
MaxAge NWFilterField `xml:"max-age,attr"`
MaxAgeHi NWFilterField `xml:"max-age-hi,attr"`
HelloTime NWFilterField `xml:"hello-time,attr"`
HelloTimeHi NWFilterField `xml:"hello-time-hi,attr"`
ForwardDelay NWFilterField `xml:"forward-delay,attr"`
ForwardDelayHi NWFilterField `xml:"forward-delay-hi,attr"`
Comment string `xml:"comment,attr,omitempty"`
}
type NWFilterRuleIP struct {
Match string `xml:"match,attr,omitempty"`
NWFilterRuleCommonMAC
SrcIPAddr NWFilterField `xml:"srcipaddr,attr,omitempty"`
SrcIPMask NWFilterField `xml:"srcipmask,attr,omitempty"`
DstIPAddr NWFilterField `xml:"dstipaddr,attr,omitempty"`
DstIPMask NWFilterField `xml:"dstipmask,attr,omitempty"`
Protocol NWFilterField `xml:"protocol,attr,omitempty"`
NWFilterRuleCommonPort
DSCP NWFilterField `xml:"dscp,attr"`
Comment string `xml:"comment,attr,omitempty"`
}
type NWFilterRuleIPv6 struct {
Match string `xml:"match,attr,omitempty"`
NWFilterRuleCommonMAC
SrcIPAddr NWFilterField `xml:"srcipaddr,attr,omitempty"`
SrcIPMask NWFilterField `xml:"srcipmask,attr,omitempty"`
DstIPAddr NWFilterField `xml:"dstipaddr,attr,omitempty"`
DstIPMask NWFilterField `xml:"dstipmask,attr,omitempty"`
Protocol NWFilterField `xml:"protocol,attr,omitempty"`
NWFilterRuleCommonPort
Type NWFilterField `xml:"type,attr"`
TypeEnd NWFilterField `xml:"typeend,attr"`
Code NWFilterField `xml:"code,attr"`
CodeEnd NWFilterField `xml:"codeend,attr"`
Comment string `xml:"comment,attr,omitempty"`
}
type NWFilterRuleTCP struct {
Match string `xml:"match,attr,omitempty"`
NWFilterRuleCommonIP
NWFilterRuleCommonPort
Option NWFilterField `xml:"option,attr"`
Flags NWFilterField `xml:"flags,attr,omitempty"`
Comment string `xml:"comment,attr,omitempty"`
}
type NWFilterRuleUDP struct {
Match string `xml:"match,attr,omitempty"`
NWFilterRuleCommonIP
NWFilterRuleCommonPort
Comment string `xml:"comment,attr,omitempty"`
}
type NWFilterRuleUDPLite struct {
Match string `xml:"match,attr,omitempty"`
NWFilterRuleCommonIP
Comment string `xml:"comment,attr,omitempty"`
}
type NWFilterRuleESP struct {
Match string `xml:"match,attr,omitempty"`
NWFilterRuleCommonIP
Comment string `xml:"comment,attr,omitempty"`
}
type NWFilterRuleAH struct {
Match string `xml:"match,attr,omitempty"`
NWFilterRuleCommonIP
Comment string `xml:"comment,attr,omitempty"`
}
type NWFilterRuleSCTP struct {
Match string `xml:"match,attr,omitempty"`
NWFilterRuleCommonIP
NWFilterRuleCommonPort
Comment string `xml:"comment,attr,omitempty"`
}
type NWFilterRuleICMP struct {
Match string `xml:"match,attr,omitempty"`
NWFilterRuleCommonIP
Type NWFilterField `xml:"type,attr"`
Code NWFilterField `xml:"code,attr"`
Comment string `xml:"comment,attr,omitempty"`
}
type NWFilterRuleAll struct {
Match string `xml:"match,attr,omitempty"`
NWFilterRuleCommonIP
Comment string `xml:"comment,attr,omitempty"`
}
type NWFilterRuleIGMP struct {
Match string `xml:"match,attr,omitempty"`
NWFilterRuleCommonIP
Comment string `xml:"comment,attr,omitempty"`
}
type NWFilterRuleTCPIPv6 struct {
Match string `xml:"match,attr,omitempty"`
NWFilterRuleCommonIP
NWFilterRuleCommonPort
Option NWFilterField `xml:"option,attr"`
Comment string `xml:"comment,attr,omitempty"`
}
type NWFilterRuleUDPIPv6 struct {
Match string `xml:"match,attr,omitempty"`
NWFilterRuleCommonIP
NWFilterRuleCommonPort
Comment string `xml:"comment,attr,omitempty"`
}
type NWFilterRuleUDPLiteIPv6 struct {
Match string `xml:"match,attr,omitempty"`
NWFilterRuleCommonIP
Comment string `xml:"comment,attr,omitempty"`
}
type NWFilterRuleESPIPv6 struct {
Match string `xml:"match,attr,omitempty"`
NWFilterRuleCommonIP
Comment string `xml:"comment,attr,omitempty"`
}
type NWFilterRuleAHIPv6 struct {
Match string `xml:"match,attr,omitempty"`
NWFilterRuleCommonIP
Comment string `xml:"comment,attr,omitempty"`
}
type NWFilterRuleSCTPIPv6 struct {
Match string `xml:"match,attr,omitempty"`
NWFilterRuleCommonIP
NWFilterRuleCommonPort
Comment string `xml:"comment,attr,omitempty"`
}
type NWFilterRuleICMPIPv6 struct {
Match string `xml:"match,attr,omitempty"`
NWFilterRuleCommonIP
Type NWFilterField `xml:"type,attr"`
Code NWFilterField `xml:"code,attr"`
Comment string `xml:"comment,attr,omitempty"`
}
type NWFilterRuleAllIPv6 struct {
Match string `xml:"match,attr,omitempty"`
NWFilterRuleCommonIP
Comment string `xml:"comment,attr,omitempty"`
}
func (s *NWFilterField) MarshalXMLAttr(name xml.Name) (xml.Attr, error) {
if s == nil {
return xml.Attr{}, nil
}
if s.Str != "" {
return xml.Attr{
Name: name,
Value: s.Str,
}, nil
} else if s.Var != "" {
return xml.Attr{
Name: name,
Value: "$" + s.Str,
}, nil
} else if s.Uint != nil {
return xml.Attr{
Name: name,
Value: fmt.Sprintf("0x%x", *s.Uint),
}, nil
} else {
return xml.Attr{}, nil
}
}
func (s *NWFilterField) UnmarshalXMLAttr(attr xml.Attr) error {
if attr.Value == "" {
return nil
}
if attr.Value[0] == '$' {
s.Var = attr.Value[1:]
}
if strings.HasPrefix(attr.Value, "0x") {
val, err := strconv.ParseUint(attr.Value[2:], 16, 64)
if err != nil {
return err
}
uval := uint(val)
s.Uint = &uval
}
s.Str = attr.Value
return nil
}
func (a *NWFilter) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
start.Name.Local = "filter"
start.Attr = append(start.Attr, xml.Attr{
Name: xml.Name{Local: "name"},
Value: a.Name,
})
if a.Chain != "" {
start.Attr = append(start.Attr, xml.Attr{
Name: xml.Name{Local: "chain"},
Value: a.Chain,
})
}
if a.Priority != 0 {
start.Attr = append(start.Attr, xml.Attr{
Name: xml.Name{Local: "priority"},
Value: fmt.Sprintf("%d", a.Priority),
})
}
err := e.EncodeToken(start)
if err != nil {
return err
}
if a.UUID != "" {
uuid := xml.StartElement{
Name: xml.Name{Local: "uuid"},
}
e.EncodeToken(uuid)
e.EncodeToken(xml.CharData(a.UUID))
e.EncodeToken(uuid.End())
}
for _, entry := range a.Entries {
if entry.Rule != nil {
rule := xml.StartElement{
Name: xml.Name{Local: "rule"},
}
e.EncodeElement(entry.Rule, rule)
} else if entry.Ref != nil {
ref := xml.StartElement{
Name: xml.Name{Local: "filterref"},
}
e.EncodeElement(entry.Ref, ref)
}
}
err = e.EncodeToken(start.End())
if err != nil {
return err
}
return nil
}
func (a *NWFilter) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
name, ok := getAttr(start.Attr, "name")
if !ok {
return fmt.Errorf("Missing filter name")
}
a.Name = name
a.Chain, _ = getAttr(start.Attr, "chain")
prio, ok := getAttr(start.Attr, "priority")
if ok {
val, err := strconv.ParseInt(prio, 10, 64)
if err != nil {
return err
}
a.Priority = int(val)
}
for {
tok, err := d.Token()
if err == io.EOF {
break
}
switch tok := tok.(type) {
case xml.StartElement:
{
if tok.Name.Local == "uuid" {
txt, err := d.Token()
if err != nil {
return err
}
txt2, ok := txt.(xml.CharData)
if !ok {
return fmt.Errorf("Expected UUID string")
}
a.UUID = string(txt2)
} else if tok.Name.Local == "rule" {
entry := NWFilterEntry{
Rule: &NWFilterRule{},
}
d.DecodeElement(entry.Rule, &tok)
a.Entries = append(a.Entries, entry)
} else if tok.Name.Local == "filterref" {
entry := NWFilterEntry{
Ref: &NWFilterRef{},
}
d.DecodeElement(entry.Ref, &tok)
a.Entries = append(a.Entries, entry)
}
}
}
}
return nil
}
func (s *NWFilter) Unmarshal(doc string) error {
return xml.Unmarshal([]byte(doc), s)
}
func (s *NWFilter) Marshal() (string, error) {
doc, err := xml.MarshalIndent(s, "", " ")
if err != nil {
return "", err
}
return string(doc), nil
}

58
vendor/github.com/libvirt/libvirt-go-xml/secret.go generated vendored Normal file
View File

@@ -0,0 +1,58 @@
/*
* This file is part of the libvirt-go-xml project
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* Copyright (C) 2016 Red Hat, Inc.
*
*/
package libvirtxml
import (
"encoding/xml"
)
type SecretUsage struct {
Type string `xml:"type,attr"`
Volume string `xml:"volume,omitempty"`
Name string `xml:"name,omitempty"`
Target string `xml:"target,omitempty"`
}
type Secret struct {
XMLName xml.Name `xml:"secret"`
Ephemeral string `xml:"ephemeral,attr,omitempty"`
Private string `xml:"private,attr,omitempty"`
Description string `xml:"description,omitempty"`
UUID string `xml:"uuid,omitempty"`
Usage *SecretUsage `xml:"usage"`
}
func (s *Secret) Unmarshal(doc string) error {
return xml.Unmarshal([]byte(doc), s)
}
func (s *Secret) Marshal() (string, error) {
doc, err := xml.MarshalIndent(s, "", " ")
if err != nil {
return "", err
}
return string(doc), nil
}

View File

@@ -0,0 +1,50 @@
/*
* This file is part of the libvirt-go-xml project
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* Copyright (C) 2017 Red Hat, Inc.
*
*/
package libvirtxml
type StorageEncryptionSecret struct {
Type string `xml:"type,attr"`
UUID string `xml:"uuid,attr"`
}
type StorageEncryptionCipher struct {
Name string `xml:"name,attr"`
Size uint64 `xml:"size,attr"`
Mode string `xml:"mode,attr"`
Hash string `xml:"hash,attr"`
}
type StorageEncryptionIvgen struct {
Name string `xml:"name,attr"`
Hash string `xml:"hash,attr"`
}
type StorageEncryption struct {
Format string `xml:"format,attr"`
Secret *StorageEncryptionSecret `xml:"secret"`
Cipher *StorageEncryptionCipher `xml:"cipher"`
Ivgen *StorageEncryptionIvgen `xml:"ivgen"`
}

View File

@@ -0,0 +1,234 @@
/*
* This file is part of the libvirt-go-xml project
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* Copyright (C) 2017 Red Hat, Inc.
*
*/
package libvirtxml
import "encoding/xml"
type StoragePoolSize struct {
Unit string `xml:"unit,attr,omitempty"`
Value uint64 `xml:",chardata"`
}
type StoragePoolTargetPermissions struct {
Owner string `xml:"owner,omitempty"`
Group string `xml:"group,omitempty"`
Mode string `xml:"mode,omitempty"`
Label string `xml:"label,omitempty"`
}
type StoragePoolTargetTimestamps struct {
Atime string `xml:"atime"`
Mtime string `xml:"mtime"`
Ctime string `xml:"ctime"`
}
type StoragePoolTarget struct {
Path string `xml:"path,omitempty"`
Permissions *StoragePoolTargetPermissions `xml:"permissions"`
Timestamps *StoragePoolTargetTimestamps `xml:"timestamps"`
Encryption *StorageEncryption `xml:"encryption"`
}
type StoragePoolSourceFormat struct {
Type string `xml:"type,attr"`
}
type StoragePoolSourceProtocol struct {
Version string `xml:"ver,attr"`
}
type StoragePoolSourceHost struct {
Name string `xml:"name,attr"`
Port string `xml:"port,attr,omitempty"`
}
type StoragePoolSourceDevice struct {
Path string `xml:"path,attr"`
PartSeparator string `xml:"part_separator,attr,omitempty"`
FreeExtents []StoragePoolSourceDeviceFreeExtent `xml:"freeExtent"`
}
type StoragePoolSourceDeviceFreeExtent struct {
Start uint64 `xml:"start,attr"`
End uint64 `xml:"end,attr"`
}
type StoragePoolSourceAuthSecret struct {
Usage string `xml:"usage,attr,omitempty"`
UUID string `xml:"uuid,attr,omitempty"`
}
type StoragePoolSourceAuth struct {
Type string `xml:"type,attr"`
Username string `xml:"username,attr"`
Secret *StoragePoolSourceAuthSecret `xml:"secret"`
}
type StoragePoolSourceVendor struct {
Name string `xml:"name,attr"`
}
type StoragePoolSourceProduct struct {
Name string `xml:"name,attr"`
}
type StoragePoolPCIAddress struct {
Domain *uint `xml:"domain,attr"`
Bus *uint `xml:"bus,attr"`
Slot *uint `xml:"slot,attr"`
Function *uint `xml:"function,attr"`
}
type StoragePoolSourceAdapterParentAddr struct {
UniqueID uint64 `xml:"unique_id,attr"`
Address *StoragePoolPCIAddress `xml:"address"`
}
type StoragePoolSourceAdapter struct {
Type string `xml:"type,attr,omitempty"`
Name string `xml:"name,attr,omitempty"`
Parent string `xml:"parent,attr,omitempty"`
Managed string `xml:"managed,attr,omitempty"`
WWNN string `xml:"wwnn,attr,omitempty"`
WWPN string `xml:"wwpn,attr,omitempty"`
ParentAddr *StoragePoolSourceAdapterParentAddr `xml:"parentaddr"`
}
type StoragePoolSourceDir struct {
Path string `xml:"path,attr"`
}
type StoragePoolSourceInitiator struct {
IQN StoragePoolSourceInitiatorIQN `xml:"iqn"`
}
type StoragePoolSourceInitiatorIQN struct {
Name string `xml:"name,attr,omitempty"`
}
type StoragePoolSource struct {
Name string `xml:"name,omitempty"`
Dir *StoragePoolSourceDir `xml:"dir"`
Host []StoragePoolSourceHost `xml:"host"`
Device []StoragePoolSourceDevice `xml:"device"`
Auth *StoragePoolSourceAuth `xml:"auth"`
Vendor *StoragePoolSourceVendor `xml:"vendor"`
Product *StoragePoolSourceProduct `xml:"product"`
Format *StoragePoolSourceFormat `xml:"format"`
Protocol *StoragePoolSourceProtocol `xml:"protocol"`
Adapter *StoragePoolSourceAdapter `xml:"adapter"`
Initiator *StoragePoolSourceInitiator `xml:"initiator"`
}
type StoragePoolRefreshVol struct {
Allocation string `xml:"allocation,attr"`
}
type StoragePoolRefresh struct {
Volume StoragePoolRefreshVol `xml:"volume"`
}
type StoragePool struct {
XMLName xml.Name `xml:"pool"`
Type string `xml:"type,attr"`
Name string `xml:"name,omitempty"`
UUID string `xml:"uuid,omitempty"`
Allocation *StoragePoolSize `xml:"allocation"`
Capacity *StoragePoolSize `xml:"capacity"`
Available *StoragePoolSize `xml:"available"`
Target *StoragePoolTarget `xml:"target"`
Source *StoragePoolSource `xml:"source"`
Refresh *StoragePoolRefresh `xml:"refresh"`
/* Pool backend namespcaes must be last */
FSCommandline *StoragePoolFSCommandline
RBDCommandline *StoragePoolRBDCommandline
}
type StoragePoolFSCommandlineOption struct {
Name string `xml:"name,attr"`
}
type StoragePoolFSCommandline struct {
XMLName xml.Name `xml:"http://libvirt.org/schemas/storagepool/fs/1.0 mount_opts"`
Options []StoragePoolFSCommandlineOption `xml:"option"`
}
type StoragePoolRBDCommandlineOption struct {
Name string `xml:"name,attr"`
Value string `xml:"value,attr"`
}
type StoragePoolRBDCommandline struct {
XMLName xml.Name `xml:"http://libvirt.org/schemas/storagepool/rbd/1.0 config_opts"`
Options []StoragePoolRBDCommandlineOption `xml:"option"`
}
func (a *StoragePoolPCIAddress) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
marshalUintAttr(&start, "domain", a.Domain, "0x%04x")
marshalUintAttr(&start, "bus", a.Bus, "0x%02x")
marshalUintAttr(&start, "slot", a.Slot, "0x%02x")
marshalUintAttr(&start, "function", a.Function, "0x%x")
e.EncodeToken(start)
e.EncodeToken(start.End())
return nil
}
func (a *StoragePoolPCIAddress) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
for _, attr := range start.Attr {
if attr.Name.Local == "domain" {
if err := unmarshalUintAttr(attr.Value, &a.Domain, 0); err != nil {
return err
}
} else if attr.Name.Local == "bus" {
if err := unmarshalUintAttr(attr.Value, &a.Bus, 0); err != nil {
return err
}
} else if attr.Name.Local == "slot" {
if err := unmarshalUintAttr(attr.Value, &a.Slot, 0); err != nil {
return err
}
} else if attr.Name.Local == "function" {
if err := unmarshalUintAttr(attr.Value, &a.Function, 0); err != nil {
return err
}
}
}
d.Skip()
return nil
}
func (s *StoragePool) Unmarshal(doc string) error {
return xml.Unmarshal([]byte(doc), s)
}
func (s *StoragePool) Marshal() (string, error) {
doc, err := xml.MarshalIndent(s, "", " ")
if err != nil {
return "", err
}
return string(doc), nil
}

View File

@@ -0,0 +1,95 @@
/*
* This file is part of the libvirt-go-xml project
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* Copyright (C) 2017 Red Hat, Inc.
*
*/
package libvirtxml
import "encoding/xml"
type StorageVolumeSize struct {
Unit string `xml:"unit,attr,omitempty"`
Value uint64 `xml:",chardata"`
}
type StorageVolumeTargetPermissions struct {
Owner string `xml:"owner,omitempty"`
Group string `xml:"group,omitempty"`
Mode string `xml:"mode,omitempty"`
Label string `xml:"label,omitempty"`
}
type StorageVolumeTargetFeature struct {
LazyRefcounts *struct{} `xml:"lazy_refcounts"`
}
type StorageVolumeTargetFormat struct {
Type string `xml:"type,attr"`
}
type StorageVolumeTargetTimestamps struct {
Atime string `xml:"atime"`
Mtime string `xml:"mtime"`
Ctime string `xml:"ctime"`
}
type StorageVolumeTarget struct {
Path string `xml:"path,omitempty"`
Format *StorageVolumeTargetFormat `xml:"format"`
Permissions *StorageVolumeTargetPermissions `xml:"permissions"`
Timestamps *StorageVolumeTargetTimestamps `xml:"timestamps"`
Compat string `xml:"compat,omitempty"`
NoCOW *struct{} `xml:"nocow"`
Features []StorageVolumeTargetFeature `xml:"features"`
Encryption *StorageEncryption `xml:"encryption"`
}
type StorageVolumeBackingStore struct {
Path string `xml:"path"`
Format *StorageVolumeTargetFormat `xml:"format"`
Permissions *StorageVolumeTargetPermissions `xml:"permissions"`
}
type StorageVolume struct {
XMLName xml.Name `xml:"volume"`
Type string `xml:"type,attr,omitempty"`
Name string `xml:"name"`
Key string `xml:"key,omitempty"`
Allocation *StorageVolumeSize `xml:"allocation"`
Capacity *StorageVolumeSize `xml:"capacity"`
Physical *StorageVolumeSize `xml:"physical"`
Target *StorageVolumeTarget `xml:"target"`
BackingStore *StorageVolumeBackingStore `xml:"backingStore"`
}
func (s *StorageVolume) Unmarshal(doc string) error {
return xml.Unmarshal([]byte(doc), s)
}
func (s *StorageVolume) Marshal() (string, error) {
doc, err := xml.MarshalIndent(s, "", " ")
if err != nil {
return "", err
}
return string(doc), nil
}

291
vendor/github.com/libvirt/libvirt-go-xml/xmlutil.go generated vendored Normal file
View File

@@ -0,0 +1,291 @@
/*
* This file is part of the libvirt-go-xml project
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* Copyright (C) 2017 Red Hat, Inc.
*
*/
package libvirtxml
import (
"encoding/xml"
"fmt"
"strconv"
"strings"
)
type element struct {
XMLNS string
Name string
Attrs map[string]string
Content string
Children []*element
}
type elementstack []*element
func (s *elementstack) push(v *element) {
*s = append(*s, v)
}
func (s *elementstack) pop() *element {
res := (*s)[len(*s)-1]
*s = (*s)[:len(*s)-1]
return res
}
func getNamespaceURI(xmlnsMap map[string]string, xmlns string, name xml.Name) string {
if name.Space != "" {
uri, ok := xmlnsMap[name.Space]
if !ok {
return "undefined://" + name.Space
} else {
return uri
}
} else {
return xmlns
}
}
func xmlName(xmlns string, name xml.Name) string {
if xmlns == "" {
return name.Local
}
return name.Local + "(" + xmlns + ")"
}
func loadXML(xmlstr string, ignoreNSDecl bool) (*element, error) {
xmlnsMap := make(map[string]string)
xmlr := strings.NewReader(xmlstr)
d := xml.NewDecoder(xmlr)
var root *element
stack := elementstack{}
for {
t, err := d.RawToken()
if err != nil {
return nil, err
}
var parent *element
if root != nil {
if len(stack) == 0 {
return nil, fmt.Errorf("Unexpectedly empty stack")
}
parent = stack[len(stack)-1]
}
switch t := t.(type) {
case xml.StartElement:
xmlns := ""
if parent != nil {
xmlns = parent.XMLNS
}
for _, a := range t.Attr {
if a.Name.Space == "xmlns" {
xmlnsMap[a.Name.Local] = a.Value
} else if a.Name.Space == "" && a.Name.Local == "xmlns" {
xmlns = a.Value
}
}
xmlns = getNamespaceURI(xmlnsMap, xmlns, t.Name)
child := &element{
XMLNS: xmlns,
Name: xmlName(xmlns, t.Name),
Attrs: make(map[string]string),
}
for _, a := range t.Attr {
if a.Name.Space == "xmlns" {
continue
}
if a.Name.Space == "" && a.Name.Local == "xmlns" {
continue
}
attrNS := getNamespaceURI(xmlnsMap, "", a.Name)
child.Attrs[xmlName(attrNS, a.Name)] = a.Value
}
stack.push(child)
if root == nil {
root = child
} else {
parent.Children = append(parent.Children, child)
parent.Content = ""
}
case xml.EndElement:
stack.pop()
case xml.CharData:
if parent != nil && len(parent.Children) == 0 {
val := string(t)
if strings.TrimSpace(val) != "" {
parent.Content = val
}
}
}
if root != nil && len(stack) == 0 {
break
}
}
return root, nil
}
func testCompareValue(filename, path, key, expected, actual string) error {
if expected == actual {
return nil
}
i1, err1 := strconv.ParseInt(expected, 0, 64)
i2, err2 := strconv.ParseInt(actual, 0, 64)
if err1 == nil && err2 == nil && i1 == i2 {
return nil
}
path = path + "/@" + key
return fmt.Errorf("%s: %s: attribute actual value '%s' does not match expected value '%s'",
filename, path, actual, expected)
}
func testCompareElement(filename, expectPath, actualPath string, expect, actual *element, extraExpectNodes, extraActualNodes map[string]bool) error {
if expect.Name != actual.Name {
return fmt.Errorf("%s: name '%s' doesn't match '%s'",
expectPath, expect.Name, actual.Name)
}
expectAttr := expect.Attrs
for key, val := range actual.Attrs {
expectval, ok := expectAttr[key]
if !ok {
attrPath := actualPath + "/@" + key
if _, ok := extraActualNodes[attrPath]; ok {
continue
}
return fmt.Errorf("%s: %s: attribute in actual XML missing in expected XML",
filename, attrPath)
}
err := testCompareValue(filename, actualPath, key, expectval, val)
if err != nil {
return err
}
delete(expectAttr, key)
}
for key, _ := range expectAttr {
attrPath := expectPath + "/@" + key
if _, ok := extraExpectNodes[attrPath]; ok {
continue
}
return fmt.Errorf("%s: %s: attribute '%s' in expected XML missing in actual XML",
filename, attrPath, expectAttr[key])
}
if expect.Content != actual.Content {
return fmt.Errorf("%s: %s: actual content '%s' does not match expected '%s'",
filename, actualPath, actual.Content, expect.Content)
}
used := make([]bool, len(actual.Children))
expectChildIndexes := make(map[string]uint)
actualChildIndexes := make(map[string]uint)
for _, expectChild := range expect.Children {
expectIndex, _ := expectChildIndexes[expectChild.Name]
expectChildIndexes[expectChild.Name] = expectIndex + 1
subExpectPath := fmt.Sprintf("%s/%s[%d]", expectPath, expectChild.Name, expectIndex)
var actualChild *element = nil
for i := 0; i < len(used); i++ {
if !used[i] && actual.Children[i].Name == expectChild.Name {
actualChild = actual.Children[i]
used[i] = true
break
}
}
if actualChild == nil {
if _, ok := extraExpectNodes[subExpectPath]; ok {
continue
}
return fmt.Errorf("%s: %s: element in expected XML missing in actual XML",
filename, subExpectPath)
}
actualIndex, _ := actualChildIndexes[actualChild.Name]
actualChildIndexes[actualChild.Name] = actualIndex + 1
subActualPath := fmt.Sprintf("%s/%s[%d]", actualPath, actualChild.Name, actualIndex)
err := testCompareElement(filename, subExpectPath, subActualPath, expectChild, actualChild, extraExpectNodes, extraActualNodes)
if err != nil {
return err
}
}
actualChildIndexes = make(map[string]uint)
for i, actualChild := range actual.Children {
actualIndex, _ := actualChildIndexes[actualChild.Name]
actualChildIndexes[actualChild.Name] = actualIndex + 1
if used[i] {
continue
}
subActualPath := fmt.Sprintf("%s/%s[%d]", actualPath, actualChild.Name, actualIndex)
if _, ok := extraActualNodes[subActualPath]; ok {
continue
}
return fmt.Errorf("%s: %s: element in actual XML missing in expected XML",
filename, subActualPath)
}
return nil
}
func makeExtraNodeMap(nodes []string) map[string]bool {
ret := make(map[string]bool)
for _, node := range nodes {
ret[node] = true
}
return ret
}
func testCompareXML(filename, expectStr, actualStr string, extraExpectNodes, extraActualNodes []string) error {
extraExpectNodeMap := makeExtraNodeMap(extraExpectNodes)
extraActualNodeMap := makeExtraNodeMap(extraActualNodes)
//fmt.Printf("%s\n", expectedstr)
expectRoot, err := loadXML(expectStr, true)
if err != nil {
return err
}
//fmt.Printf("%s\n", actualstr)
actualRoot, err := loadXML(actualStr, true)
if err != nil {
return err
}
if expectRoot.Name != actualRoot.Name {
return fmt.Errorf("%s: /: expected root element '%s' does not match actual '%s'",
filename, expectRoot.Name, actualRoot.Name)
}
err = testCompareElement(filename, "/"+expectRoot.Name+"[0]", "/"+actualRoot.Name+"[0]", expectRoot, actualRoot, extraExpectNodeMap, extraActualNodeMap)
if err != nil {
return err
}
return nil
}