'Attach an interface to an instance.'

@extensions.expected_errors((400, 404, 409, 500, 501))
@validation.schema(attach_interfaces.create, '2.0', '2.48')
@validation.schema(attach_interfaces.create_v249, '2.49')
def create(self, req, server_id, body):

    context = req.environ['nova.context']
    context.can(ai_policies.BASE_POLICY_NAME)
    context.can((ai_policies.POLICY_ROOT % 'create'))
    network_id = None
    port_id = None
    req_ip = None
    tag = None
    if body:
        attachment = body['interfaceAttachment']
        network_id = attachment.get('net_id', None)
        port_id = attachment.get('port_id', None)
        tag = attachment.get('tag', None)
        try:
            req_ip = attachment['fixed_ips'][0]['ip_address']
        except Exception:
            pass
    if (network_id and port_id):
        msg = _('Must    not    input    both    network_id    and    port_id')
        raise exc.HTTPBadRequest(explanation=msg)
    if (req_ip and (not network_id)):
        msg = _('Must    input    network_id    when    request    IP    address')
        raise exc.HTTPBadRequest(explanation=msg)
    instance = common.get_instance(self.compute_api, context, server_id)
    try:
        vif = self.compute_api.attach_interface(context, instance, network_id, port_id, req_ip, tag=tag)
    except (exception.InterfaceAttachFailedNoNetwork, exception.NetworkAmbiguous, exception.NoMoreFixedIps, exception.PortNotUsable, exception.AttachInterfaceNotSupported, exception.SecurityGroupCannotBeApplied, exception.TaggedAttachmentNotSupported) as e:
        raise exc.HTTPBadRequest(explanation=e.format_message())
    except (exception.InstanceIsLocked, exception.FixedIpAlreadyInUse, exception.PortInUse) as e:
        raise exc.HTTPConflict(explanation=e.format_message())
    except (exception.PortNotFound, exception.NetworkNotFound) as e:
        raise exc.HTTPNotFound(explanation=e.format_message())
    except exception.InterfaceAttachFailed as e:
        raise webob.exc.HTTPInternalServerError(explanation=e.format_message())
    except exception.InstanceInvalidState as state_error:
        common.raise_http_conflict_for_instance_invalid_state(state_error, 'attach_interface', server_id)
    return self.show(req, server_id, vif['id'])
