def query_one_group(group_id):
    uid, err = get_oemid(request=request)
    if err is not None:
        return jsonify(UNAUTH_RESULT)

    ctx.current_user = DccaUser.get_by_id(uid)

    limit = request.args.get('limit') if request.args.get(
        'limit') else DEFAULT_GROUP_LIMTI
    offset = request.args.get('offset') if request.args.get(
        'offset') else DEFAULT_GROUP_OFFSET

    empty_check(group_id, error_message='The "group_id" cannot be empty.')
    results = OrderedDict()

    # workaround it is not a uuid, group id
    if group_id and len(str(group_id)) < 32:
        devices_group_list = DccaAssHostModel.get_model_deviceid(int(group_id))

        r = DccaModel.get_by_id(int(group_id))
        if not r:
            raise Exception("%s: group or model not found" % (str(group_id)))

        results['id'] = r.id
        name = "%s-%s-%s-%s" % (r.model, r.type, r.platform, r.vendor)
        results['name'] = name
        results["description"] = "%s: model group" % name

    else:
        group = DccaDeviceGroup.get_by_id(group_id, uid)
        empty_check(group, error_message='The "group" is not accessable.')
        devices_group_list = group.query_bind_devices(limit=limit,
                                                      offset=offset)

        results['id'] = group_id
        results["name"] = group.name
        results["description"] = group.desc

    results["device"] = OrderedDict()
    results["device"]['limit'] = limit
    results["device"]['offset'] = offset
    results['devices'] = []
    total = 0

    for device_group in devices_group_list:
        device_id = device_group[0]
        device = Host.get_id(device_id)
        if device:
            model_id = Host.get_model_id(device_id)
            devices = device.as_dict(schema=DeviceSchema)
            devices['status'] = query_one_device_status(devices['name'])
            total += 1
            results['devices'].append(devices)
            if model_id[0]:
                model = DccaModel.get_by_id(model_id)
                devices['model'] = model.as_dict(schema=ModelSchema)
    results['device']['total'] = total

    return jsonify(results)
def batch_delete_device_group():
    uid, err = get_oemid(request=request)
    if err is not None:
        return jsonify(UNAUTH_RESULT)

    ctx.current_user = DccaUser.get_by_id(uid)

    check_json(request)
    group_ids = get_json(request).get('group_ids')

    empty_check(group_ids, error_message='The "group_ids" cannot be empty.')

    remove_fail_list = []
    remove_list = []
    results = OrderedDict()
    results['groups'] = OrderedDict()
    results['groups']['success'] = []
    results['groups']['fail'] = []

    for group_id in group_ids:
        group = DccaDeviceGroup.get_by_id(group_id, uid)
        if group:
            try:
                remove_list.append(group)
                group.remove()
                session.commit()
            except Exception as e:
                remove_fail_dict = {'id': group_id, 'message': e}
                remove_fail_list.append(remove_fail_dict)
                raise DCCAException('Fail to remove device group')
        else:
            message = 'Fail to remove device group'
            remove_fail_dict = {'id': group_id, 'message': message}
            remove_fail_list.append(remove_fail_dict)

    if len(remove_list) == 0:
        results['status'] = "fail"
        results['message'] = "Fail to remove device group"
        for group_fail in remove_fail_list:
            results['groups']['fail'].append(group_fail)
        results['groups']['fail_total'] = len(remove_fail_list)
    else:
        for group in remove_list:
            results['status'] = "success"
            results['message'] = "Success to remove group"
            results['groups']['success'].append(
                group.as_dict(schema=DeviceGroupBindSchema))
        results['groups']['success_total'] = len(remove_list)
        for group_fail in remove_fail_list:
            results['groups']['fail'].append(group_fail)
        results['groups']['fail_total'] = len(remove_fail_list)

    return jsonify(results)
