docs: def _gen_xml(name,
               cpu,
               mem,
               diskp,
               nicp,
               hypervisor,
               os_type,
               arch,
               graphics=None,
               loader=None,
               **kwargs):
      '''
      Generate the XML string to define a libvirt VM
      '''
      mem = int(mem) * 1024  # MB
      context = {
          'hypervisor': hypervisor,
          'name': name,
          'cpu': six.text_type(cpu),
          'mem': six.text_type(mem),
      }
      if hypervisor in ['qemu', 'kvm']:
          context['controller_model'] = False
      elif hypervisor == 'vmware':
          # TODO: make bus and model parameterized, this works for 64-bit Linux
          context['controller_model'] = 'lsilogic'
  
      # By default, set the graphics to listen to all addresses
      if graphics:
          if 'listen' not in graphics:
              graphics['listen'] = {'type': 'address', 'address': '0.0.0.0'}
          elif 'address' not in graphics['listen'] and graphics['listen']['type'] == 'address':
              graphics['listen']['address'] = '0.0.0.0'
  
          # Graphics of type 'none' means no graphics device at all
          if graphics.get('type', 'none') == 'none':
              graphics = None
      context['graphics'] = graphics
  
      if loader and 'path' not in loader:
          log.info('`path` is a required property of `loader`, and cannot be found. Skipping loader configuration')
          loader = None
      elif loader:
          loader_attributes = []
          for key, val in loader.items():
              if key == 'path':
                  continue
              loader_attributes.append("{key}='{val}'".format(key=key, val=val))
          loader['_attributes'] = ' '.join(loader_attributes)
  
      if 'boot_dev' in kwargs:
          context['boot_dev'] = []
          for dev in kwargs['boot_dev'].split():
              context['boot_dev'].append(dev)
      else:
          context['boot_dev'] = ['hd']
  
      context['loader'] = loader
  
      if os_type == 'xen':
          # Compute the Xen PV boot method
          if __grains__['os_family'] == 'Suse':
              context['kernel'] = '/usr/lib/grub2/x86_64-xen/grub.xen'
              context['boot_dev'] = []
  
      if 'serial_type' in kwargs:
          context['serial_type'] = kwargs['serial_type']
      if 'serial_type' in context and context['serial_type'] == 'tcp':
          if 'telnet_port' in kwargs:
              context['telnet_port'] = kwargs['telnet_port']
          else:
              context['telnet_port'] = 23023  # FIXME: use random unused port
      if 'serial_type' in context:
          if 'console' in kwargs:
              context['console'] = kwargs['console']
          else:
              context['console'] = True
  
      context['disks'] = []
      disk_bus_map = {'virtio': 'vd', 'xen': 'xvd', 'fdc': 'fd', 'ide': 'hd'}
      for i, disk in enumerate(diskp):
          prefix = disk_bus_map.get(disk['model'], 'sd')
          disk_context = {
              'device': disk.get('device', 'disk'),
              'target_dev': '{0}{1}'.format(prefix, string.ascii_lowercase[i]),
              'disk_bus': disk['model'],
              'type': disk['format'],
              'index': six.text_type(i),
          }
          if 'source_file' and disk['source_file']:
              disk_context['source_file'] = disk['source_file']
  
          if hypervisor in ['qemu', 'kvm', 'bhyve', 'xen']:
              disk_context['address'] = False
              disk_context['driver'] = True
          elif hypervisor in ['esxi', 'vmware']:
              disk_context['address'] = True
              disk_context['driver'] = False
          context['disks'].append(disk_context)
      context['nics'] = nicp
  
      context['os_type'] = os_type
      context['arch'] = arch
  
      fn_ = 'libvirt_domain.jinja'
      try:
          template = JINJA.get_template(fn_)
      except jinja2.exceptions.TemplateNotFound:
          log.error('Could not load template %s', fn_)
          return ''
  
      return template.render(**context)