예제 #1
0
def create_template():
    try:
        init_tenant_context(request, db)
        tpl, json_payload = parse_payload(request, template_schema)
        loaded_template = DeviceTemplate(**tpl)
        load_attrs(json_payload['attrs'], loaded_template, DeviceAttr, db)
        db.session.add(loaded_template)

        try:
            db.session.commit()
        except IntegrityError as error:
            handle_consistency_exception(error)

        results = json.dumps({
            'template':
            template_schema.dump(loaded_template).data,
            'result':
            'ok'
        })
        return make_response(results, 200)
    except HTTPRequestError as error:
        if isinstance(error.message, dict):
            return make_response(json.dumps(error.message), error.error_code)
        else:
            return format_response(error.error_code, error.message)
예제 #2
0
def update_template(templateid):
    try:
        init_tenant_context(request, db)

        # find old version of the template, if any
        old = assert_template_exists(templateid)
        # parse updated version from payload
        updated, json_payload = parse_payload(request, template_schema)
        old.label = updated['label']

        for attr in old.attrs:
            db.session.delete(attr)
        for attr in json_payload['attrs']:
            mapped = DeviceAttr(template=old, **attr)
            db.session.add(mapped)

        try:
            db.session.commit()
        except IntegrityError as error:
            handle_consistency_exception(error)

        results = {'updated': template_schema.dump(old).data, 'result': 'ok'}
        return make_response(json.dumps(results), 200)
    except HTTPRequestError as error:
        if isinstance(error.message, dict):
            return make_response(json.dumps(error.message), error.error_code)
        else:
            return format_response(error.error_code, error.message)
예제 #3
0
def get_templates():
    try:
        init_tenant_context(request, db)

        page_number, per_page = get_pagination(request)
        page = DeviceTemplate.query.paginate(page=int(page_number),
                                             per_page=int(per_page),
                                             error_out=False)
        templates = template_list_schema.dump(page.items).data
        result = {
            'pagination': {
                'page': page.page,
                'total': page.pages,
                'has_next': page.has_next,
                'next_page': page.next_num
            },
            'templates': templates
        }

        attr_format(request, result)
        return make_response(json.dumps(result), 200)

    except HTTPRequestError as e:
        if isinstance(e.message, dict):
            return make_response(json.dumps(e.message), e.error_code)
        else:
            return format_response(e.error_code, e.message)
예제 #4
0
def get_by_template(templateid):
    try:
        init_tenant_context(request, db)

        page_number, per_page = get_pagination(request)
        page = (
            db.session.query(Device)
            .join(DeviceTemplateMap)
            .filter_by(template_id=templateid)
            .paginate(page=page_number, per_page=per_page, error_out=False)
        )
        devices = []
        for d in page.items:
            devices.append(serialize_full_device(d))

        result = json.dumps({
            'pagination': {
                'page': page.page,
                'total': page.pages,
                'has_next': page.has_next,
                'next_page': page.next_num
            },
            'devices': devices
        })
        return make_response(result, 200)
    except HTTPRequestError as e:
        if isinstance(e.message, dict):
            return make_response(json.dumps(e.message), e.error_code)
        else:
            return format_response(e.error_code, e.message)
예제 #5
0
def get_devices():
    """
        Fetches known devices, potentially limited by a given value.
        Ordering might be user-configurable too.
    """
    try:
        init_tenant_context(request, db)

        page_number, per_page = get_pagination(request)
        page = Device.query.paginate(page=page_number, per_page=per_page, error_out=False)
        devices = []
        for d in page.items:
            devices.append(serialize_full_device(d))

        result = json.dumps({
            'pagination': {
                'page': page.page,
                'total': page.pages,
                'has_next': page.has_next,
                'next_page': page.next_num
            },
            'devices': devices
        })
        return make_response(result, 200)
    except HTTPRequestError as e:
        if isinstance(e.message, dict):
            return make_response(json.dumps(e.message), e.error_code)
        else:
            return format_response(e.error_code, e.message)
예제 #6
0
def get_device(deviceid):
    try:
        init_tenant_context(request, db)
        orm_device = assert_device_exists(deviceid)
        return make_response(json.dumps(serialize_full_device(orm_device)), 200)
    except HTTPRequestError as e:
        if isinstance(e.message, dict):
            return make_response(json.dumps(e.message), e.error_code)
        else:
            return format_response(e.error_code, e.message)
def get_template(templateid):
    try:
        init_tenant_context(request, db)
        tpl = assert_template_exists(templateid)
        json_template = template_schema.dump(tpl).data
        return make_response(json.dumps(json_template), 200)
    except HTTPRequestError as e:
        if isinstance(e.message, dict):
            return make_response(json.dumps(e.message), e.error_code)
        else:
            return format_response(e.error_code, e.message)