def modify_one_group(group_id):
    uid, err = get_oemid(request=request)
    if err is not None:
        return jsonify(UNAUTH_RESULT)

    ctx.current_user = DccaUser.get_by_id(uid)

    empty_check(group_id, error_message='The "group_id" cannot be empty.')

    check_json(request)
    name = get_json(request).get('name')
    input_valid_check(name, error_message='Invalid characters in name.')

    group = DccaDeviceGroup.get_by_id(group_id, uid)

    empty_check(group, error_message='The "group" is not accessable.')

    desc = get_json(request).get('description')

    if not name and not desc:
        return jsonify({
            'status': 'fail',
            'message': 'Empty parameters, not modified'
        })

    if name:
        group.name = name

    if desc:
        group.desc = desc
    elif desc == '':
        group.desc = ''

    group.updated_at = datetime.utcnow()

    try:
        session.add(group)
        session.commit()
    except Exception:
        raise DCCAException('Fail to update group')

    results = OrderedDict()
    results['status'] = 'success'
    results['message'] = 'Success to update group'
    results['group'] = group.as_dict(schema=DeviceGroupSchema)

    return jsonify(results)
def bind_device_to_group(group_id, device_id):
    uid, err = get_oemid(request=request)
    if err is not None:
        return jsonify(UNAUTH_RESULT)

    ctx.current_user = DccaUser.get_by_id(uid)

    empty_check(group_id, error_message='The "group_id" cannot be empty.')
    empty_check(device_id, error_message='The "device_id" cannot be empty')

    group = DccaDeviceGroup.get_by_id(group_id, uid)

    if group is None:
        return jsonify({
            'status': 'fail',
            'message': "The group_id does not exist"
        })

    device = Host.get_by_id(device_id)
    if device is None:
        return jsonify({
            'status': 'fail',
            'message': "The device_id does not exist"
        })

    results = OrderedDict()

    if not device.has_group(group):
        try:
            device.groups.append(group)
            session.add(device)
            session.commit()
        except Exception:
            raise DCCAException('Fail to bind device to group')

        results['status'] = 'success'
        results['message'] = 'Success to add device to group'
        results['group'] = group.as_dict(schema=DeviceGroupBindSchema)
        results['device'] = device.as_dict(schema=DeviceIDSchema)
    else:
        results['status'] = 'fail'
        results[
            'message'] = 'This device already exists in the {} group, please do not add it repeatedly'.format(
                group.name)

    return jsonify(results)
def delete_device_group(group_id):
    uid, err = get_oemid(request=request)
    if err is not None:
        return jsonify(UNAUTH_RESULT)

    ctx.current_user = DccaUser.get_by_id(uid)

    empty_check(group_id, error_message='The "group_id" cannot be empty.')

    group = DccaDeviceGroup.get_by_id(group_id, uid)
    empty_check(group, error_message='The "group" is not accessable.')

    try:
        group.remove()
        session.commit()
    except Exception:
        raise DCCAException('Fail to remove device group')

    results = OrderedDict()
    results['status'] = 'success'
    results['message'] = 'Success to remove group'
    results['group'] = group.as_dict(schema=DeviceGroupSchema)

    return jsonify(results)
def remove_device_from_group(group_id):
    uid, err = get_oemid(request=request)
    if err is not None:
        return jsonify(UNAUTH_RESULT)

    ctx.current_user = DccaUser.get_by_id(uid)

    empty_check(group_id, error_message='The "group_id" cannot be empty.')

    check_json(request)
    device_ids = get_json(request).get('devices')
    empty_check(device_ids, error_message='The "device_ids" cannot be empty')

    group = DccaDeviceGroup.get_by_id(group_id, uid)

    if group is None:
        return jsonify({
            'status': 'fail',
            'message': "The group_id does not exist"
        })

    remove_fail_list = []
    remove_list = []
    for device_id in device_ids:
        device = Host.get_by_id(device_id)
        if device is None:
            bind_fail_dict = {
                'id': device_id,
                'message': 'The device_id does not exist'
            }
            remove_fail_list.append(bind_fail_dict)
        else:
            if device.has_group(group):
                try:
                    group.devices.remove(device)
                    session.commit()
                    remove_list.append(device)
                except Exception as e:
                    bind_fail_dict = {'id': device_id, 'message': e}
                    remove_fail_list.append(bind_fail_dict)
                    raise DCCAException('Fail to bind device to group')
            else:
                message = 'This device already exists in the {} group, please do not add it repeatedly'.format(
                    group.name)
                bind_fail_dict = {'id': device_id, 'message': message}
                remove_fail_list.append(bind_fail_dict)

    results = OrderedDict()
    if len(remove_list) == 0:
        results['status'] = "fail"
        results['message'] = "Fail to unbind device from group"
        results['group'] = group.as_dict(schema=DeviceGroupBindSchema)
        results['devices'] = {}
    else:
        results['status'] = "success"
        results['message'] = "Success to remove device from group"
        results['group'] = group.as_dict(schema=DeviceGroupBindSchema)
        results['devices'] = {}
        results['devices']['success'] = []
        results['devices']['success_total'] = len(remove_list)
        for device in remove_list:
            results['devices']['success'].append(
                device.as_dict(schema=DeviceIDSchema))
    results['devices']['fail'] = []
    results['devices']['fail_total'] = len(remove_fail_list)
    for device_fail in remove_fail_list:
        results['devices']['fail'].append(device_fail)

    return jsonify(results)
