diff --git a/server/controller/genesis/common/utils.go b/server/controller/genesis/common/utils.go index c8a1bbffd1d..ba3c8ae913f 100644 --- a/server/controller/genesis/common/utils.go +++ b/server/controller/genesis/common/utils.go @@ -129,14 +129,22 @@ type KVMDomain struct { Type string `xml:"type,attr"` UUID string `xml:"uuid"` Name string `xml:"name"` - Label string `xml:"label"` + Title string `xml:"title"` MetaData KVMMetaData `xml:"metadata"` Devices KVMDevices `xml:"devices"` } -type KVMDomains struct { +type ETCDomains struct { Domains []KVMDomain `xml:"domain"` } +type DomStatus struct { + Domains KVMDomain `xml:"domain"` +} + +type RUNDomains struct { + DomStatus []DomStatus `xml:"domstatus"` +} + type XMLVPC struct { UUID string Name string @@ -367,32 +375,57 @@ func ParseVMStates(s string) (map[string]int, error) { return vmToState, nil } -func ParseVMXml(s string) ([]XMLVM, error) { +func ParseVMXml(s, nameField string) ([]XMLVM, error) { var vms []XMLVM if s == "" { return vms, nil } // ns := "http://openstack.org/xmlns/libvirt/nova/1.0" - - var domains KVMDomains - err := xml.Unmarshal([]byte(s), &domains) + var domains []KVMDomain + var etcDomains ETCDomains + err := xml.Unmarshal([]byte(s), &etcDomains) if err != nil { return vms, err } - for _, domain := range domains.Domains { + if len(etcDomains.Domains) != 0 { + domains = etcDomains.Domains + } else { + var runDomains RUNDomains + err := xml.Unmarshal([]byte(s), &runDomains) + if err != nil { + return vms, err + } + for _, d := range runDomains.DomStatus { + domains = append(domains, d.Domains) + } + } + for _, domain := range domains { var vm XMLVM if domain.UUID == "" { + log.Warning("vm uuid not found in xml") continue } - vm.UUID = domain.UUID if domain.Name == "" { + log.Warning("vm uuid not found in xml") continue } + vm.UUID = domain.UUID vm.Label = domain.Name - vm.Name = domain.MetaData.Instance.Name + switch nameField { + case "metadata": + vm.Name = domain.MetaData.Instance.Name + case "uuid": + vm.Name = domain.UUID + case "name": + vm.Name = domain.Name + case "title": + vm.Name = domain.Title + default: + log.Warningf("invalid config vm_name_field: (%s)", nameField) + } if vm.Name == "" { - vm.Name = vm.Label + vm.Name = domain.Name } if domain.MetaData.Instance.Owner.Project.UUID != "" { uuid := domain.MetaData.Instance.Owner.Project.UUID diff --git a/server/controller/genesis/common/utils_test.go b/server/controller/genesis/common/utils_test.go index 2de10a54eea..309bf47cc4b 100644 --- a/server/controller/genesis/common/utils_test.go +++ b/server/controller/genesis/common/utils_test.go @@ -236,7 +236,7 @@ func TestParseVMStates(t *testing.T) { func TestParseVMXml(t *testing.T) { XMLStr := `\n\n instance-00000064\n a51e6527-bd5e-42c2-81be-fee17d814706\n \n \n test-vm-liqian\n \n bangongfuwu\n NSLS\n \n \n \n \n \n \n \n \n \n
\n \n \n\n\n\n instance-00000065\n 75e9bb32-09c8-48e9-93bc-0330686702f3\n \n \n lbq-vm-vxlan-1\n \n bangongfuwu\n NSLS\n \n \n \n \n \n \n \n \n \n
\n \n \n \n \n \n \n
\n \n \n\n\n` Convey("TestParseVMXml", t, func() { - xmls, _ := ParseVMXml(XMLStr) + xmls, _ := ParseVMXml(XMLStr, "metadata") Convey("ParseVMXml items should be equal", func() { So(len(xmls), ShouldEqual, 2) So(xmls[0].UUID, ShouldEqual, "a51e6527-bd5e-42c2-81be-fee17d814706") diff --git a/server/controller/genesis/config/config.go b/server/controller/genesis/config/config.go index 241543f151e..2ea55d153b2 100644 --- a/server/controller/genesis/config/config.go +++ b/server/controller/genesis/config/config.go @@ -27,4 +27,5 @@ type GenesisConfig struct { MultiNSMode bool `default:"false" yaml:"multi_ns_mode"` SingleVPCMode bool `default:"false" yaml:"single_vpc_mode"` IgnoreNICRegex string `default:"^(kube-ipvs)" yaml:"ignore_nic_regex"` + VMNameField string `default:"metadata" yaml:"vm_name_field"` } diff --git a/server/controller/genesis/updater.go b/server/controller/genesis/updater.go index a897f2122f9..b7eb8d98808 100644 --- a/server/controller/genesis/updater.go +++ b/server/controller/genesis/updater.go @@ -55,6 +55,7 @@ type GenesisSyncRpcUpdater struct { excludeIPRanges []netaddr.IPPrefix multiNSMode bool singleVPCMode bool + vmNameField string ignoreNICRegex *regexp.Regexp genesisSyncDataByVtap map[string]GenesisSyncDataOperation } @@ -141,6 +142,7 @@ func NewGenesisSyncRpcUpdater(storage *SyncStorage, queue queue.QueueReader, cfg excludeIPRanges: excludeIPRanges, multiNSMode: cfg.MultiNSMode, singleVPCMode: cfg.SingleVPCMode, + vmNameField: cfg.VMNameField, ignoreNICRegex: ignoreNICRegex, genesisSyncDataByVtap: map[string]GenesisSyncDataOperation{}, } @@ -666,7 +668,7 @@ func (v *GenesisSyncRpcUpdater) ParseKVMPlatformInfo(info VIFRPCMessage, peer st if err != nil { log.Warning("parse vm states failed: " + err.Error()) } - xmlVMs, err := genesiscommon.ParseVMXml(rawVM) + xmlVMs, err := genesiscommon.ParseVMXml(rawVM, v.vmNameField) if err != nil { log.Warning("parse vm xml failed: " + err.Error()) } diff --git a/server/server.yaml b/server/server.yaml index 47405bf832e..50237d7c543 100644 --- a/server/server.yaml +++ b/server/server.yaml @@ -306,6 +306,12 @@ controller: # 忽略网卡正则表达式配置,匹配到会忽略该网卡,默认为 ^(kube-ipvs) ,增加其他的网卡名称需要在此基础上新增 ignore_nic_regex: + ## 采集器同步 KVM ,解析虚拟机的 XML 时,默认为 metadata 即使用 domian.metadata.instance.name 字段作为虚拟机的名称 + ## 可通过此配置将虚拟机名称指定为 domain.name、domain.title、domain.uuid 之一,默认为空 + ## 当使用此配置指定的字段取不到虚拟机名称或虚拟机名称为空时,则将使用 domain.name 的值作为虚拟机名称 + ## 例:vm_name_field: title ,指定 domain.title 作为虚拟机的名称 + #vm_name_field: metadata + prometheus: # synchronizer cache refresh interval, unit: second synchronizer_cache_refresh_interval: 60