docs: def portgroups_configured(name, dvs, portgroups):
      '''
      Configures portgroups on a DVS.
  
      Creates/updates/removes portgroups in a provided DVS
  
      dvs
          Name of the DVS
  
      portgroups
          Portgroup dict representations (see module sysdocs)
      '''
      datacenter = _get_datacenter_name()
      log.info('Running state %s on DVS \'%s\', datacenter \'%s\'',
               name, dvs, datacenter)
      changes_required = False
      ret = {'name': name,
             'changes': {},
             'result': None,
             'comment': None}
      comments = []
      changes = {}
      changes_required = False
  
      try:
          #TODO portroups validation
          si = __salt__['vsphere.get_service_instance_via_proxy']()
          current_pgs = __salt__['vsphere.list_dvportgroups'](
              dvs=dvs, service_instance=si)
          expected_pg_names = []
          for pg in portgroups:
              pg_name = pg['name']
              expected_pg_names.append(pg_name)
              del pg['name']
              log.info('Checking pg \'%s\'', pg_name)
              filtered_current_pgs = \
                      [p for p in current_pgs if p.get('name') == pg_name]
              if not filtered_current_pgs:
                  changes_required = True
                  if __opts__['test']:
                      comments.append('State {0} will create a new portgroup '
                                      '\'{1}\' in DVS \'{2}\', datacenter '
                                      '\'{3}\''.format(name, pg_name, dvs,
                                                       datacenter))
                  else:
                      __salt__['vsphere.create_dvportgroup'](
                          portgroup_dict=pg, portgroup_name=pg_name, dvs=dvs,
                          service_instance=si)
                      comments.append('Created a new portgroup \'{0}\' in DVS '
                                      '\'{1}\', datacenter \'{2}\''
                                      ''.format(pg_name, dvs, datacenter))
                  log.info(comments[-1])
                  changes.update({pg_name: {'new': pg}})
              else:
                  # Porgroup already exists. Checking the config
                  log.trace('Portgroup \'%s\' found in DVS \'%s\', datacenter '
                            '\'%s\'. Checking for any updates.',
                            pg_name, dvs, datacenter)
                  current_pg = filtered_current_pgs[0]
                  diff_dict = _get_diff_dict(current_pg, pg)
  
                  if diff_dict:
                      changes_required = True
                      if __opts__['test']:
                          changes_strings = \
                                  _get_changes_from_diff_dict(diff_dict)
                          log.trace('changes_strings = %s', changes_strings)
                          comments.append(
                              'State {0} will update portgroup \'{1}\' in '
                              'DVS \'{2}\', datacenter \'{3}\':\n{4}'
                              ''.format(name, pg_name, dvs, datacenter,
                                        '\n'.join(['\t{0}'.format(c) for c in
                                                   changes_strings])))
                      else:
                          __salt__['vsphere.update_dvportgroup'](
                              portgroup_dict=pg, portgroup=pg_name, dvs=dvs,
                              service_instance=si)
                          comments.append('Updated portgroup \'{0}\' in DVS '
                                          '\'{1}\', datacenter \'{2}\''
                                          ''.format(pg_name, dvs, datacenter))
                      log.info(comments[-1])
                      changes.update(
                          {pg_name: {'new':
                                     _get_val2_dict_from_diff_dict(diff_dict),
                                     'old':
                                     _get_val1_dict_from_diff_dict(diff_dict)}})
          # Add the uplink portgroup to the expected pg names
          uplink_pg = __salt__['vsphere.list_uplink_dvportgroup'](
              dvs=dvs, service_instance=si)
          expected_pg_names.append(uplink_pg['name'])
          # Remove any extra portgroups
          for current_pg in current_pgs:
              if current_pg['name'] not in expected_pg_names:
                  changes_required = True
                  if __opts__['test']:
                      comments.append('State {0} will remove '
                                      'the portgroup \'{1}\' from DVS \'{2}\', '
                                      'datacenter \'{3}\''
                                      ''.format(name, current_pg['name'], dvs,
                                                datacenter))
                  else:
                      __salt__['vsphere.remove_dvportgroup'](
                          portgroup=current_pg['name'], dvs=dvs,
                          service_instance=si)
                      comments.append('Removed the portgroup \'{0}\' from DVS '
                                      '\'{1}\', datacenter \'{2}\''
                                      ''.format(current_pg['name'], dvs,
                                                datacenter))
                  log.info(comments[-1])
                  changes.update({current_pg['name']:
                                  {'old': current_pg}})
          __salt__['vsphere.disconnect'](si)
      except salt.exceptions.CommandExecutionError as exc:
          log.exception('Encountered error')
          if si:
              __salt__['vsphere.disconnect'](si)
          if not __opts__['test']:
              ret['result'] = False
          ret.update({'comment': exc.strerror,
                      'result': False if not __opts__['test'] else None})
          return ret
      if not changes_required:
          # We have no changes
          ret.update({'comment': ('All portgroups in DVS \'{0}\', datacenter '
                                  '\'{1}\' exist and are correctly configured. '
                                  'Nothing to be done.'.format(dvs, datacenter)),
                      'result': True})
      else:
          ret.update({
              'comment': '\n'.join(comments),
              'changes': changes,
              'result': None if __opts__['test'] else True,
          })
      return ret