def post(self):
        """**Create an Event entry**

        **Example Request:**

        .. sourcecode:: http

            POST /api/v1/events HTTP/1.1
            Host: localhost
            Content-Type: application/json
            {
                "hostname": "example",
                "user": "johnny",
                "eventTypeId": 3,
                "note": "Sample description"
            }

        or

        .. sourcecode:: http

            POST /api/v1/events HTTP/1.1
            Host: localhost
            Content-Type: application/json
            {
                "hostname": "example",
                "user": "johnny",
                "category": "system-reboot",
                "state": "completed",
                "note": "Sample description"
            }

        or

        .. sourcecode:: http

            POST /api/v1/events HTTP/1.1
            Host: localhost
            Content-Type: application/json
            {
                "hostQuery": "tag=value",
                "user": "johnny",
                "eventTypeId": 3,
                "note": "Sample description"
            }

        or

        .. sourcecode:: http

            POST /api/v1/events HTTP/1.1
            Host: localhost
            Content-Type: application/json
            {
                "questId": 1,
                "user": "johnny",
                "eventTypeId": 3,
                "note": "Sample description"
            }

        **Example response:**

        .. sourcecode:: http

            HTTP/1.1 201 OK
            Location: /api/v1/events/1

            {
                "status": "created",
                "id": 1,
                "href": "/api/v1/events/1",
                "hostname": "example",
                "user": "johnny",
                "eventTypeId": 3,
                "note": "Sample description"
            }

        or

        .. sourcecode:: http

        HTTP/1.1 201 OK
            Location: /api/v1/events/1

            {
                "status": "created",
                "events": [{
                    "id": 1,
                    "href": "/api/v1/events/1",
                    "hostname": "example",
                    "user": "johnny",
                    "eventTypeId": 3,
                    "note": "Sample description"
                },
                ...
                ]
            }

        :reqjson string hostname: (*optional*) The hostname of the Host of this Event
        :regjson string hostnames: (*optional*) The list of hostnames for which we want to throw this Event
        :reqjson string hostQuery: (*optional*) The external query to run to get Hosts for which to create Events
        :regjson int questId: (*optional*) The Quest ID which has hosts for which we want to create Events
        :regjson string user: The user responsible for throwing this Event
        :regjson int eventTypeId: The id of the EventType
        :regjson string category: the category to use for the event
        :regjson string state: the state to use for the event
        :regjson string note: (*optional*) The human readable note describing this Event

        :reqheader Content-Type: The server expects a json body specified with
                                 this header.

        :resheader Location: URL to the created resource.

        :statuscode 201: The Event was successfully created.
        :statuscode 400: The request was malformed.
        :statuscode 401: The request was made without being logged in.
        :statuscode 409: There was a conflict with another resource.
        """

        # we need a unique tx number so we can look these back up again
        # as well as for logging
        # FIXME: how can we guarantee uniqueness here?
        tx = int(time.time() * 100000) + random.randrange(10000, 99999)

        log.info("EVENTS [{}]: Creating events".format(tx))

        try:
            user = self.jbody["user"]
            if not EMAIL_REGEX.match(user):
                user += "@" + self.domain
            event_type_id = self.jbody.get("eventTypeId", None)
            category = self.jbody.get("category", None)
            state = self.jbody.get("state", None)
            note = self.jbody.get("note", None)
        except KeyError as err:
            raise exc.BadRequest(
                "Missing Required Argument: {}".format(err.message)
            )
        except ValueError as err:
            raise exc.BadRequest(err.message)

        if not event_type_id and (not category and not state):
            raise exc.BadRequest(
                "Must specify an event type id or both category and state"
            )

        if event_type_id:
            event_type = self.session.query(EventType).get(event_type_id)
        else:
            event_type = self.session.query(EventType).filter(
                and_(
                    EventType.category == category,
                    EventType.state == state
                )
            ).one()

        if event_type is None:
            self.write_error(400, message="Bad event type")
            return

        category = event_type.category
        state = event_type.state

        hostnames = (
            [self.jbody.get("hostname", None)]
            if self.jbody.get("hostname", None) else []
        )

        if "hostnames" in self.jbody:
            hostnames.extend(self.jbody.get("hostnames"))

        log.info(
            "EVENTS [{}]: Will create event {} {}".format(
                tx, category, state
            )
        )

        log.info(
            "EVENTS [{}]: Hostnames specified: {}".format(
                tx, ", ".join(hostnames)
            )
        )

        # If a host query was specified, we need to talk to the external
        # query server to resolve this into a list of hostnames
        if "hostQuery" in self.jbody:
            query = self.jbody["hostQuery"]
            log.info("EVENTS [{}]: Running query {}".format(tx, query))
            response = PluginHelper.request_get(params={"query": query})
            if response.json()["status"] == "ok":
                hostnames.extend(response.json()["results"])
                log.info(
                    "EVENTS [{}]: Hostnames after query: {}".format(
                        tx, ", ".join(hostnames)
                    )
                )

        # If a quest Id was given, look up the labors in that quest and
        # get all the hostnames for those labors.
        if self.jbody in "questId":
            log.info("EVENTS [{}]: Looking up quest {}".format(
                tx, self.jbody["questId"])
            )
            quest = self.session.query(Quest).filter_by(
                id=self.jbody["questId"]
            ).scalar()
            if not quest:
                raise exc.NotFound("No such Quest {} found".format(id))
            for labor in quest.labors:
                hostnames.append(labor.host.hostname)

            log.info(
                "EVENTS [{}]: Hostnames after quest expansion: {}".format(
                    tx, ", ".join(hostnames)
                )
            )

        # We need to create a list of hostnames that don't have a Host record
        new_hosts_needed = set(hostnames)
        hosts = (
            self.session.query(Host).filter(Host.hostname.in_(hostnames)).all()
        )

        for host in hosts:
            new_hosts_needed.remove(str(host.hostname))

        # if we need to create hosts, do them all at once
        if new_hosts_needed:
            log.info("EVENTS [{}]: Creating hosts {}".format(
                tx, ", ".join(new_hosts_needed)
            ))
            Host.create_many(self.session, new_hosts_needed)
            hosts = (
                self.session.query(Host).filter(
                    Host.hostname.in_(hostnames)
                ).all()
            )

        if not hosts:
            raise exc.BadRequest("No hosts found with given list")

        try:
            if len(hosts) > 1:
                # if we are supposed to create many events,
                #  we want to do them as a giant batch
                log.info("EVENTS [{}]: Creating multiple events".format(tx))
                events_to_create = []
                for host in hosts:
                    events_to_create.append({
                        "host_id": host.id,
                        "user": user,
                        "event_type_id": event_type.id,
                        "note": note,
                        "tx": tx
                    })
                Event.create_many(self.session, events_to_create, tx)
            else:
                # if we are just creating one event, do it the simple way
                log.info("EVENTS [{}]: Creating 1 event".format(tx))
                event = Event.create(
                    self.session, hosts[0], user, event_type, note=note
                )

        except IntegrityError as err:
            raise exc.Conflict(err.orig.message)
        except exc.ValidationError as err:
            raise exc.BadRequest(err.message)

        log.info("EVENTS [{}]: Flushing and committing".format(tx))
        self.session.flush()
        log.info("EVENTS [{}]: Flushed".format(tx))
        self.session.commit()
        log.info("EVENTS [{}]: Committed".format(tx))

        if len(hosts) == 1:
            json = event.to_dict(self.href_prefix)
            json["href"] = "/api/v1/events/{}".format(event.id)
            self.created(
                "/api/v1/events/{}".format(event.id), json
            )
        else:
            # if we created many events, we need to look them up by the TX
            # number to figure out what they were since the were created in bulk
            created_events = self.session.query(Event).filter(Event.tx == tx).all()
            self.created(
                data={
                    "events": (
                        [event.to_dict(self.href_prefix) for event in created_events]
                    ),
                    "totalEvents": len(created_events)
                }
            )

        log.info("EVENTS [{}]: Created event {} {} for {}".format(
            tx, category, state,
            ", ".join(hostnames)
        ))
dataset/ETHPy150Open dropbox/hermes/hermes/handlers/api.py/EventsHandler.post/swapped operands of `in`