예제 #8
0
def remove_device(deviceid):
    try:
        init_tenant_context(request, db)
        orm_device = assert_device_exists(deviceid)
        data = serialize_full_device(orm_device)
        db.session.delete(orm_device)
        db.session.commit()

        results = json.dumps({'result': 'ok', 'removed_device': data})
        return make_response(results, 200)
    except HTTPRequestError as e:
        if isinstance(e.message, dict):
            return make_response(json.dumps(e.message), e.error_code)
        else:
            return format_response(e.error_code, e.message)
def remove_template(templateid):
    try:
        init_tenant_context(request, db)
        tpl = assert_template_exists(templateid)

        json_template = template_schema.dump(tpl).data
        db.session.delete(tpl)
        db.session.commit()

        results = json.dumps({'result': 'ok', 'removed': json_template})
        return make_response(results, 200)
    except HTTPRequestError as e:
        if isinstance(e.message, dict):
            return make_response(json.dumps(e.message), e.error_code)
        else:
            return format_response(e.error_code, e.message)
예제 #10
0
def add_template_to_device(deviceid, templateid):
    """ associates given template with device """

    try:
        tenant = init_tenant_context(request, db)
        orm_device = assert_device_exists(deviceid)
        orm_template = assert_template_exists(templateid)

        orm_device.templates.append(orm_template)

        try:
            db.session.commit()
        except IntegrityError as error:
            handle_consistency_exception(error)

        result = {
            'message': 'device updated',
            'device': serialize_full_device(orm_device)
        }
        return make_response(json.dumps(result))
    except HTTPRequestError as e:
        if isinstance(e.message, dict):
            return make_response(json.dumps(e.message), e.error_code)
        else:
            return format_response(e.error_code, e.message)
예제 #11
0
def configure_device(deviceid):
    try:
        tenant = init_tenant_context(request, db)
        # In fact, the actual device is not needed. We must be sure that it exists.
        assert_device_exists(deviceid)
        json_payload = json.loads(request.data)
        kafka_handler = KafkaHandler()
        # Remove topic metadata from JSON to be sent to the device
        # Should this be moved to a HTTP header?
        topic = json_payload["topic"]
        del json_payload["topic"]

        kafka_handler.configure(json_payload,
                                meta={
                                    "service": tenant,
                                    "id": deviceid,
                                    "topic": topic
                                })

        result = {'message': 'configuration sent'}
        return make_response(result, 200)

    except HTTPRequestError as e:
        if isinstance(e.message, dict):
            return make_response(json.dumps(e.message), e.error_code)
        else:
            return format_response(e.error_code, e.message)
예제 #12
0
def update_device(deviceid):
    try:
        tenant = init_tenant_context(request, db)
        old_device = assert_device_exists(deviceid)

        device_data, json_payload = parse_payload(request, device_schema)
        device_data.pop('templates')
        updated_device = Device(**device_data)
        parse_template_list(json_payload['templates'], updated_device)
        updated_device.id = deviceid

        # update sanity check
        if 'attrs' in json_payload:
            error = "Attributes cannot be updated inline. Update the associated template instead."
            return format_response(400, error)

        # TODO revisit iotagent notification mechanism
        # protocolHandler = IotaHandler(service=tenant)
        # device_type = 'virtual'
        # old_type = old_device.protocol
        # new_type = updated_device.protocol
        # if (old_type != 'virtual') and (new_type != 'virtual'):
        #     device_type = 'device'
        #     protocolHandler.update(updated_device)
        # if old_type != new_type:
        #     if old_type == 'virtual':
        #         device_type = 'device'
        #         protocolHandler.create(updated_device)
        #     elif new_type == 'virtual':
        #         protocolHandler.remove(updated_device.id)

        # TODO revisit device data persistence
        # subsHandler = PersistenceHandler(service=tenant)
        # subsHandler.remove(old_device.persistence)
        # updated_device.persistence = subsHandler.create(deviceid, device_type)

        # TODO remove this in favor of kafka as data broker....
        ctx_broker_handler = OrionHandler(service=tenant)
        ctx_broker_handler.update(serialize_full_device(old_device))

        db.session.delete(old_device)
        db.session.add(updated_device)

        try:
            db.session.commit()
        except IntegrityError as error:
            handle_consistency_exception(error)

        result = {
            'message': 'device updated',
            'device': serialize_full_device(updated_device)
        }
        return make_response(json.dumps(result))

    except HTTPRequestError as e:
        if isinstance(e.message, dict):
            return make_response(json.dumps(e.message), e.error_code)
        else:
            return format_response(e.error_code, e.message)
예제 #13
0
def remove_template(templateid):
    try:
        init_tenant_context(request, db)
        tpl = assert_template_exists(templateid)

        json_template = template_schema.dump(tpl).data
        try:
            db.session.delete(tpl)
            db.session.commit()
        except IntegrityError:
            raise HTTPRequestError(
                400,
                "Template cannot be removed as it is being used by devices")

        results = json.dumps({'result': 'ok', 'removed': json_template})
        return make_response(results, 200)
    except HTTPRequestError as e:
        if isinstance(e.message, dict):
            return make_response(json.dumps(e.message), e.error_code)
        else:
            return format_response(e.error_code, e.message)
