github.com/juju/juju@v0.0.0-20240327075706-a90865de2538/container/kvm/libvirt/domainxml_test.go (about)

     1  // Copyright 2016 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package libvirt_test
     5  
     6  import (
     7  	"encoding/xml"
     8  
     9  	"github.com/juju/errors"
    10  	"github.com/juju/testing"
    11  	jc "github.com/juju/testing/checkers"
    12  	gc "gopkg.in/check.v1"
    13  
    14  	. "github.com/juju/juju/container/kvm/libvirt"
    15  )
    16  
    17  // gocheck boilerplate.
    18  type domainXMLSuite struct {
    19  	testing.IsolationSuite
    20  }
    21  
    22  var _ = gc.Suite(&domainXMLSuite{})
    23  
    24  var amd64DomainStr = `
    25  <domain type="kvm">
    26      <name>juju-someid</name>
    27      <vcpu>2</vcpu>
    28      <currentMemory unit="MiB">1024</currentMemory>
    29      <memory unit="MiB">1024</memory>
    30      <os>
    31          <type>hvm</type>
    32      </os>
    33      <features>
    34          <acpi></acpi>
    35      </features>
    36      <cpu mode="host-passthrough" check="none"></cpu>
    37      <devices>
    38          <disk device="disk" type="file">
    39              <driver type="qcow2" name="qemu"></driver>
    40              <source file="/some/path"></source>
    41              <target dev="vda"></target>
    42          </disk>
    43          <disk device="disk" type="file">
    44              <driver type="raw" name="qemu"></driver>
    45              <source file="/another/path"></source>
    46              <target dev="vdb"></target>
    47          </disk>
    48          <interface type="bridge">
    49              <mac address="00:00:00:00:00:00"></mac>
    50              <model type="virtio"></model>
    51              <source bridge="parent-dev"></source>
    52              <guest dev="device-name"></guest>
    53          </interface>
    54          <serial type="pty">
    55              <source path="/dev/pts/2"></source>
    56              <target port="0"></target>
    57          </serial>
    58          <console type="pty" tty="/dev/pts/2">
    59              <source path="/dev/pts/2"></source>
    60              <target port="0"></target>
    61          </console>
    62      </devices>
    63  </domain>`[1:]
    64  
    65  var arm64DomainStr = `
    66  <domain type="kvm">
    67      <name>juju-someid</name>
    68      <vcpu>2</vcpu>
    69      <currentMemory unit="MiB">1024</currentMemory>
    70      <memory unit="MiB">1024</memory>
    71      <os>
    72          <type arch="aarch64" machine="virt">hvm</type>
    73          <loader readonly="yes" type="pflash">/shared/readonly.fd</loader>
    74      </os>
    75      <features>
    76          <gic version="host"></gic>
    77          <acpi></acpi>
    78      </features>
    79      <cpu mode="host-passthrough" check="none"></cpu>
    80      <devices>
    81          <disk device="disk" type="file">
    82              <driver type="qcow2" name="qemu"></driver>
    83              <source file="/some/path"></source>
    84              <target dev="vda"></target>
    85          </disk>
    86          <disk device="disk" type="file">
    87              <driver type="raw" name="qemu"></driver>
    88              <source file="/another/path"></source>
    89              <target dev="vdb"></target>
    90          </disk>
    91          <interface type="bridge">
    92              <mac address="00:00:00:00:00:00"></mac>
    93              <model type="virtio"></model>
    94              <source bridge="parent-dev"></source>
    95              <guest dev="device-name"></guest>
    96          </interface>
    97          <serial type="pty">
    98              <source path="/dev/pts/2"></source>
    99              <target port="0"></target>
   100          </serial>
   101          <console type="pty" tty="/dev/pts/2">
   102              <source path="/dev/pts/2"></source>
   103              <target port="0"></target>
   104          </console>
   105      </devices>
   106  </domain>`[1:]
   107  
   108  var amd64WithOvsBridgeDomainStr = `
   109  <domain type="kvm">
   110      <name>juju-someid</name>
   111      <vcpu>2</vcpu>
   112      <currentMemory unit="MiB">1024</currentMemory>
   113      <memory unit="MiB">1024</memory>
   114      <os>
   115          <type>hvm</type>
   116      </os>
   117      <features>
   118          <acpi></acpi>
   119      </features>
   120      <cpu mode="host-passthrough" check="none"></cpu>
   121      <devices>
   122          <disk device="disk" type="file">
   123              <driver type="qcow2" name="qemu"></driver>
   124              <source file="/some/path"></source>
   125              <target dev="vda"></target>
   126          </disk>
   127          <disk device="disk" type="file">
   128              <driver type="raw" name="qemu"></driver>
   129              <source file="/another/path"></source>
   130              <target dev="vdb"></target>
   131          </disk>
   132          <interface type="bridge">
   133              <mac address="00:00:00:00:00:00"></mac>
   134              <model type="virtio"></model>
   135              <source bridge="parent-dev"></source>
   136              <guest dev="device-name"></guest>
   137              <virtualport type="openvswitch"></virtualport>
   138          </interface>
   139          <serial type="pty">
   140              <source path="/dev/pts/2"></source>
   141              <target port="0"></target>
   142          </serial>
   143          <console type="pty" tty="/dev/pts/2">
   144              <source path="/dev/pts/2"></source>
   145              <target port="0"></target>
   146          </console>
   147      </devices>
   148  </domain>`[1:]
   149  
   150  func (domainXMLSuite) TestNewDomain(c *gc.C) {
   151  	table := []struct {
   152  		arch, want string
   153  	}{
   154  		{"amd64", amd64DomainStr},
   155  		{"arm64", arm64DomainStr},
   156  	}
   157  	for i, test := range table {
   158  		c.Logf("TestNewDomain: test #%d for %s", i+1, test.arch)
   159  		ifaces := []InterfaceInfo{
   160  			dummyInterface{
   161  				mac:    "00:00:00:00:00:00",
   162  				parent: "parent-dev",
   163  				name:   "device-name"}}
   164  		disks := []DiskInfo{
   165  			dummyDisk{driver: "qcow2", source: "/some/path"},
   166  			dummyDisk{driver: "raw", source: "/another/path"},
   167  		}
   168  		params := dummyParams{ifaceInfo: ifaces, diskInfo: disks, memory: 1024, cpuCores: 2, hostname: "juju-someid", arch: test.arch}
   169  
   170  		if test.arch == "arm64" {
   171  			params.loader = "/shared/readonly.fd"
   172  		}
   173  
   174  		d, err := NewDomain(params)
   175  		c.Check(err, jc.ErrorIsNil)
   176  		ml, err := xml.MarshalIndent(&d, "", "    ")
   177  		c.Check(err, jc.ErrorIsNil)
   178  		c.Assert(string(ml), jc.DeepEquals, test.want)
   179  	}
   180  }
   181  
   182  func (domainXMLSuite) TestNewDomainWithOvsBridge(c *gc.C) {
   183  	ifaces := []InterfaceInfo{
   184  		dummyInterface{
   185  			mac:                   "00:00:00:00:00:00",
   186  			parent:                "parent-dev",
   187  			name:                  "device-name",
   188  			parentVirtualPortType: "openvswitch",
   189  		},
   190  	}
   191  	disks := []DiskInfo{
   192  		dummyDisk{driver: "qcow2", source: "/some/path"},
   193  		dummyDisk{driver: "raw", source: "/another/path"},
   194  	}
   195  	params := dummyParams{ifaceInfo: ifaces, diskInfo: disks, memory: 1024, cpuCores: 2, hostname: "juju-someid", arch: "amd64"}
   196  
   197  	d, err := NewDomain(params)
   198  	c.Check(err, jc.ErrorIsNil)
   199  	ml, err := xml.MarshalIndent(&d, "", "    ")
   200  	c.Check(err, jc.ErrorIsNil)
   201  	c.Assert(string(ml), jc.DeepEquals, amd64WithOvsBridgeDomainStr)
   202  }
   203  
   204  func (domainXMLSuite) TestNewDomainError(c *gc.C) {
   205  	d, err := NewDomain(dummyParams{err: errors.Errorf("boom")})
   206  	c.Check(d, jc.DeepEquals, Domain{})
   207  	c.Check(err, gc.ErrorMatches, "boom")
   208  }
   209  
   210  type dummyParams struct {
   211  	err       error
   212  	arch      string
   213  	cpuCores  uint64
   214  	diskInfo  []DiskInfo
   215  	hostname  string
   216  	ifaceInfo []InterfaceInfo
   217  	loader    string
   218  	memory    uint64
   219  	nvram     string
   220  }
   221  
   222  func (p dummyParams) Arch() string                 { return p.arch }
   223  func (p dummyParams) CPUs() uint64                 { return p.cpuCores }
   224  func (p dummyParams) DiskInfo() []DiskInfo         { return p.diskInfo }
   225  func (p dummyParams) Host() string                 { return p.hostname }
   226  func (p dummyParams) Loader() string               { return p.loader }
   227  func (p dummyParams) NVRAM() string                { return p.nvram }
   228  func (p dummyParams) NetworkInfo() []InterfaceInfo { return p.ifaceInfo }
   229  func (p dummyParams) RAM() uint64                  { return p.memory }
   230  func (p dummyParams) ValidateDomainParams() error  { return p.err }
   231  
   232  type dummyDisk struct {
   233  	source string
   234  	driver string
   235  }
   236  
   237  func (d dummyDisk) Driver() string { return d.driver }
   238  func (d dummyDisk) Source() string { return d.source }
   239  
   240  type dummyInterface struct {
   241  	mac, parent, parentVirtualPortType, name string
   242  }
   243  
   244  func (i dummyInterface) InterfaceName() string         { return i.name }
   245  func (i dummyInterface) MACAddress() string            { return i.mac }
   246  func (i dummyInterface) ParentInterfaceName() string   { return i.parent }
   247  func (i dummyInterface) ParentVirtualPortType() string { return i.parentVirtualPortType }