@ConfigSync()
  def AssignGroupNodes(self, mods):
    """Changes the group of a number of nodes.

    @type mods: list of tuples; (node name, new group UUID)
    @param mods: Node membership modifications

    """
    groups = self._ConfigData().nodegroups
    nodes = self._ConfigData().nodes

    resmod = []

    # Try to resolve UUIDs first
    for (node_uuid, new_group_uuid) in mods:
      try:
        node = nodes[node_uuid]
      except __HOLE__:
        raise errors.ConfigurationError("Unable to find node '%s'" % node_uuid)

      if node.group == new_group_uuid:
        # Node is being assigned to its current group
        logging.debug("Node '%s' was assigned to its current group (%s)",
                      node_uuid, node.group)
        continue

      # Try to find current group of node
      try:
        old_group = groups[node.group]
      except KeyError:
        raise errors.ConfigurationError("Unable to find old group '%s'" %
                                        node.group)

      # Try to find new group for node
      try:
        new_group = groups[new_group_uuid]
      except KeyError:
        raise errors.ConfigurationError("Unable to find new group '%s'" %
                                        new_group_uuid)

      assert node.uuid in old_group.members, \
        ("Inconsistent configuration: node '%s' not listed in members for its"
         " old group '%s'" % (node.uuid, old_group.uuid))
      assert node.uuid not in new_group.members, \
        ("Inconsistent configuration: node '%s' already listed in members for"
         " its new group '%s'" % (node.uuid, new_group.uuid))

      resmod.append((node, old_group, new_group))

    # Apply changes
    for (node, old_group, new_group) in resmod:
      assert node.uuid != new_group.uuid and old_group.uuid != new_group.uuid, \
        "Assigning to current group is not possible"

      node.group = new_group.uuid

      # Update members of involved groups
      if node.uuid in old_group.members:
        old_group.members.remove(node.uuid)
      if node.uuid not in new_group.members:
        new_group.members.append(node.uuid)

    # Update timestamps and serials (only once per node/group object)
    now = time.time()
    for obj in frozenset(itertools.chain(*resmod)): # pylint: disable=W0142
      obj.serial_no += 1
      obj.mtime = now

    # Force ssconf update
    self._ConfigData().cluster.serial_no += 1
dataset/ETHPy150Open ganeti/ganeti/lib/config/__init__.py/ConfigWriter.AssignGroupNodes