def group_create_tasks():
    uid, err = get_oemid(request=request)
    if err is not None:
        return jsonify(UNAUTH_RESULT)

    ctx.current_user = DccaUser.get_by_id(uid)

    check_json(request)
    group_id = get_json(request).get('group_id')
    task_type = get_json(request).get('type')
    payloads = get_json(request).get('payload')
    # workaround it is not a uuid, group id
    if group_id and len(str(group_id)) < 32:
        device_list = DccaAssHostModel.get_model_deviceid(int(group_id))
    else:
        group = DccaDeviceGroup.get_by_id(group_id, uid)
        empty_check(group, error_message='The "group" is not accessable.')
        device_list = DccaDeviceGroup.query_bind_model_devices(group_id, uid)
    if not device_list or len(device_list) < 1:
        return jsonify({
            'status': 'fail',
            'message': 'There are no devices in this device group'
        })
    device_list = set(device_list)
    device_ids = [device_id[0] for device_id in device_list]

    devices = Host.query_in(device_ids)
    if len(devices) != len(device_ids):
        return jsonify({
            'status':
            'fail',
            'message':
            'Not authorized devices exist. Device not exist or cannot access',
            'not_authorized_devices':
            list(set(device_ids) - set([d.id for d in devices]))
        })

    if task_type not in list(TASK_TYPE_NAMES.values()):
        return jsonify({'status': 'fail', 'message': 'No such kind of task'})

    try:
        inst_list = []
        if task_type == TASK_TYPE_NAMES[TASK_TYPE_APP]:
            unauthoried = EsTask.check_da_payload(payloads)
            if unauthoried:
                return jsonify({
                    'status': 'fail',
                    'message':
                    'Unauthorized application exists, not exist or cannot access.',
                    'unauthorized': unauthoried
                })

            task = EsTask.create_da_task(payloads)
            session.add(task)
            session.flush()
            for pl in payloads:
                softapp = DccaSoftapp.get(pl['softapp_id'])
                del pl['softapp_id']
                for device in devices:
                    inst = task.da_inst(device, softapp, pl)
                    session.add(inst)
                    inst_list.append(inst)
            session.commit()
        elif task_type == TASK_TYPE_NAMES[TASK_TYPE_SOLUTION]:
            authed, solution = EsTask.check_ota_payload(payloads)
            if not authed:
                return jsonify({
                    'status':
                    'fail',
                    'message':
                    'Solution not exist or cannot access.'
                })

            task = EsTask.create_ota_task(payloads)
            session.add(task)
            session.flush()
            for device in devices:
                inst = task.ota_inst(device, solution)
                session.add(inst)
                inst_list.append(inst)
            session.commit()
        else:
            return jsonify({
                'status': 'fail',
                'message': 'No such kind of task'
            })

        try:
            for inst in inst_list:
                if inst.task.type == TASK_TYPE_APP:
                    print(('Start da task: ', inst))
                    inst.start(APPSERVER_HOST, APPSERVER_PORT)
                elif inst.task.type == TASK_TYPE_SOLUTION:
                    print('Start ota task')
                    inst.start(MQTT_HOST)
        except Exception:
            import traceback
            traceback.print_exc()
            session.rollback()
        else:
            session.commit()

        results = OrderedDict()
        results['status'] = 'success'
        results['message'] = 'Success to create the task'
        results['task'] = task.as_dict(schema=TaskSchema)
        return jsonify(results)
    except Exception as e:
        raise DCCAException(str(e))