docs: def update(name,
             cpu=0,
             mem=0,
             disk_profile=None,
             disks=None,
             nic_profile=None,
             interfaces=None,
             graphics=None,
             live=True,
             **kwargs):
      '''
      Update the definition of an existing domain.
  
      :param name: Name of the domain to update
      :param cpu: Number of virtual CPUs to assign to the virtual machine
      :param mem: Amount of memory to allocate to the virtual machine in MiB.
      :param disk_profile: disk profile to use
      :param disks:
          Disk definitions as documented in the :func:`init` function.
          If neither the profile nor this parameter are defined, the disk devices
          will not be changed. However to clear disks set this parameter to empty list.
  
      :param nic_profile: network interfaces profile to use
      :param interfaces:
          Network interface definitions as documented in the :func:`init` function.
          If neither the profile nor this parameter are defined, the interface devices
          will not be changed. However to clear network interfaces set this parameter
          to empty list.
  
      :param graphics:
          The new graphics definition as defined in init-graphics-def_. If not set,
          the graphics will not be changed. To remove a graphics device, set this parameter
          to ``{'type': 'none'}``.
  
      :param live:
          ``False`` to avoid trying to live update the definition. In such a case, the
          new definition is applied at the next start of the virtual machine. If ``True``,
          not all aspects of the definition can be live updated, but as much as possible
          will be attempted. (Default: ``True``)
  
      :param connection: libvirt connection URI, overriding defaults
      :param username: username to connect with, overriding defaults
      :param password: password to connect with, overriding defaults
  
      :return:
  
          Returns a dictionary indicating the status of what has been done. It is structured in
          the following way:
  
          .. code-block:: python
  
              {
                'definition': True,
                'cpu': True,
                'mem': True,
                'disks': {'attached': [list of actually attached disks],
                          'detached': [list of actually detached disks]},
                'nics': {'attached': [list of actually attached nics],
                         'detached': [list of actually detached nics]},
                'errors': ['error messages for failures']
              }
  
      .. versionadded:: 2019.2.0
  
      CLI Example:
  
      .. code-block:: bash
  
          salt '*' virt.update domain cpu=2 mem=1024
  
      '''
      status = {
          'definition': False,
          'disk': {'attached': [], 'detached': []},
          'interface': {'attached': [], 'detached': []}
      }
      conn = __get_conn(**kwargs)
      domain = _get_domain(conn, name)
      desc = ElementTree.fromstring(domain.XMLDesc(0))
      need_update = False
  
      # Compute the XML to get the disks, interfaces and graphics
      hypervisor = desc.get('type')
      all_disks = _disk_profile(disk_profile, hypervisor, disks, name, **kwargs)
      new_desc = ElementTree.fromstring(_gen_xml(name,
                                                 cpu,
                                                 mem,
                                                 all_disks,
                                                 _get_merged_nics(hypervisor, nic_profile, interfaces),
                                                 hypervisor,
                                                 domain.OSType(),
                                                 desc.find('.//os/type').get('arch'),
                                                 graphics,
                                                 **kwargs))
  
      # Update the cpu
      cpu_node = desc.find('vcpu')
      if cpu and int(cpu_node.text) != cpu:
          cpu_node.text = six.text_type(cpu)
          cpu_node.set('current', six.text_type(cpu))
          need_update = True
  
      # Update the memory, note that libvirt outputs all memory sizes in KiB
      for mem_node_name in ['memory', 'currentMemory']:
          mem_node = desc.find(mem_node_name)
          if mem and int(mem_node.text) != mem * 1024:
              mem_node.text = six.text_type(mem)
              mem_node.set('unit', 'MiB')
              need_update = True
  
      # Update the XML definition with the new disks and diff changes
      devices_node = desc.find('devices')
      parameters = {'disk': ['disks', 'disk_profile'],
                    'interface': ['interfaces', 'nic_profile'],
                    'graphics': ['graphics']}
      changes = {}
      for dev_type in parameters:
          changes[dev_type] = {}
          func_locals = locals()
          if [param for param in parameters[dev_type] if func_locals.get(param, None) is not None]:
              old = devices_node.findall(dev_type)
              new = new_desc.findall('devices/{0}'.format(dev_type))
              changes[dev_type] = globals()['_diff_{0}_lists'.format(dev_type)](old, new)
              if changes[dev_type]['deleted'] or changes[dev_type]['new']:
                  for item in old:
                      devices_node.remove(item)
                  devices_node.extend(changes[dev_type]['sorted'])
                  need_update = True
  
      # Set the new definition
      if need_update:
          # Create missing disks if needed
          if changes['disk']:
              for idx, item in enumerate(changes['disk']['sorted']):
                  source_file = all_disks[idx]['source_file']
                  if item in changes['disk']['new'] and source_file and not os.path.isfile(source_file):
                      _qemu_image_create(all_disks[idx])
  
          try:
              conn.defineXML(salt.utils.stringutils.to_str(ElementTree.tostring(desc)))
              status['definition'] = True
          except libvirt.libvirtError as err:
              conn.close()
              raise err
  
          # Do the live changes now that we know the definition has been properly set
          # From that point on, failures are not blocking to try to live update as much
          # as possible.
          commands = []
          if domain.isActive() and live:
              if cpu:
                  commands.append({'device': 'cpu',
                                   'cmd': 'setVcpusFlags',
                                   'args': [cpu, libvirt.VIR_DOMAIN_AFFECT_LIVE]})
              if mem:
                  commands.append({'device': 'mem',
                                   'cmd': 'setMemoryFlags',
                                   'args': [mem * 1024, libvirt.VIR_DOMAIN_AFFECT_LIVE]})
  
              for dev_type in ['disk', 'interface']:
                  for added in changes[dev_type].get('new', []):
                      commands.append({'device': dev_type,
                                       'cmd': 'attachDevice',
                                       'args': [salt.utils.stringutils.to_str(ElementTree.tostring(added))]})
  
                  for removed in changes[dev_type].get('deleted', []):
                      commands.append({'device': dev_type,
                                       'cmd': 'detachDevice',
                                       'args': [salt.utils.stringutils.to_str(ElementTree.tostring(removed))]})
  
          for cmd in commands:
              try:
                  ret = getattr(domain, cmd['cmd'])(*cmd['args'])
                  device_type = cmd['device']
                  if device_type in ['cpu', 'mem']:
                      status[device_type] = not bool(ret)
                  else:
                      actions = {'attachDevice': 'attached', 'detachDevice': 'detached'}
                      status[device_type][actions[cmd['cmd']]].append(cmd['args'][0])
  
              except libvirt.libvirtError as err:
                  if 'errors' not in status:
                      status['errors'] = []
                  status['errors'].append(six.text_type(err))
  
      conn.close()
      return status