First real snapshots :-)

This commit is contained in:
Xavier Bustamante Talavera 2018-07-02 12:52:54 +02:00
parent cd8928e1cd
commit af885c2aec
23 changed files with 732 additions and 121 deletions

View file

@ -75,4 +75,17 @@ Devicehub has many commands that allows you to administrate it. You
can, for example, create a dummy database of devices with ``flask dummy``
or create users with ``flask create-user``. See all the
available commands by just executing ``flask`` and get more information
per command by executing ``flask command --help``.
per command by executing ``flask command --help``.
## Understand the software
See the [docs](docs/index.rst) to understand how the software works and
the design principles.
### Use the API
Checkout [Swagger](https://app.swaggerhub.com/apis/ereuse/devicehub/0.2)
to see the schemas and endpoints (we are working in making it
interactive).
Use postman as an example of how to use the API.
[![Run in Postman](https://run.pstmn.io/button.svg)](https://documenter.getpostman.com/view/254251/RWEnmFPs)

View file

@ -5,7 +5,7 @@ from ereuse_devicehub.resources.device import CellphoneDef, ComponentDef, Comput
ComputerMonitorDef, DataStorageDef, DesktopDef, DeviceDef, DisplayDef, GraphicCardDef, \
HardDriveDef, LaptopDef, MobileDef, MonitorDef, MotherboardDef, NetworkAdapterDef, \
ProcessorDef, RamModuleDef, ServerDef, SmartphoneDef, SolidStateDriveDef, TabletDef, \
TelevisionSetDef
TelevisionSetDef, SoundCardDef
from ereuse_devicehub.resources.event import AddDef, AggregateRateDef, AppRateDef, \
BenchmarkDataStorageDef, BenchmarkDef, BenchmarkProcessorDef, BenchmarkProcessorSysbenchDef, \
BenchmarkRamSysbenchDef, BenchmarkWithRateDef, EraseBasicDef, EraseSectorsDef, EventDef, \
@ -23,7 +23,8 @@ class DevicehubConfig(Config):
DeviceDef, ComputerDef, DesktopDef, LaptopDef, ServerDef, MonitorDef, TelevisionSetDef,
ComputerMonitorDef, ComponentDef, GraphicCardDef, DataStorageDef,
SolidStateDriveDef, MobileDef, DisplayDef, SmartphoneDef, TabletDef, CellphoneDef,
HardDriveDef, MotherboardDef, NetworkAdapterDef, RamModuleDef, ProcessorDef, UserDef,
HardDriveDef, MotherboardDef, NetworkAdapterDef, RamModuleDef, ProcessorDef, SoundCardDef,
UserDef,
OrganizationDef, TagDef, EventDef, AddDef, RemoveDef, EraseBasicDef, EraseSectorsDef,
StepDef, StepZeroDef, StepRandomDef, RateDef, AggregateRateDef, WorkbenchRateDef,
PhotoboxUserDef, PhotoboxSystemRateDef, InstallDef, SnapshotDef, TestDef,
@ -33,7 +34,7 @@ class DevicehubConfig(Config):
}
PASSWORD_SCHEMES = {'pbkdf2_sha256'} # type: Set[str]
SQLALCHEMY_DATABASE_URI = 'postgresql://dhub:ereuse@localhost/devicehub' # type: str
MIN_WORKBENCH = StrictVersion('11.0') # type: StrictVersion
MIN_WORKBENCH = StrictVersion('11.0a1') # type: StrictVersion
"""
the minimum algorithm_version of ereuse.org workbench that this devicehub
accepts. we recommend not changing this value.

View file

@ -3,11 +3,10 @@ from pathlib import Path
import click
import click_spinner
import yaml
from tqdm import tqdm
from ereuse_devicehub.client import UserClient
from ereuse_devicehub.db import db
from ereuse_devicehub.resources.event.models import Snapshot
from ereuse_devicehub.resources.inventory import Inventory
from ereuse_devicehub.resources.tag.model import Tag
from ereuse_devicehub.resources.user import User
@ -32,16 +31,21 @@ class Dummy:
@click.confirmation_option(prompt='This command deletes the DB in the process. '
'Do you want to continue?')
def run(self):
print('Preparing the database...')
print('Preparing the database...'.ljust(30), end='')
with click_spinner.spinner():
self.app.init_db(erase=True)
user = self.user_client('user@dhub.com', '1234')
user.post(res=Tag, query=[('ids', i) for i in self.TAGS], data={})
print('Creating devices...')
for file_name in tqdm(self.SNAPSHOTS):
snapshot = self.file(file_name)
user.post(res=Snapshot, data=snapshot)
print('Done :-)')
files = tuple(Path(__file__).parent.joinpath('files').iterdir())
print('done.')
with click.progressbar(files, label='Creating devices...'.ljust(28)) as bar:
for path in bar:
with path.open() as f:
snapshot = yaml.load(f)
user.post(res=Snapshot, data=snapshot)
inventory, _ = user.get(res=Inventory)
assert len(inventory['devices'])
print('⭐ Done.')
def user_client(self, email: str, password: str):
user = User(email=email, password=password)
@ -53,10 +57,3 @@ class Dummy:
password=password)
client.user, _ = client.login(client.email, client.password)
return client
def file(self, name: str):
with Path(__file__) \
.parent \
.joinpath('files') \
.joinpath(name + '.snapshot.yaml').open() as f:
return yaml.load(f)

View file

@ -0,0 +1,160 @@
{
"closed": false,
"uuid": "f9e5e587-baee-44e1-9a94-255d216bbda9",
"components": [
{
"events": [],
"serialNumber": "6c:62:6d:81:22:9f",
"type": "NetworkAdapter",
"manufacturer": "Intel Corporation",
"speed": 1000,
"model": "82578DM Gigabit Network Connection"
},
{
"format": "DIMM",
"events": [
],
"interface": "DDR3",
"serialNumber": "B4012F30",
"size": 2048,
"type": "RamModule",
"manufacturer": "JEDEC ID:80 2C",
"speed": 1333.0,
"model": "16JTF25664AZ-1G4F"
},
{
"format": "DIMM",
"events": [],
"interface": "DDR3",
"serialNumber": "8E9F2E29",
"size": 2048,
"type": "RamModule",
"manufacturer": "JEDEC ID:80 2C",
"speed": 1333.0,
"model": "16JTF25664AZ-1G4F"
},
{
"format": "DIMM",
"events": [],
"interface": "DDR3",
"serialNumber": "9A012F30",
"size": 2048,
"type": "RamModule",
"manufacturer": "JEDEC ID:80 2C",
"speed": 1333.0,
"model": "16JTF25664AZ-1G4F"
},
{
"format": "DIMM",
"events": [
],
"interface": "DDR3",
"serialNumber": "8F9F2E29",
"size": 2048,
"type": "RamModule",
"manufacturer": "JEDEC ID:80 2C",
"speed": 1333.0,
"model": "16JTF25664AZ-1G4F"
},
{
"cores": 2,
"events": [
{
"rate": 23410.76,
"type": "BenchmarkProcessor",
"elapsed": 1
},
{
"rate": 17.0186,
"type": "BenchmarkProcessorSysbench",
"elapsed": 18
}
],
"serialNumber": null,
"type": "Processor",
"manufacturer": "Intel Corp.",
"address": 64,
"speed": 1.199,
"model": "Intel Core i3 CPU 530 @ 2.93GHz"
},
{
"events": [
{
"writeSpeed": 24.5,
"readSpeed": 111.0,
"type": "BenchmarkDataStorage",
"elapsed": 14
},
{
"status": "Unspecified Error. Self-test not started.",
"error": true,
"type": "TestDataStorage",
"elapsed": 1,
"length": Short
}
],
"interface": "ATA",
"serialNumber": "WD-WCAV2U909540",
"size": 305245,
"type": "HardDrive",
"manufacturer": "Western Digital",
"model": "WDC WD3200AAJS-6"
},
{
"events": [],
"serialNumber": null,
"type": "SoundCard",
"manufacturer": "Intel Corporation",
"model": "5 Series/3400 Series Chipset High Definition Audio"
},
{
"memory": 256.0,
"events": [],
"serialNumber": null,
"type": "GraphicCard",
"manufacturer": "Intel Corporation",
"model": "Core Processor Integrated Graphics Controller"
},
{
"events": [],
"firewire": 0,
"pcmcia": 0,
"serialNumber": "CZC0408YJG",
"slots": 0,
"type": "Motherboard",
"manufacturer": "Hewlett-Packard",
"usb": 2,
"serial": 0,
"model": "304Ah"
}
],
"software": "Workbench",
"elapsed": 96,
"version": "11.0a1",
"expectedEvents": [
"StressTest",
"Benchmark",
"SmartTest"
],
"device": {
"events": [
{
"type": "StressTest",
"elapsed": 60,
"error": false
},
{
"rate": 0.9759,
"type": "BenchmarkRamSysbench",
"elapsed": 1
}
],
"serialNumber": "CZC0408YJG",
"type": "Desktop",
"manufacturer": "Hewlett-Packard",
"chassis": "Tower",
"model": "HP Compaq 8100 Elite SFF"
},
"type": "Snapshot",
"date": "2018-06-29T12:28:54.508266"
}

View file

@ -0,0 +1,139 @@
{
"expectedEvents": [
"SmartTest",
"Benchmark",
"StressTest"
],
"date": "2018-06-29T15:29:29.322424",
"elapsed": 391,
"software": "Workbench",
"components": [
{
"serialNumber": null,
"interface": "DDR",
"size": 1024,
"manufacturer": null,
"format": "SODIMM",
"events": [
],
"speed": 533.0,
"type": "RamModule",
"model": null
},
{
"serialNumber": null,
"manufacturer": "Intel Corporation",
"events": [],
"type": "SoundCard",
"model": "NM10/ICH7 Family High Definition Audio Controller"
},
{
"serialNumber": null,
"manufacturer": "Chicony Electronics Co., Ltd.",
"events": [],
"type": "SoundCard",
"model": "USB2.0 UVC WebCam"
},
{
"serialNumber": "00:23:08:a5:07:6d",
"manufacturer": "Qualcomm Atheros",
"events": [],
"type": "NetworkAdapter",
"model": "AR9285 Wireless Network Adapter"
},
{
"serialNumber": "00:23:5a:fe:d7:14",
"manufacturer": "Realtek Semiconductor Co., Ltd.",
"events": [],
"speed": 100,
"type": "NetworkAdapter",
"model": "RTL810xE PCI Express Fast Ethernet controller"
},
{
"serialNumber": null,
"address": 32,
"manufacturer": "Intel Corp.",
"events": [
{
"rate": 171.3049,
"type": "BenchmarkProcessorSysbench",
"elapsed": 171
},
{
"rate": 6383.9,
"type": "BenchmarkProcessor",
"elapsed": 1
}
],
"speed": 1.3330000000000002,
"type": "Processor",
"model": "Intel Atom CPU N270 @ 1.60GHz"
},
{
"memory": 256.0,
"serialNumber": null,
"manufacturer": "Intel Corporation",
"events": [],
"type": "GraphicCard",
"model": "Mobile 945GSE Express Integrated Graphics Controller"
},
{
"serialNumber": "090623PB5B00QCGREMAH",
"interface": "ATA",
"size": 152627,
"manufacturer": "Hitachi",
"events": [
{
"elapsed": 71,
"readSpeed": 19.1,
"type": "BenchmarkDataStorage",
"writeSpeed": 4.7
},
{
"elapsed": 2,
"status": "Unspecified Error. Self-test not started.",
"type": "TestDataStorage",
"length": Short,
"error": true
}
],
"type": "HardDrive",
"model": "HTS54501"
},
{
"slots": 0,
"serialNumber": "0123456789AB",
"manufacturer": "TOSHIBA",
"firewire": 0,
"events": [],
"pcmcia": 0,
"usb": 5,
"serial": 1,
"type": "Motherboard",
"model": "KAVAA"
}
],
"version": "11.0a1",
"device": {
"serialNumber": "79545417K",
"manufacturer": "TOSHIBA",
"events": [
{
"type": "StressTest",
"error": false,
"elapsed": 120
},
{
"rate": 19.0443,
"type": "BenchmarkRamSysbench",
"elapsed": 19
}
],
"type": "Laptop",
"chassis": "Netbook",
"model": "NB200"
},
"uuid": "918726ae-c6bc-40aa-97cf-ad80d69268f9",
"closed": false,
"type": "Snapshot"
}

View file

@ -60,7 +60,6 @@ components:
elapsed: 21
- type: TestDataStorage
elapsed: 233
firstError: 0
error: False
status: Completed without error
length: Short
@ -76,17 +75,14 @@ components:
remainingLifetimePercentage: 1
- type: EraseSectors
error: False
cleanWithZeros: False
zeros: False
startTime: 2018-01-01T10:10:10
endTime: 2018-01-01T12:10:10
secureRandomSteps: 0
steps:
- type: StepRandom
startTime: 2018-01-01T10:10:10
endTime: 2018-01-01T12:10:10
error: False
cleanWithZeros: False
secureRandomSteps: 0
- type: HardDrive
serialNumber: hdd1-1s
model: hdd1-1ml
@ -97,17 +93,14 @@ components:
writeSpeed: 5
- type: EraseSectors
error: False
cleanWithZeros: False
zeros: False
startTime: 2018-01-01T10:10:10
endTime: 2018-01-01T12:10:10
secureRandomSteps: 0
steps:
- type: StepRandom
startTime: 2018-01-01T10:10:10
endTime: 2018-01-01T12:10:10
error: False
cleanWithZeros: False
secureRandomSteps: 0
- type: Install
elapsed: 420
error: False

View file

@ -1,7 +1,7 @@
from ereuse_devicehub.resources.device.schemas import Cellphone, Component, Computer, \
ComputerMonitor, DataStorage, Desktop, Device, Display, GraphicCard, HardDrive, Laptop, Mobile, \
Monitor, Motherboard, NetworkAdapter, Processor, RamModule, Server, Smartphone, \
SolidStateDrive, Tablet, TelevisionSet
SolidStateDrive, SoundCard, Tablet, TelevisionSet
from ereuse_devicehub.resources.device.views import DeviceView
from teal.resource import Converters, Resource
@ -113,6 +113,11 @@ class ProcessorDef(ComponentDef):
SCHEMA = Processor
class SoundCardDef(ComponentDef):
VIEW = None
SCHEMA = SoundCard
class DisplayDef(ComponentDef):
VIEW = None
SCHEMA = Display

View file

@ -1,8 +1,11 @@
from contextlib import suppress
from itertools import chain
from operator import attrgetter
from typing import Dict, Set
from ereuse_devicehub.resources.enums import ComputerChassis, DataStorageInterface, DisplayTech, \
RamFormat, RamInterface
from ereuse_devicehub.resources.models import STR_BIG_SIZE, STR_SIZE, STR_SM_SIZE, Thing
from itertools import chain
from sqlalchemy import BigInteger, Column, Enum as DBEnum, Float, ForeignKey, Integer, Sequence, \
SmallInteger, Unicode, inspect
from sqlalchemy.ext.declarative import declared_attr
@ -10,14 +13,11 @@ from sqlalchemy.orm import ColumnProperty, backref, relationship, validates
from sqlalchemy.util import OrderedSet
from sqlalchemy_utils import ColorType
from stdnum import imei, meid
from ereuse_devicehub.resources.enums import ComputerChassis, DataStorageInterface, DisplayTech, \
RamFormat, RamInterface
from ereuse_devicehub.resources.models import STR_BIG_SIZE, STR_SIZE, STR_SM_SIZE, Thing
from ereuse_utils.naming import Naming
from teal.db import CASCADE, POLYMORPHIC_ID, POLYMORPHIC_ON, ResourceNotFound, check_range
from teal.marshmallow import ValidationError
from ereuse_utils.naming import Naming
class Device(Thing):
"""
@ -264,14 +264,14 @@ class SolidStateDrive(DataStorage):
class Motherboard(JoinedComponentTableMixin, Component):
slots = Column(SmallInteger, check_range('slots'))
slots = Column(SmallInteger, check_range('slots', min=0))
slots.comment = """
PCI slots the motherboard has.
"""
usb = Column(SmallInteger, check_range('usb'))
firewire = Column(SmallInteger, check_range('firewire'))
serial = Column(SmallInteger, check_range('serial'))
pcmcia = Column(SmallInteger, check_range('pcmcia'))
usb = Column(SmallInteger, check_range('usb', min=0))
firewire = Column(SmallInteger, check_range('firewire', min=0))
serial = Column(SmallInteger, check_range('serial', min=0))
pcmcia = Column(SmallInteger, check_range('pcmcia', min=0))
class NetworkMixin:
@ -298,6 +298,10 @@ class RamModule(JoinedComponentTableMixin, Component):
format = Column(DBEnum(RamFormat))
class SoundCard(JoinedComponentTableMixin, Component):
pass
class Display(JoinedComponentTableMixin, DisplayMixin, Component):
"""
The display of a device. This is used in all devices that have

View file

@ -1,15 +1,14 @@
from ereuse_devicehub.marshmallow import NestedOn
from ereuse_devicehub.resources.device import models as m
from ereuse_devicehub.resources.enums import ComputerChassis, DataStorageInterface, DisplayTech, \
RamFormat, RamInterface
from ereuse_devicehub.resources.models import STR_BIG_SIZE, STR_SIZE
from ereuse_devicehub.resources.schemas import Thing, UnitCodes
from marshmallow import post_load, pre_load
from marshmallow.fields import Float, Integer, Str
from marshmallow.validate import Length, OneOf, Range
from sqlalchemy.util import OrderedSet
from stdnum import imei, meid
from ereuse_devicehub.marshmallow import NestedOn
from ereuse_devicehub.resources.device import models as m
from ereuse_devicehub.resources.enums import ComputerChassis, DisplayTech, \
RamFormat, RamInterface
from ereuse_devicehub.resources.models import STR_BIG_SIZE, STR_SIZE
from ereuse_devicehub.resources.schemas import Thing, UnitCodes
from teal.marshmallow import EnumField, ValidationError
@ -138,6 +137,7 @@ class DataStorage(Component):
size = Integer(validate=Range(0, 10 ** 8),
unit=UnitCodes.mbyte,
description=m.DataStorage.size.comment)
interface = EnumField(DataStorageInterface)
class HardDrive(DataStorage):
@ -149,7 +149,7 @@ class SolidStateDrive(DataStorage):
class Motherboard(Component):
slots = Integer(validate=Range(1, 20),
slots = Integer(validate=Range(0, 20),
description=m.Motherboard.slots.comment)
usb = Integer(validate=Range(0, 20))
firewire = Integer(validate=Range(0, 20))
@ -174,5 +174,9 @@ class RamModule(Component):
format = EnumField(RamFormat)
class SoundCard(Component):
pass
class Display(DisplayMixin, Component):
pass

View file

@ -116,9 +116,11 @@ class ImageMimeTypes(Enum):
@unique
class SnapshotExpectedEvents(Enum):
"""Events that Workbench can perform when processing a device."""
Benchmark = 'Benchmark'
TestDataStorage = 'TestDataStorage'
StressTest = 'StressTest'
EraseSectors = 'EraseSectors'
SmartTest = 'SmartTest'
Install = 'Install'

View file

@ -1,17 +1,8 @@
from collections import Iterable
from datetime import timedelta
from typing import Set, Union
from uuid import uuid4
from flask import g
from sqlalchemy import BigInteger, Boolean, CheckConstraint, Column, DateTime, Enum as DBEnum, \
Float, ForeignKey, Interval, JSON, SmallInteger, Unicode, event
from sqlalchemy.dialects.postgresql import UUID
from sqlalchemy.ext.declarative import declared_attr
from sqlalchemy.ext.orderinglist import ordering_list
from sqlalchemy.orm import backref, relationship
from sqlalchemy.orm.events import AttributeEvents as Events
from sqlalchemy.util import OrderedSet
from ereuse_devicehub.db import db
from ereuse_devicehub.resources.device.models import Component, Computer, DataStorage, Device
from ereuse_devicehub.resources.enums import AppearanceRange, BOX_RATE_3, BOX_RATE_5, Bios, \
@ -20,6 +11,15 @@ from ereuse_devicehub.resources.enums import AppearanceRange, BOX_RATE_3, BOX_RA
from ereuse_devicehub.resources.image.models import Image
from ereuse_devicehub.resources.models import STR_BIG_SIZE, STR_SIZE, STR_SM_SIZE, Thing
from ereuse_devicehub.resources.user.models import User
from flask import g
from sqlalchemy import BigInteger, Boolean, CheckConstraint, Column, DateTime, Enum as DBEnum, \
Float, ForeignKey, Interval, JSON, SmallInteger, Unicode, event
from sqlalchemy.dialects.postgresql import UUID
from sqlalchemy.ext.declarative import declared_attr
from sqlalchemy.ext.orderinglist import ordering_list
from sqlalchemy.orm import backref, relationship, validates
from sqlalchemy.orm.events import AttributeEvents as Events
from sqlalchemy.util import OrderedSet
from teal.db import ArrayOfEnum, CASCADE, CASCADE_OWN, INHERIT_COND, POLYMORPHIC_ID, \
POLYMORPHIC_ON, StrictVersionType, check_range
@ -198,10 +198,11 @@ class Deallocate(JoinedTableMixin, EventWithMultipleDevices):
class EraseBasic(JoinedTableMixin, EventWithOneDevice):
start_time = Column(DateTime, nullable=False)
end_time = Column(DateTime, CheckConstraint('end_time > start_time'), nullable=False)
secure_random_steps = Column(SmallInteger,
check_range('secure_random_steps', min=0),
nullable=False)
clean_with_zeros = Column(Boolean, nullable=False)
zeros = Column(Boolean, nullable=False)
zeros.comment = """
Whether this erasure had a first erasure step consisting of
only writing zeros.
"""
class Ready(EventWithMultipleDevices):
@ -219,10 +220,6 @@ class Step(db.Model):
error = Column(Boolean, default=False, nullable=False)
start_time = Column(DateTime, nullable=False)
end_time = Column(DateTime, CheckConstraint('end_time > start_time'), nullable=False)
secure_random_steps = Column(SmallInteger,
check_range('secure_random_steps', min=0),
nullable=False)
clean_with_zeros = Column(Boolean, nullable=False)
erasure = relationship(EraseBasic,
backref=backref('steps',
@ -412,8 +409,7 @@ class TestDataStorage(Test):
id = Column(UUID(as_uuid=True), ForeignKey(Test.id), primary_key=True)
length = Column(DBEnum(TestHardDriveLength), nullable=False) # todo from type
status = Column(Unicode(STR_SIZE), nullable=False)
lifetime = Column(Interval, nullable=False)
first_error = Column(SmallInteger, nullable=False, default=0)
lifetime = Column(Interval)
assessment = Column(Boolean)
reallocated_sector_count = Column(SmallInteger)
power_cycle_count = Column(SmallInteger)
@ -429,6 +425,10 @@ class TestDataStorage(Test):
class StressTest(Test):
pass
@validates('elapsed')
def bigger_than_a_minute(self, _, value: timedelta):
assert value.total_seconds() >= 60
class Benchmark(JoinedTableMixin, EventWithOneDevice):
elapsed = Column(Interval)
@ -483,6 +483,13 @@ def validate_device_is_data_storage(target: Event, value: DataStorage, old_value
raise TypeError('{} must be a DataStorage but you passed {}'.format(initiator.impl, value))
@event.listens_for(BenchmarkRamSysbench.device, Events.set.__name__, propagate=True)
def events_not_for_components(target: Event, value: Device, old_value, initiator):
"""Validates events that cannot be performed to components."""
if isinstance(value, Component):
raise TypeError('{!r} cannot be performed to a component ({!r}).'.format(target, value))
# The following listeners keep relationships with device <-> components synced with the event
# So, if you add or remove devices from events these listeners will
# automatically add/remove the ``components`` and ``parent`` of such events

View file

@ -81,8 +81,6 @@ class Step(Model):
self.success = ... # type: bool
self.start_time = ... # type: datetime
self.end_time = ... # type: datetime
self.secure_random_steps = ... # type: int
self.clean_with_zeros = ... # type: bool
self.erasure = ... # type: EraseBasic
@ -230,9 +228,8 @@ class EraseBasic(EventWithOneDevice):
super().__init__(**kwargs)
self.start_time = ... # type: datetime
self.end_time = ... # type: datetime
self.secure_random_steps = ... # type: int
self.steps = ... # type: List[Step]
self.clean_with_zeros = ... # type: bool
self.zeros = ... # type: bool
self.success = ... # type: bool

View file

@ -63,9 +63,7 @@ class Deallocate(EventWithMultipleDevices):
class EraseBasic(EventWithOneDevice):
start_time = DateTime(required=True, data_key='startTime')
end_time = DateTime(required=True, data_key='endTime')
secure_random_steps = Integer(validate=Range(min=0), required=True,
data_key='secureRandomSteps')
clean_with_zeros = Boolean(required=True, data_key='cleanWithZeros')
zeros = Boolean(required=True, description=m.EraseBasic.zeros.comment)
steps = NestedOn('Step', many=True, required=True)
@ -77,10 +75,6 @@ class Step(Schema):
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')
secure_random_steps = Integer(validate=Range(min=0),
required=True,
data_key='secureRandomSteps')
clean_with_zeros = Boolean(required=True, data_key='cleanWithZeros')
error = Boolean(default=False, description='Did the event fail?')
@ -243,8 +237,7 @@ class Test(EventWithOneDevice):
class TestDataStorage(Test):
length = EnumField(TestHardDriveLength, required=True)
status = String(validate=Length(max=STR_SIZE), required=True)
lifetime = TimeDelta(precision=TimeDelta.DAYS, required=True)
first_error = Integer(missing=0, data_key='firstError')
lifetime = TimeDelta(precision=TimeDelta.DAYS)
assessment = Boolean()
reallocated_sector_count = Integer(data_key='reallocatedSectorCount')
power_cycle_count = Integer(data_key='powerCycleCount')

View file

@ -5,7 +5,7 @@ with open('README.md') as f:
setup(
name='ereuse-devicehub',
version='0.2.0a9',
version='0.2.0a10',
packages=find_packages(),
url='https://github.com/ereuse/devicehub-teal',
license='Affero',
@ -16,14 +16,14 @@ setup(
long_description=long_description,
long_description_content_type='text/markdown',
install_requires=[
'teal>=0.2.0a5',
'teal>=0.2.0a6',
'marshmallow_enum',
'ereuse-utils[Naming]>=0.3.0b2',
'psycopg2-binary',
'requests',
'requests-toolbelt',
'hashids',
'tqdm',
'click',
'click-spinner',
'sqlalchemy-utils[password, color, babel]',
'PyYAML',

View file

@ -16,23 +16,18 @@ components:
manufacturer: c1mr
events:
- type: EraseSectors
cleanWithZeros: True
zeros: True
startTime: 2018-06-01T08:12:06
endTime: 2018-06-01T09:12:06
secureRandomSteps: 20
steps:
- type: StepZero
error: False
startTime: 2018-06-01T08:15:00
endTime: 2018-06-01T09:16:00
secureRandomSteps: 1
cleanWithZeros: True
- type: StepZero
error: False
startTime: 2018-06-01T08:16:00
endTime: 2018-06-01T09:17:00
secureRandomSteps: 1
cleanWithZeros: True
- type: GraphicCard
serialNumber: gc1s
model: gc1ml

View file

@ -0,0 +1,160 @@
{
"closed": false,
"uuid": "f9e5e587-baee-44e1-9a94-255d216bbda9",
"components": [
{
"events": [],
"serialNumber": "6c:62:6d:81:22:9f",
"type": "NetworkAdapter",
"manufacturer": "Intel Corporation",
"speed": 1000,
"model": "82578DM Gigabit Network Connection"
},
{
"format": "DIMM",
"events": [
],
"interface": "DDR3",
"serialNumber": "B4012F30",
"size": 2048,
"type": "RamModule",
"manufacturer": "JEDEC ID:80 2C",
"speed": 1333.0,
"model": "16JTF25664AZ-1G4F"
},
{
"format": "DIMM",
"events": [],
"interface": "DDR3",
"serialNumber": "8E9F2E29",
"size": 2048,
"type": "RamModule",
"manufacturer": "JEDEC ID:80 2C",
"speed": 1333.0,
"model": "16JTF25664AZ-1G4F"
},
{
"format": "DIMM",
"events": [],
"interface": "DDR3",
"serialNumber": "9A012F30",
"size": 2048,
"type": "RamModule",
"manufacturer": "JEDEC ID:80 2C",
"speed": 1333.0,
"model": "16JTF25664AZ-1G4F"
},
{
"format": "DIMM",
"events": [
],
"interface": "DDR3",
"serialNumber": "8F9F2E29",
"size": 2048,
"type": "RamModule",
"manufacturer": "JEDEC ID:80 2C",
"speed": 1333.0,
"model": "16JTF25664AZ-1G4F"
},
{
"cores": 2,
"events": [
{
"rate": 23410.76,
"type": "BenchmarkProcessor",
"elapsed": 1
},
{
"rate": 17.0186,
"type": "BenchmarkProcessorSysbench",
"elapsed": 18
}
],
"serialNumber": null,
"type": "Processor",
"manufacturer": "Intel Corp.",
"address": 64,
"speed": 1.199,
"model": "Intel Core i3 CPU 530 @ 2.93GHz"
},
{
"events": [
{
"writeSpeed": 24.5,
"readSpeed": 111.0,
"type": "BenchmarkDataStorage",
"elapsed": 14
},
{
"status": "Unspecified Error. Self-test not started.",
"error": true,
"type": "TestDataStorage",
"elapsed": 1,
"length": Short
}
],
"interface": "ATA",
"serialNumber": "WD-WCAV2U909540",
"size": 305245,
"type": "HardDrive",
"manufacturer": "Western Digital",
"model": "WDC WD3200AAJS-6"
},
{
"events": [],
"serialNumber": null,
"type": "SoundCard",
"manufacturer": "Intel Corporation",
"model": "5 Series/3400 Series Chipset High Definition Audio"
},
{
"memory": 256.0,
"events": [],
"serialNumber": null,
"type": "GraphicCard",
"manufacturer": "Intel Corporation",
"model": "Core Processor Integrated Graphics Controller"
},
{
"events": [],
"firewire": 0,
"pcmcia": 0,
"serialNumber": "CZC0408YJG",
"slots": 0,
"type": "Motherboard",
"manufacturer": "Hewlett-Packard",
"usb": 2,
"serial": 0,
"model": "304Ah"
}
],
"software": "Workbench",
"elapsed": 96,
"version": "11.0a1",
"expectedEvents": [
"StressTest",
"Benchmark",
"SmartTest"
],
"device": {
"events": [
{
"type": "StressTest",
"elapsed": 60,
"error": false
},
{
"rate": 0.9759,
"type": "BenchmarkRamSysbench",
"elapsed": 1
}
],
"serialNumber": "CZC0408YJG",
"type": "Desktop",
"manufacturer": "Hewlett-Packard",
"chassis": "Tower",
"model": "HP Compaq 8100 Elite SFF"
},
"type": "Snapshot",
"date": "2018-06-29T12:28:54.508266"
}

View file

@ -0,0 +1,139 @@
{
"expectedEvents": [
"SmartTest",
"Benchmark",
"StressTest"
],
"date": "2018-06-29T15:29:29.322424",
"elapsed": 391,
"software": "Workbench",
"components": [
{
"serialNumber": null,
"interface": "DDR",
"size": 1024,
"manufacturer": null,
"format": "SODIMM",
"events": [
],
"speed": 533.0,
"type": "RamModule",
"model": null
},
{
"serialNumber": null,
"manufacturer": "Intel Corporation",
"events": [],
"type": "SoundCard",
"model": "NM10/ICH7 Family High Definition Audio Controller"
},
{
"serialNumber": null,
"manufacturer": "Chicony Electronics Co., Ltd.",
"events": [],
"type": "SoundCard",
"model": "USB2.0 UVC WebCam"
},
{
"serialNumber": "00:23:08:a5:07:6d",
"manufacturer": "Qualcomm Atheros",
"events": [],
"type": "NetworkAdapter",
"model": "AR9285 Wireless Network Adapter"
},
{
"serialNumber": "00:23:5a:fe:d7:14",
"manufacturer": "Realtek Semiconductor Co., Ltd.",
"events": [],
"speed": 100,
"type": "NetworkAdapter",
"model": "RTL810xE PCI Express Fast Ethernet controller"
},
{
"serialNumber": null,
"address": 32,
"manufacturer": "Intel Corp.",
"events": [
{
"rate": 171.3049,
"type": "BenchmarkProcessorSysbench",
"elapsed": 171
},
{
"rate": 6383.9,
"type": "BenchmarkProcessor",
"elapsed": 1
}
],
"speed": 1.3330000000000002,
"type": "Processor",
"model": "Intel Atom CPU N270 @ 1.60GHz"
},
{
"memory": 256.0,
"serialNumber": null,
"manufacturer": "Intel Corporation",
"events": [],
"type": "GraphicCard",
"model": "Mobile 945GSE Express Integrated Graphics Controller"
},
{
"serialNumber": "090623PB5B00QCGREMAH",
"interface": "ATA",
"size": 152627,
"manufacturer": "Hitachi",
"events": [
{
"elapsed": 71,
"readSpeed": 19.1,
"type": "BenchmarkDataStorage",
"writeSpeed": 4.7
},
{
"elapsed": 2,
"status": "Unspecified Error. Self-test not started.",
"type": "TestDataStorage",
"length": Short,
"error": true
}
],
"type": "HardDrive",
"model": "HTS54501"
},
{
"slots": 0,
"serialNumber": "0123456789AB",
"manufacturer": "TOSHIBA",
"firewire": 0,
"events": [],
"pcmcia": 0,
"usb": 5,
"serial": 1,
"type": "Motherboard",
"model": "KAVAA"
}
],
"version": "11.0a1",
"device": {
"serialNumber": "79545417K",
"manufacturer": "TOSHIBA",
"events": [
{
"type": "StressTest",
"error": false,
"elapsed": 120
},
{
"rate": 19.0443,
"type": "BenchmarkRamSysbench",
"elapsed": 19
}
],
"type": "Laptop",
"chassis": "Netbook",
"model": "NB200"
},
"uuid": "918726ae-c6bc-40aa-97cf-ad80d69268f9",
"closed": false,
"type": "Snapshot"
}

View file

@ -58,7 +58,6 @@ components:
elapsed: 21
- type: TestDataStorage
elapsed: 233
firstError: 0
error: False
status: Completed without error
length: Short

View file

@ -10,14 +10,11 @@ type: 'EraseSectors'
error: False
# snapshot: None fulfill!
# device: None fulfill!
cleanWithZeros: False
zeros: False
startTime: 2018-01-01T10:10:10
endTime: 2018-01-01T12:10:10
secureRandomSteps: 0
steps:
- type: 'StepRandom'
startTime: '2018-01-01T10:10:10'
endTime: '2018-01-01T12:10:10'
error: False
cleanWithZeros: False
secureRandomSteps: 0

View file

@ -35,4 +35,4 @@ def test_api_docs(client: Client):
'scheme': 'basic',
'name': 'Authorization'
}
assert len(docs['definitions']) == 51
assert 52 == len(docs['definitions'])

View file

@ -1,15 +1,14 @@
from datetime import datetime, timedelta
import pytest
from flask import g
from sqlalchemy.util import OrderedSet
from ereuse_devicehub.db import db
from ereuse_devicehub.resources.device.models import Computer, Device, GraphicCard, HardDrive, \
RamModule, SolidStateDrive
from ereuse_devicehub.resources.enums import TestHardDriveLength
from ereuse_devicehub.resources.event.models import BenchmarkDataStorage, EraseBasic, EraseSectors, \
EventWithOneDevice, Install, Ready, StepZero, StressTest, TestDataStorage
EventWithOneDevice, Install, Ready, StepRandom, StepZero, StressTest, TestDataStorage
from flask import g
from sqlalchemy.util import OrderedSet
from tests.conftest import create_user
@ -34,10 +33,9 @@ def test_author():
def test_erase_basic():
erasure = EraseBasic(
device=HardDrive(serial_number='foo', manufacturer='bar', model='foo-bar'),
clean_with_zeros=True,
zeros=True,
start_time=datetime.now(),
end_time=datetime.now(),
secure_random_steps=25,
error=False
)
db.session.add(erasure)
@ -59,7 +57,6 @@ def test_validate_device_data_storage():
clean_with_zeros=True,
start_time=datetime.now(),
end_time=datetime.now(),
secure_random_steps=25,
error=False
)
@ -68,38 +65,28 @@ def test_validate_device_data_storage():
def test_erase_sectors_steps():
erasure = EraseSectors(
device=SolidStateDrive(serial_number='foo', manufacturer='bar', model='foo-bar'),
clean_with_zeros=True,
zeros=True,
start_time=datetime.now(),
end_time=datetime.now(),
secure_random_steps=25,
error=False,
steps=[
StepZero(error=False,
start_time=datetime.now(),
end_time=datetime.now(),
secure_random_steps=1,
clean_with_zeros=True),
end_time=datetime.now()),
StepRandom(error=False,
start_time=datetime.now(),
end_time=datetime.now()),
StepZero(error=False,
start_time=datetime.now(),
end_time=datetime.now(),
secure_random_steps=2,
clean_with_zeros=True),
StepZero(error=False,
start_time=datetime.now(),
end_time=datetime.now(),
secure_random_steps=3,
clean_with_zeros=True)
end_time=datetime.now())
]
)
db.session.add(erasure)
db.session.commit()
db_erasure = EraseSectors.query.one()
# Steps are in order
assert db_erasure.steps[0].secure_random_steps == 1
assert db_erasure.steps[0].num == 0
assert db_erasure.steps[1].secure_random_steps == 2
assert db_erasure.steps[1].num == 1
assert db_erasure.steps[2].secure_random_steps == 3
assert db_erasure.steps[2].num == 2

View file

@ -330,8 +330,6 @@ def test_erase(user: UserClient):
for step in erasure['steps']:
assert step['type'] == 'StepZero'
assert step['error'] is False
assert step['secureRandomSteps'] == 1
assert step['cleanWithZeros'] is True
assert 'num' not in step

View file

@ -112,3 +112,24 @@ def test_workbench_server_phases(user: UserClient):
pc, _ = user.get(res=Device, item=snapshot['id'])
assert len(pc['events']) == 10 # todo shall I add child events?
def test_real_hp_11(user: UserClient):
s = file('real-hp.snapshot.11')
snapshot, _ = user.post(res=Snapshot, data=s)
assert snapshot['device']['hid'] == 'hewlett-packard-czc0408yjg-hp_compaq_8100_elite_sff'
assert snapshot['device']['chassis'] == 'Tower'
assert set(e['type'] for e in snapshot['events']) == {
'BenchmarkDataStorage',
'BenchmarkProcessor',
'BenchmarkProcessorSysbench',
'TestDataStorage',
'BenchmarkRamSysbench',
'StressTest'
}
assert len(list(e['type'] for e in snapshot['events'])) == 6
def test_real_toshiba_11(user: UserClient):
s = file('real-toshiba.snapshot.11')
snapshot, _ = user.post(res=Snapshot, data=s)