Update prefix matching `spec` with attributes `attr`.

            * `auth` [BaseAuth]
                AAA options.
            * `spec` [prefix_spec]
                Specifies the prefix to edit.
            * `attr` [prefix_attr]
                Prefix attributes.

            Note that there are restrictions on when and how a prefix's type
            can be changed; reservations can be changed to assignments and vice
            versa, but only if they contain no child prefixes.

            This is the documentation of the internal backend function. It's
            exposed over XML-RPC, please also see the XML-RPC documentation for
            :py:func:`nipap.xmlrpc.NipapXMLRPC.edit_prefix` for full
            understanding.

def edit_prefix(self, auth, spec, attr):
        """ Update prefix matching `spec` with attributes `attr`.

            * `auth` [BaseAuth]
                AAA options.
            * `spec` [prefix_spec]
                Specifies the prefix to edit.
            * `attr` [prefix_attr]
                Prefix attributes.

            Note that there are restrictions on when and how a prefix's type
            can be changed; reservations can be changed to assignments and vice
            versa, but only if they contain no child prefixes.

            This is the documentation of the internal backend function. It's
            exposed over XML-RPC, please also see the XML-RPC documentation for
            :py:func:`nipap.xmlrpc.NipapXMLRPC.edit_prefix` for full
            understanding.
        """

        self._logger.debug("edit_prefix called; spec: %s attr: %s" %
                (unicode(spec), unicode(attr)))

        # Handle Pool - find correct one and remove bad pool keys
        pool = None
        if 'pool_id' in attr or 'pool_name' in attr:
            if 'pool_id' in attr:
                if attr['pool_id'] is None:
                    pool = {
                        'id': None,
                        'name': None
                    }
                else:
                    pool = self._get_pool(auth, { 'id': attr['pool_id'] })

            else:
                if attr['pool_name'] is None:
                    pool = {
                        'id': None,
                        'name': None
                    }
                else:
                    # resolve pool name to pool id
                    pool = self._get_pool(auth, { 'name': attr['pool_name'] })
                # and delete the pool_name attr
                del(attr['pool_name'])

            attr['pool_id'] = pool['id']

        else:
            pool = {
                'id': None,
                'name': None
            }

        # Handle VRF - find the correct one and remove bad VRF keys.
        vrf = self._get_vrf(auth, attr)
        if 'vrf_rt' in attr:
            del(attr['vrf_rt'])
        if 'vrf_name' in attr:
            del(attr['vrf_name'])
        attr['vrf_id'] = vrf['id']

        self._check_attr(attr, [], _prefix_attrs)

        if 'expires' in attr:
            attr['expires'] = _parse_expires(attr['expires'])

        prefixes = self.list_prefix(auth, spec)
        where, params1 = self._expand_prefix_spec(spec.copy())

        update, params2 = self._sql_expand_update(attr)
        params = dict(params2.items() + params1.items())

        sql = "UPDATE ip_net_plan SET " + update + " WHERE " + where
        sql += " RETURNING id"

        self._execute(sql, params)
        updated_prefixes = self._get_updated_rows(auth, self.search_prefix)

        # write to audit table
        audit_params = {
            'username': auth.username,
            'authenticated_as': auth.authenticated_as,
            'full_name': auth.full_name,
            'authoritative_source': auth.authoritative_source,
            'vrf_id': vrf['id'],
            'vrf_rt': vrf['rt'],
            'vrf_name': vrf['name']
        }

        for p in prefixes:
            audit_params['vrf_id'] = p['vrf_id']
            audit_params['vrf_rt'] = p['vrf_rt']
            audit_params['vrf_name'] = p['vrf_name']
            audit_params['prefix_id'] = p['id']
            audit_params['prefix_prefix'] = p['prefix']
            audit_params['description'] = 'Edited prefix %s attr: %s' % (p['prefix'], unicode(attr))
            sql, params = self._sql_expand_insert(audit_params)
            self._execute('INSERT INTO ip_net_log %s' % sql, params)

            # Only add to log if something was changed
            if p['pool_id'] != pool['id']:

                audit_params2 = {
                    'prefix_id': p['id'],
                    'prefix_prefix': p['prefix'],
                    'vrf_id': p['vrf_id'],
                    'vrf_rt': p['vrf_rt'],
                    'vrf_name': p['vrf_name'],
                    'username': auth.username,
                    'authenticated_as': auth.authenticated_as,
                    'full_name': auth.full_name,
                    'authoritative_source': auth.authoritative_source,
                }

                # If pool ID set, pool was expanded
                if pool['id'] is not None:

                    audit_params2['pool_id'] = pool['id']
                    audit_params2['pool_name'] = pool['name']
                    audit_params2['description'] = 'Expanded pool %s with prefix %s' % (pool['name'], p['prefix'])

                    sql, params = self._sql_expand_insert(audit_params2)
                    self._execute('INSERT INTO ip_net_log %s' % sql, params)

                # if prefix had pool set previously, prefix was removed from that pool
                if p['pool_id'] is not None:

                    pool2 = self._get_pool(auth, { 'id': p['pool_id'] })

                    audit_params2['pool_id'] = pool2['id']
                    audit_params2['pool_name'] = pool2['name']
                    audit_params2['description'] = 'Removed prefix %s from pool %s' % (p['prefix'], pool2['name'])

                    sql, params = self._sql_expand_insert(audit_params2)
                    self._execute('INSERT INTO ip_net_log %s' % sql, params)

        return updated_prefixes