예제 #14
0
def create_device():
    """ Creates and configures the given device (in json) """
    try:
        tenant = init_tenant_context(request, db)
        device_data, json_payload = parse_payload(request, device_schema)
        device_data['id'] = generate_device_id()
        device_data.pop(
            'templates')  # handled separatly by parse_template_list
        orm_device = Device(**device_data)
        parse_template_list(json_payload['templates'], orm_device)
        auto_create_template(json_payload, orm_device)

        # TODO revisit iotagent notification procedure
        # protocol_handler = IotaHandler(service=tenant)
        # device_type = "virtual"
        # if orm_device.protocol != "virtual":
        #     device_type = "device"
        #     protocol_handler.create(orm_device)
        # TODO revisit history management
        # subscription_handler = PersistenceHandler(service=tenant)
        # orm_device.persistence = subscription_handler.create(orm_device.device_id, "device")

        db.session.add(orm_device)

        try:
            db.session.commit()
        except IntegrityError as error:
            handle_consistency_exception(error)

        full_device = serialize_full_device(orm_device)

        result = json.dumps({
            'message': 'device created',
            'device': full_device
        })

        # TODO remove this in favor of kafka as data broker....
        ctx_broker_handler = OrionHandler(service=tenant)
        ctx_broker_handler.create(full_device)
        kafka_handler = KafkaHandler()
        kafka_handler.create(full_device, meta={"service": tenant})

        return make_response(result, 200)

    except HTTPRequestError as e:
        if isinstance(e.message, dict):
            return make_response(json.dumps(e.message), e.error_code)
        else:
            return format_response(e.error_code, e.message)
예제 #15
0
def remove_template_from_device(deviceid, templateid):
    """ removes given template from device """
    try:
        tenant = init_tenant_context(request, db)
        device = assert_device_exists(deviceid)
        relation = assert_device_relation_exists(deviceid, templateid)

        # Here (for now) there are no more validations to perform, as template removal
        # cannot violate attribute constraints

        db.session.remove(relation)
        db.session.commit()
        result = {'message': 'device updated', 'device': serialize_full_device(device)}
        return make_response(json.dumps(result))
    except HTTPRequestError as e:
        if isinstance(e.message, dict):
            return make_response(json.dumps(e.message), e.error_code)
        else:
            return format_response(e.error_code, e.message)
예제 #16
0
def create_device():
    """ Creates and configures the given device (in json) """
    try:
        tenant = init_tenant_context(request, db)
        try:
            count = int(request.args.get('count', '1'))
            clength = len(str(count))
            verbose = request.args.get('verbose', 'false') in ['true', '1', 'True']
            if verbose and count != 1:
                raise HTTPRequestError(400, "Verbose can only be used for single device creation")
        except ValueError as e:
            LOGGER.error(e)
            raise HTTPRequestError(400, "If provided, count must be integer")


        def indexed_label(base, index):
            if count == 1:
                return base
            else:
                return "{}_{:0{width}d}".format(base, index, width=clength)

        devices = []

        # Handlers
        ctx_broker_handler = OrionHandler(service=tenant)
        kafka_handler = KafkaHandler()
        subs_handler = PersistenceHandler(service=tenant)

        for i in range(0, count):
            device_data, json_payload = parse_payload(request, device_schema)
            device_data['id'] = generate_device_id()
            device_data['label'] = indexed_label(device_data['label'], i)
            device_data.pop('templates', None)  # handled separately by parse_template_list
            orm_device = Device(**device_data)
            parse_template_list(json_payload.get('templates', []), orm_device)
            auto_create_template(json_payload, orm_device)
            db.session.add(orm_device)

            devices.append({'id': device_data['id'], 'label': device_data['label']})

            full_device = serialize_full_device(orm_device)

            # TODO remove this in favor of kafka as data broker....
            # Updating handlers
            ctx_broker_handler.create(full_device)
            kafka_handler.create(full_device, meta={"service": tenant})
            # Generating 'device type' field for history
            type_descr = "template"
            for dev_type in full_device['attrs'].keys():
                type_descr += "_" + str(dev_type)
            subid = subs_handler.create(full_device['id'], type_descr)
            orm_device.persistence = subid

        try:
            db.session.commit()
        except IntegrityError as error:
            handle_consistency_exception(error)

        if verbose:
            result = json.dumps({
                'message': 'device created',
                'device': full_device
            })
        else:
            result = json.dumps({
                'message': 'devices created',
                'devices': devices
            })

        # TODO revisit iotagent notification procedure
        # protocol_handler = IotaHandler(service=tenant)
        # device_type = "virtual"
        # if orm_device.protocol != "virtual":
        #     device_type = "device"
        #     protocol_handler.create(orm_device)

        return make_response(result, 200)

    except HTTPRequestError as e:
        if isinstance(e.message, dict):
            return make_response(json.dumps(e.message), e.error_code)
        else:
            return format_response(e.error_code, e.message)