This repository has been archived on 2024-05-31. You can view files and clone it, but cannot push or open issues or pull requests.
devicehub-teal/ereuse_devicehub/resources/event/schemas.py

562 lines
22 KiB
Python
Raw Normal View History

2018-06-20 21:18:15 +00:00
from flask import current_app as app
from marshmallow import Schema as MarshmallowSchema, ValidationError, fields as f, validates_schema
from marshmallow.fields import Boolean, DateTime, Decimal, Float, Integer, List, Nested, String, \
TimeDelta, UUID
2018-11-26 12:11:07 +00:00
from marshmallow.validate import Length, OneOf, Range
from sqlalchemy.util import OrderedSet
2018-09-07 10:38:02 +00:00
from teal.enums import Country, Currency, Subdivision
from teal.marshmallow import EnumField, IP, SanitizedStr, URL, Version
2018-09-07 10:38:02 +00:00
from teal.resource import Schema
2018-06-20 21:18:15 +00:00
2018-04-27 17:16:43 +00:00
from ereuse_devicehub.marshmallow import NestedOn
from ereuse_devicehub.resources import enums
from ereuse_devicehub.resources.agent import schemas as s_agent
from ereuse_devicehub.resources.device import schemas as s_device
2018-06-10 16:47:49 +00:00
from ereuse_devicehub.resources.enums import AppearanceRange, Bios, FunctionalityRange, \
PhysicalErasureMethod, PriceSoftware, RATE_POSITIVE, RatingRange, RatingSoftware, ReceiverRole, \
Severity, SnapshotExpectedEvents, SnapshotSoftware, TestDataStorageLength, FunctionalityRangev2
2018-06-12 14:50:05 +00:00
from ereuse_devicehub.resources.event import models as m
2018-04-27 17:16:43 +00:00
from ereuse_devicehub.resources.models import STR_BIG_SIZE, STR_SIZE
from ereuse_devicehub.resources.schemas import Thing
from ereuse_devicehub.resources.user import schemas as s_user
2018-04-27 17:16:43 +00:00
class Event(Thing):
__doc__ = m.Event.__doc__
2018-06-15 13:31:03 +00:00
id = UUID(dump_only=True)
name = SanitizedStr(default='',
validate=Length(max=STR_BIG_SIZE),
description=m.Event.name.comment)
closed = Boolean(missing=True, description=m.Event.closed.comment)
severity = EnumField(Severity, description=m.Event.severity.comment)
description = SanitizedStr(default='', description=m.Event.description.comment)
start_time = DateTime(data_key='startTime', description=m.Event.start_time.comment)
end_time = DateTime(data_key='endTime', description=m.Event.end_time.comment)
snapshot = NestedOn('Snapshot', dump_only=True)
agent = NestedOn(s_agent.Agent, description=m.Event.agent_id.comment)
author = NestedOn(s_user.User, dump_only=True, exclude=('token',))
components = NestedOn(s_device.Component, dump_only=True, many=True)
parent = NestedOn(s_device.Computer, dump_only=True, description=m.Event.parent_id.comment)
url = URL(dump_only=True, description=m.Event.url.__doc__)
2018-04-27 17:16:43 +00:00
class EventWithOneDevice(Event):
__doc__ = m.EventWithOneDevice.__doc__
device = NestedOn(s_device.Device, only_query='id')
2018-04-27 17:16:43 +00:00
class EventWithMultipleDevices(Event):
__doc__ = m.EventWithMultipleDevices.__doc__
devices = NestedOn(s_device.Device, many=True, only_query='id', collection_class=OrderedSet)
2018-04-27 17:16:43 +00:00
class Add(EventWithOneDevice):
__doc__ = m.Add.__doc__
2018-04-27 17:16:43 +00:00
class Remove(EventWithOneDevice):
__doc__ = m.Remove.__doc__
2018-04-27 17:16:43 +00:00
class Allocate(EventWithMultipleDevices):
__doc__ = m.Allocate.__doc__
to = NestedOn(s_user.User,
description='The user the devices are allocated to.')
organization = SanitizedStr(validate=Length(max=STR_SIZE),
description='The organization where the '
'user was when this happened.')
2018-04-27 17:16:43 +00:00
class Deallocate(EventWithMultipleDevices):
__doc__ = m.Deallocate.__doc__
from_rel = Nested(s_user.User,
2018-04-27 17:16:43 +00:00
data_key='from',
description='The user where the devices are not allocated to anymore.')
organization = SanitizedStr(validate=Length(max=STR_SIZE),
description='The organization where the '
'user was when this happened.')
2018-04-27 17:16:43 +00:00
class EraseBasic(EventWithOneDevice):
__doc__ = m.EraseBasic.__doc__
steps = NestedOn('Step', many=True)
standards = f.List(EnumField(enums.ErasureStandards), dump_only=True)
2018-12-30 11:43:29 +00:00
certificate = URL(dump_only=True)
2018-04-27 17:16:43 +00:00
class EraseSectors(EraseBasic):
__doc__ = m.EraseSectors.__doc__
2018-04-27 17:16:43 +00:00
class ErasePhysical(EraseBasic):
__doc__ = m.ErasePhysical.__doc__
method = EnumField(PhysicalErasureMethod, description=PhysicalErasureMethod.__doc__)
2018-04-27 17:16:43 +00:00
class Step(Schema):
__doc__ = m.Step.__doc__
2018-06-10 16:47:49 +00:00
type = String(description='Only required when it is nested.')
start_time = DateTime(required=True, data_key='startTime')
end_time = DateTime(required=True, data_key='endTime')
severity = EnumField(Severity, description=m.Event.severity.comment)
2018-06-10 16:47:49 +00:00
class StepZero(Step):
__doc__ = m.StepZero.__doc__
2018-06-10 16:47:49 +00:00
class StepRandom(Step):
__doc__ = m.StepRandom.__doc__
2018-06-10 16:47:49 +00:00
2018-06-10 16:47:49 +00:00
class Rate(EventWithOneDevice):
__doc__ = m.Rate.__doc__
2018-06-10 16:47:49 +00:00
rating = Integer(validate=Range(*RATE_POSITIVE),
dump_only=True,
description=m.Rate.rating.comment)
2018-07-14 14:41:22 +00:00
software = EnumField(RatingSoftware,
dump_only=True,
description=m.Rate.software.comment)
2018-07-14 14:41:22 +00:00
version = Version(dump_only=True,
description=m.Rate.version.comment)
2018-06-10 16:47:49 +00:00
appearance = Integer(validate=Range(-3, 5), dump_only=True)
2018-10-15 12:20:26 +00:00
functionality = Integer(validate=Range(-3, 5), dump_only=True)
rating_range = EnumField(RatingRange, dump_only=True, data_key='ratingRange')
2018-06-10 16:47:49 +00:00
class IndividualRate(Rate):
__doc__ = m.IndividualRate.__doc__
2018-06-10 16:47:49 +00:00
2018-06-20 21:18:15 +00:00
class ManualRate(IndividualRate):
__doc__ = m.ManualRate.__doc__
2018-06-10 16:47:49 +00:00
appearance_range = EnumField(AppearanceRange,
required=True,
data_key='appearanceRange',
2018-10-14 09:37:10 +00:00
description=m.ManualRate.appearance_range.comment)
2018-06-10 16:47:49 +00:00
functionality_range = EnumField(FunctionalityRange,
required=True,
data_key='functionalityRange',
2018-10-14 09:37:10 +00:00
description=m.ManualRate.functionality_range.comment)
labelling = Boolean(description=m.ManualRate.labelling.comment)
2018-06-20 21:18:15 +00:00
class WorkbenchRate(ManualRate):
__doc__ = m.WorkbenchRate.__doc__
2018-06-20 21:18:15 +00:00
processor = Float()
ram = Float()
data_storage = Float()
graphic_card = Float()
2018-10-14 09:37:10 +00:00
bios = Float()
bios_range = EnumField(Bios,
description=m.WorkbenchRate.bios_range.comment,
data_key='biosRange')
data_storage_range = EnumField(RatingRange, dump_only=True, data_key='dataStorageRange')
ram_range = EnumField(RatingRange, dump_only=True, data_key='ramRange')
processor_range = EnumField(RatingRange, dump_only=True, data_key='processorRange')
graphic_card_range = EnumField(RatingRange, dump_only=True, data_key='graphicCardRange')
2018-06-10 16:47:49 +00:00
"""
WORKBENCH RATE COMPUTER
Adaptation of old class WorkbenchRate
"""
class WorkbenchRateComputer(ManualRate):
__doc__ = m.WorkbenchRate.__doc__
processor = Float()
ram = Float()
data_storage = Float()
graphic_card = Float()
bios = Float()
bios_range = EnumField(Bios,
description=m.WorkbenchComputerRate.bios_range.comment,
data_key='biosRange')
data_storage_range = EnumField(RatingRange, dump_only=True, data_key='dataStorageRange')
ram_range = EnumField(RatingRange, dump_only=True, data_key='ramRange')
processor_range = EnumField(RatingRange, dump_only=True, data_key='processorRange')
graphic_card_range = EnumField(RatingRange, dump_only=True, data_key='graphicCardRange')
class AggregateRate(Rate):
__doc__ = m.AggregateRate.__doc__
workbench = NestedOn(WorkbenchRate, dump_only=True,
description=m.AggregateRate.workbench_id.comment)
manual = NestedOn(ManualRate,
dump_only=True,
description=m.AggregateRate.manual_id.comment)
processor = Float(dump_only=True)
ram = Float(dump_only=True)
data_storage = Float(dump_only=True)
graphic_card = Float(dump_only=True)
bios = EnumField(Bios, dump_only=True)
2018-10-15 12:20:26 +00:00
bios_range = EnumField(Bios,
description=m.WorkbenchRate.bios_range.comment,
data_key='biosRange')
appearance_range = EnumField(AppearanceRange,
required=True,
data_key='appearanceRange',
description=m.ManualRate.appearance_range.comment)
functionality_range = EnumField(FunctionalityRange,
required=True,
data_key='functionalityRange',
description=m.ManualRate.functionality_range.comment)
labelling = Boolean(description=m.ManualRate.labelling.comment)
data_storage_range = EnumField(RatingRange, dump_only=True, data_key='dataStorageRange')
ram_range = EnumField(RatingRange, dump_only=True, data_key='ramRange')
processor_range = EnumField(RatingRange, dump_only=True, data_key='processorRange')
graphic_card_range = EnumField(RatingRange, dump_only=True, data_key='graphicCardRange')
class QualityRate(Rate):
__doc__ = m.QualityRate.__doc__
ram = Float(dump_only=True, description=m.QualityRate.ram.comment)
processor = Float(dump_only=True, description=m.QualityRate.processor.comment)
data_storage = Float(dump_only=True, description=m.QualityRate.data_storage.comment)
""" New class for WorkbenchRate in Rate v2"""
class QualityRateComputer(Rate):
__doc__ = m.QualityRateComputer.__doc__
""" List of components appears in general quality rate a device
ram = Float(dump_only=True, description=m.QualityRateComputer.ram.comment)
processor = Float(dump_only=True, description=m.QualityRateComputer.processor.comment)
data_storage = Float(dump_only=True, description=m.QualityRateComputer.data_storage.comment)
"""
graphic_card = Float(dump_only=True, description=m.QualityRateComputer.processor.comment)
network_adapter = Float(dump_only=True, description=m.QualityRateComputer.network_adapter.comment)
class QualityRateMobile(Rate):
__doc__ = m.QualityRateMobile.__doc__
""" List of components appears in general quality rate a device
ram = Float(dump_only=True, description=m.QualityRateMobile.ram.comment)
processor = Float(dump_only=True, description=m.QualityRateMobile.processor.comment)
data_storage = Float(dump_only=True, description=m.QualityRateMobile.data_storage.comment)
"""
display = Float(dump_only=True, description=m.QualityRateMobile.display.comment)
battery = Float(dump_only=True, description=m.QualityRateMobile.batter.comment)
camera = Float(dump_only=True, description=m.QualityRateMobile.camera.comment)
class FunctionalityRate(Rate):
__doc__ = m.FunctionalityRate.__doc__
functionality = EnumField(dump_only=True, description=m.FunctionalityRate.functionality.comment)
functionality_range = EnumField(dump_only=True, description=m.FunctionalityRate.functionality_range.comment)
connectivity_rate = EnumField(dump_only=True, description=m.FunctionalityRate.connectivity_rate.comment)
audio_rate = EnumField(dump_only=True, description=m.FunctionalityRate.audio_rate.comment)
class FinalRate(Rate):
__doc__ = m.FinalRate.__doc__
workbench_computer = NestedOn(WorkbenchComputer, dump_only=True,
description=m.ResultRate.workbench_computer_id.comment)
workbench_mobile = NestedOn(WorkbenchMobile, dump_only=True,
description=m.ResultRate.workbench_mobile_id.comment)
bios = EnumField(Bios, dump_only=True)
bios_range = EnumField(Bios,
description=m.WorkbenchRate.bios_range.comment,
data_key='biosRange')
# TODO Finish input rates (internal and external sources) - Whats really interesting to save in BD?? Whichs aspects?
class ResultRate(Rate):
__doc__ = m.ResultRate.__doc__
# TODO ask for what to do NestedOn??
workbench_computer = NestedOn(WorkbenchRateComputer, dump_only=True,
description=m.ResultRate.workbench_computer_id.comment)
workbench_mobile = NestedOn(WorkbenchRateMobile, dump_only=True,
description=m.ResultRate.workbench_mobile_id.comment)
manual_computer = NestedOn(ManualRateComputer,
dump_only=True,
description=m.ResultRate.manual_computer_id.comment)
processor = Float(dump_only=True)
ram = Float(dump_only=True)
data_storage = Float(dump_only=True)
graphic_card = Float(dump_only=True)
bios = EnumField(Bios, dump_only=True)
bios_range = EnumField(Bios,
description=m.WorkbenchRate.bios_range.comment,
data_key='biosRange')
appearance_range = EnumField(AppearanceRange,
required=True,
data_key='appearanceRange',
description=m.ManualRate.appearance_range.comment)
functionality_range = EnumField(FunctionalityRange,
required=True,
data_key='functionalityRange',
description=m.ManualRate.functionality_range.comment)
labelling = Boolean(description=m.ManualRate.labelling.comment)
data_storage_range = EnumField(RatingRange, dump_only=True, data_key='dataStorageRange')
ram_range = EnumField(RatingRange, dump_only=True, data_key='ramRange')
processor_range = EnumField(RatingRange, dump_only=True, data_key='processorRange')
graphic_card_range = EnumField(RatingRange, dump_only=True, data_key='graphicCardRange')
2018-07-14 14:41:22 +00:00
class Price(EventWithOneDevice):
__doc__ = m.Price.__doc__
currency = EnumField(Currency, required=True, description=m.Price.currency.comment)
2018-10-15 09:21:21 +00:00
price = Decimal(places=m.Price.SCALE,
rounding=m.Price.ROUND,
required=True,
description=m.Price.price.comment)
software = EnumField(PriceSoftware, dump_only=True, description=m.Price.software.comment)
version = Version(dump_only=True, description=m.Price.version.comment)
rating = NestedOn(AggregateRate, dump_only=True, description=m.Price.rating_id.comment)
2018-07-14 14:41:22 +00:00
class EreusePrice(Price):
__doc__ = m.EreusePrice.__doc__
2018-07-14 14:41:22 +00:00
class Service(MarshmallowSchema):
class Type(MarshmallowSchema):
amount = Float()
percentage = Float()
standard = Nested(Type)
warranty2 = Nested(Type)
warranty2 = Float()
refurbisher = Nested(Service)
retailer = Nested(Service)
platform = Nested(Service)
2018-06-10 16:47:49 +00:00
class Install(EventWithOneDevice):
__doc__ = m.Install.__doc__
name = SanitizedStr(validate=Length(min=4, max=STR_BIG_SIZE),
required=True,
description='The name of the OS installed.')
2018-04-27 17:16:43 +00:00
elapsed = TimeDelta(precision=TimeDelta.SECONDS, required=True)
2018-11-26 12:11:07 +00:00
address = Integer(validate=OneOf({8, 16, 32, 64, 128, 256}))
2018-04-27 17:16:43 +00:00
class Snapshot(EventWithOneDevice):
__doc__ = m.Snapshot.__doc__
"""
The Snapshot updates the state of the device with information about
its components and events performed at them.
See docs for more info.
"""
2018-06-20 21:18:15 +00:00
uuid = UUID()
2018-06-10 16:47:49 +00:00
software = EnumField(SnapshotSoftware,
required=True,
description='The software that generated this Snapshot.')
version = Version(required=True, description='The version of the software.')
events = NestedOn(Event, many=True, dump_only=True)
2018-06-19 16:38:42 +00:00
expected_events = List(EnumField(SnapshotExpectedEvents),
data_key='expectedEvents',
description='Keep open this Snapshot until the following events'
'are performed. Setting this value will activate'
'the async Snapshot.')
2018-06-20 21:18:15 +00:00
elapsed = TimeDelta(precision=TimeDelta.SECONDS)
components = NestedOn(s_device.Component,
many=True,
description='A list of components that are inside of the device'
'at the moment of this Snapshot.'
'Order is preserved, so the component num 0 when'
'submitting is the component num 0 when returning it back.')
2018-04-27 17:16:43 +00:00
@validates_schema
def validate_workbench_version(self, data: dict):
2018-06-10 16:47:49 +00:00
if data['software'] == SnapshotSoftware.Workbench:
2018-04-27 17:16:43 +00:00
if data['version'] < app.config['MIN_WORKBENCH']:
raise ValidationError(
2018-07-14 14:41:22 +00:00
'Min. supported Workbench version is '
'{} but yours is {}.'.format(app.config['MIN_WORKBENCH'], data['version']),
2018-04-27 17:16:43 +00:00
field_names=['version']
)
@validates_schema
def validate_components_only_workbench(self, data: dict):
2018-06-10 16:47:49 +00:00
if data['software'] != SnapshotSoftware.Workbench:
2018-06-20 21:18:15 +00:00
if data.get('components', None) is not None:
2018-04-27 17:16:43 +00:00
raise ValidationError('Only Workbench can add component info',
field_names=['components'])
2018-06-20 21:18:15 +00:00
@validates_schema
def validate_only_workbench_fields(self, data: dict):
"""Ensures workbench has ``elapsed`` and ``uuid`` and no others."""
# todo test
if data['software'] == SnapshotSoftware.Workbench:
if not data.get('uuid', None):
raise ValidationError('Snapshots from Workbench must have uuid',
field_names=['uuid'])
if data.get('elapsed', None) is None:
2018-06-20 21:18:15 +00:00
raise ValidationError('Snapshots from Workbench must have elapsed',
field_names=['elapsed'])
else:
if data.get('uuid', None):
raise ValidationError('Only Snapshots from Workbench can have uuid',
field_names=['uuid'])
if data.get('elapsed', None):
raise ValidationError('Only Snapshots from Workbench can have elapsed',
field_names=['elapsed'])
2018-04-27 17:16:43 +00:00
class Test(EventWithOneDevice):
__doc__ = m.Test.__doc__
2018-04-27 17:16:43 +00:00
elapsed = TimeDelta(precision=TimeDelta.SECONDS, required=True)
2018-06-10 16:47:49 +00:00
class TestDataStorage(Test):
__doc__ = m.TestDataStorage.__doc__
length = EnumField(TestDataStorageLength, required=True)
status = SanitizedStr(lower=True, validate=Length(max=STR_SIZE), required=True)
lifetime = TimeDelta(precision=TimeDelta.HOURS)
2018-06-19 16:38:42 +00:00
assessment = Boolean()
reallocated_sector_count = Integer(data_key='reallocatedSectorCount')
power_cycle_count = Integer(data_key='powerCycleCount')
reported_uncorrectable_errors = Integer(data_key='reportedUncorrectableErrors')
command_timeout = Integer(data_key='commandTimeout')
current_pending_sector_count = Integer(data_key='currentPendingSectorCount')
offline_uncorrectable = Integer(data_key='offlineUncorrectable')
remaining_lifetime_percentage = Integer(data_key='remainingLifetimePercentage')
2018-04-27 17:16:43 +00:00
class StressTest(Test):
__doc__ = m.StressTest.__doc__
2018-06-19 16:38:42 +00:00
class Benchmark(EventWithOneDevice):
__doc__ = m.Benchmark.__doc__
elapsed = TimeDelta(precision=TimeDelta.SECONDS, required=True)
2018-06-19 16:38:42 +00:00
class BenchmarkDataStorage(Benchmark):
__doc__ = m.BenchmarkDataStorage.__doc__
2018-06-19 16:38:42 +00:00
read_speed = Float(required=True, data_key='readSpeed')
write_speed = Float(required=True, data_key='writeSpeed')
class BenchmarkWithRate(Benchmark):
__doc__ = m.BenchmarkWithRate.__doc__
rate = Float(required=True)
2018-06-19 16:38:42 +00:00
class BenchmarkProcessor(BenchmarkWithRate):
__doc__ = m.BenchmarkProcessor.__doc__
2018-06-19 16:38:42 +00:00
class BenchmarkProcessorSysbench(BenchmarkProcessor):
__doc__ = m.BenchmarkProcessorSysbench.__doc__
2018-06-19 16:38:42 +00:00
class BenchmarkRamSysbench(BenchmarkWithRate):
__doc__ = m.BenchmarkRamSysbench.__doc__
class ToRepair(EventWithMultipleDevices):
__doc__ = m.ToRepair.__doc__
class Repair(EventWithMultipleDevices):
__doc__ = m.Repair.__doc__
class ReadyToUse(EventWithMultipleDevices):
__doc__ = m.ReadyToUse.__doc__
class ToPrepare(EventWithMultipleDevices):
__doc__ = m.ToPrepare.__doc__
class Prepare(EventWithMultipleDevices):
__doc__ = m.Prepare.__doc__
class Live(EventWithOneDevice):
__doc__ = m.Live.__doc__
ip = IP(dump_only=True)
subdivision_confidence = Integer(dump_only=True, data_key='subdivisionConfidence')
subdivision = EnumField(Subdivision, dump_only=True)
country = EnumField(Country, dump_only=True)
city = SanitizedStr(lower=True, dump_only=True)
city_confidence = Integer(dump_only=True, data_key='cityConfidence')
isp = SanitizedStr(lower=True, dump_only=True)
organization = SanitizedStr(lower=True, dump_only=True)
organization_type = SanitizedStr(lower=True, dump_only=True, data_key='organizationType')
class Organize(EventWithMultipleDevices):
__doc__ = m.Organize.__doc__
class Reserve(Organize):
__doc__ = m.Reserve.__doc__
class CancelReservation(Organize):
__doc__ = m.CancelReservation.__doc__
class Trade(EventWithMultipleDevices):
__doc__ = m.Trade.__doc__
shipping_date = DateTime(data_key='shippingDate')
invoice_number = SanitizedStr(validate=Length(max=STR_SIZE), data_key='invoiceNumber')
price = NestedOn(Price)
to = NestedOn(s_agent.Agent, only_query='id', required=True, comment=m.Trade.to_comment)
confirms = NestedOn(Organize)
class Sell(Trade):
__doc__ = m.Sell.__doc__
class Donate(Trade):
__doc__ = m.Donate.__doc__
class Rent(Trade):
__doc__ = m.Rent.__doc__
class CancelTrade(Trade):
__doc__ = m.CancelTrade.__doc__
class ToDisposeProduct(Trade):
__doc__ = m.ToDisposeProduct.__doc__
class DisposeProduct(Trade):
__doc__ = m.DisposeProduct.__doc__
class Receive(EventWithMultipleDevices):
__doc__ = m.Receive.__doc__
role = EnumField(ReceiverRole)
class Migrate(EventWithMultipleDevices):
__doc__ = m.Migrate.__doc__
other = URL()
class MigrateTo(Migrate):
__doc__ = m.MigrateTo.__doc__
class MigrateFrom(Migrate):
__doc__ = m.MigrateFrom.__doc__