-
Notifications
You must be signed in to change notification settings - Fork 21
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Fix: Added cost tests and fixed issue with vm calculation. * Fix: Changed test name to avoid duplication. * Fix: Changed cost calculation on views and models, and added another test case. * Fix: Fixed migration and tests. * Fix: Fixed unit tests and type mismatching for float. * Fix: Fixed last float value on test. --------- Co-authored-by: Andres D. Molins <[email protected]>
- Loading branch information
Showing
5 changed files
with
295 additions
and
8 deletions.
There are no files selected for viewing
146 changes: 146 additions & 0 deletions
146
deployment/migrations/versions/0020_e682fc8f9506_fix_vm_costs_view.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
"""fix_vm_costs_view | ||
Revision ID: e682fc8f9506 | ||
Revises: 08602db6c78f | ||
Create Date: 2023-11-27 18:19:35.782198 | ||
""" | ||
from alembic import op | ||
import sqlalchemy as sa | ||
|
||
|
||
revision = 'e682fc8f9506' | ||
down_revision = '3bf484f2cc95' | ||
branch_labels = None | ||
depends_on = None | ||
|
||
|
||
def upgrade() -> None: | ||
op.execute( | ||
""" | ||
create or replace view vm_costs_view as | ||
SELECT vm_versions.vm_hash, | ||
vm_versions.owner, | ||
vms.resources_vcpus, | ||
vms.resources_memory, | ||
file_volumes_size.file_volumes_size, | ||
other_volumes_size.other_volumes_size, | ||
used_disk.required_disk_space, | ||
cu.compute_units_required, | ||
bcp.base_compute_unit_price, | ||
m.compute_unit_price_multiplier, | ||
cpm.compute_unit_price, | ||
free_disk.included_disk_space, | ||
additional_disk.additional_disk_space, | ||
adp.disk_price, | ||
tp.total_price | ||
FROM vm_versions | ||
JOIN vms ON vm_versions.current_version::text = vms.item_hash::text | ||
JOIN (SELECT volume.vm_hash, | ||
sum(files.size) AS file_volumes_size | ||
FROM vm_volumes_files_view volume | ||
LEFT JOIN files ON volume.volume_to_use::text = files.hash::text | ||
GROUP BY volume.vm_hash) file_volumes_size | ||
ON vm_versions.current_version::text = file_volumes_size.vm_hash::text | ||
LEFT JOIN (SELECT instance_rootfs.instance_hash, | ||
instance_rootfs.size_mib::bigint * 1024 * 1024 AS rootfs_size | ||
FROM instance_rootfs) rootfs_size ON vm_versions.vm_hash::text = rootfs_size.instance_hash::text | ||
JOIN (SELECT vm_machine_volumes.vm_hash, | ||
sum(vm_machine_volumes.size_mib) * 1024 * 1024 AS other_volumes_size | ||
FROM vm_machine_volumes | ||
GROUP BY vm_machine_volumes.vm_hash) other_volumes_size | ||
ON vm_versions.current_version::text = other_volumes_size.vm_hash::text, | ||
LATERAL ( SELECT file_volumes_size.file_volumes_size + | ||
other_volumes_size.other_volumes_size::numeric AS required_disk_space) used_disk, | ||
LATERAL ( SELECT ceil(GREATEST(ceil((vms.resources_vcpus / 1)::double precision), | ||
(vms.resources_memory / 2048)::double precision)) AS compute_units_required) cu, | ||
LATERAL ( SELECT CASE | ||
WHEN COALESCE(vms.persistent, true) | ||
THEN '21474836480'::bigint::double precision * cu.compute_units_required | ||
ELSE 2147483648::double precision * cu.compute_units_required | ||
END AS included_disk_space) free_disk, | ||
LATERAL ( SELECT GREATEST((file_volumes_size.file_volumes_size + rootfs_size.rootfs_size::numeric + | ||
other_volumes_size.other_volumes_size::numeric)::double precision - | ||
free_disk.included_disk_space, | ||
0::double precision) AS additional_disk_space) additional_disk, | ||
LATERAL ( SELECT CASE | ||
WHEN COALESCE(vms.persistent, true) THEN 2000 | ||
ELSE 200 | ||
END AS base_compute_unit_price) bcp, | ||
LATERAL ( SELECT CASE | ||
WHEN COALESCE(vms.persistent, true) THEN 1 + vms.environment_internet::integer | ||
ELSE 1 | ||
END AS compute_unit_price_multiplier) m, | ||
LATERAL ( SELECT cu.compute_units_required * m.compute_unit_price_multiplier::double precision * | ||
bcp.base_compute_unit_price::double precision AS compute_unit_price) cpm, | ||
LATERAL ( SELECT additional_disk.additional_disk_space / 20::double precision / | ||
(1024 * 1024)::double precision AS disk_price) adp, | ||
LATERAL ( SELECT cpm.compute_unit_price + adp.disk_price AS total_price) tp | ||
""" | ||
) | ||
|
||
|
||
def downgrade() -> None: | ||
op.execute( | ||
""" | ||
create or replace view vm_costs_view as | ||
SELECT vm_versions.vm_hash, | ||
vm_versions.owner, | ||
vms.resources_vcpus, | ||
vms.resources_memory, | ||
file_volumes_size.file_volumes_size, | ||
other_volumes_size.other_volumes_size, | ||
used_disk.required_disk_space, | ||
cu.compute_units_required, | ||
bcp.base_compute_unit_price, | ||
m.compute_unit_price_multiplier, | ||
cpm.compute_unit_price, | ||
free_disk.included_disk_space, | ||
additional_disk.additional_disk_space, | ||
adp.disk_price, | ||
tp.total_price | ||
FROM vm_versions | ||
JOIN vms ON vm_versions.current_version::text = vms.item_hash::text | ||
JOIN (SELECT volume.vm_hash, | ||
sum(files.size) AS file_volumes_size | ||
FROM vm_volumes_files_view volume | ||
LEFT JOIN files ON volume.volume_to_use::text = files.hash::text | ||
GROUP BY volume.vm_hash) file_volumes_size | ||
ON vm_versions.current_version::text = file_volumes_size.vm_hash::text | ||
LEFT JOIN (SELECT instance_rootfs.instance_hash, | ||
instance_rootfs.size_mib::bigint * 1024 * 1024 AS rootfs_size | ||
FROM instance_rootfs) rootfs_size ON vm_versions.vm_hash::text = rootfs_size.instance_hash::text | ||
JOIN (SELECT vm_machine_volumes.vm_hash, | ||
sum(vm_machine_volumes.size_mib) * 1024 * 1024 AS other_volumes_size | ||
FROM vm_machine_volumes | ||
GROUP BY vm_machine_volumes.vm_hash) other_volumes_size | ||
ON vm_versions.current_version::text = other_volumes_size.vm_hash::text, | ||
LATERAL ( SELECT file_volumes_size.file_volumes_size + | ||
other_volumes_size.other_volumes_size::numeric AS required_disk_space) used_disk, | ||
LATERAL ( SELECT ceil(GREATEST(ceil((vms.resources_vcpus / 1)::double precision), | ||
(vms.resources_memory / 2048)::double precision)) AS compute_units_required) cu, | ||
LATERAL ( SELECT CASE | ||
WHEN COALESCE(vms.persistent, true) | ||
THEN '21474836480'::bigint::double precision * cu.compute_units_required | ||
ELSE 2147483648::double precision * cu.compute_units_required | ||
END AS included_disk_space) free_disk, | ||
LATERAL ( SELECT GREATEST((file_volumes_size.file_volumes_size + rootfs_size.rootfs_size::numeric + | ||
other_volumes_size.other_volumes_size::numeric)::double precision - | ||
free_disk.included_disk_space, | ||
0::double precision) AS additional_disk_space) additional_disk, | ||
LATERAL ( SELECT CASE | ||
WHEN COALESCE(vms.persistent, true) THEN 2000 | ||
ELSE 200 | ||
END AS base_compute_unit_price) bcp, | ||
LATERAL ( SELECT 1 + vms.environment_internet::integer AS compute_unit_price_multiplier) m, | ||
LATERAL ( SELECT cu.compute_units_required * m.compute_unit_price_multiplier::double precision * | ||
bcp.base_compute_unit_price::double precision AS compute_unit_price) cpm, | ||
LATERAL ( SELECT additional_disk.additional_disk_space * 20::double precision / | ||
(1024 * 1024)::double precision AS disk_price) adp, | ||
LATERAL ( SELECT cpm.compute_unit_price + adp.disk_price AS total_price) tp | ||
""" | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
import pytest | ||
from aleph.types.db_session import DbSession | ||
|
||
from aleph_message.models import ExecutableContent, InstanceContent | ||
|
||
from aleph.services.cost import ( | ||
compute_cost, | ||
get_additional_storage_price, | ||
) | ||
|
||
from unittest.mock import Mock | ||
|
||
|
||
class StoredFileDb: | ||
pass | ||
|
||
|
||
@pytest.fixture | ||
def fixture_instance_message() -> ExecutableContent: | ||
content = { | ||
"time": 1701099523.849, | ||
"rootfs": { | ||
"parent": { | ||
"ref": "6e30de68c6cedfa6b45240c2b51e52495ac6fb1bd4b36457b3d5ca307594d595", | ||
"use_latest": True | ||
}, | ||
"size_mib": 20480, | ||
"persistence": "host" | ||
}, | ||
"address": "0xA07B1214bAe0D5ccAA25449C3149c0aC83658874", | ||
"volumes": [], | ||
"metadata": { | ||
"name": "Test Debian 12" | ||
}, | ||
"resources": { | ||
"vcpus": 1, | ||
"memory": 2048, | ||
"seconds": 30 | ||
}, | ||
"allow_amend": False, | ||
"environment": { | ||
"internet": True, | ||
"aleph_api": True, | ||
"reproducible": False, | ||
"shared_cache": False | ||
}, | ||
"authorized_keys": [ | ||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHlGJRaIv/EzNT0eNqNB5DiGEbii28Fb2zCjuO/bMu7y [email protected]" | ||
] | ||
} | ||
|
||
return InstanceContent.parse_obj(content) | ||
|
||
@pytest.fixture | ||
def fixture_instance_message_complete() -> ExecutableContent: | ||
content = { | ||
"time": 1701099523.849, | ||
"rootfs": { | ||
"parent": { | ||
"ref": "6e30de68c6cedfa6b45240c2b51e52495ac6fb1bd4b36457b3d5ca307594d595", | ||
"use_latest": True | ||
}, | ||
"size_mib": 20480, | ||
"persistence": "host" | ||
}, | ||
"address": "0xA07B1214bAe0D5ccAA25449C3149c0aC83658874", | ||
"volumes": [ | ||
{ | ||
"comment": "Ephemeral storage, read-write but will not persist after the VM stops", | ||
"mount": "/var/cache", | ||
"ephemeral": True, | ||
"size_mib": 50, | ||
}, | ||
{ | ||
"comment": "Working data persisted on the VM supervisor, not available on other nodes", | ||
"mount": "/var/lib/sqlite", | ||
"name": "sqlite-data", | ||
"persistence": "host", | ||
"size_mib": 100, | ||
}, | ||
{ | ||
"comment": "Working data persisted on the Aleph network. " | ||
"New VMs will try to use the latest version of this volume, " | ||
"with no guarantee against conflicts", | ||
"mount": "/var/lib/statistics", | ||
"name": "statistics", | ||
"persistence": "store", | ||
"size_mib": 100, | ||
}, | ||
{ | ||
"comment": "Raw drive to use by a process, do not mount it", | ||
"name": "raw-data", | ||
"persistence": "host", | ||
"size_mib": 100, | ||
}, | ||
], | ||
"metadata": { | ||
"name": "Test Debian 12" | ||
}, | ||
"resources": { | ||
"vcpus": 1, | ||
"memory": 2048, | ||
"seconds": 30 | ||
}, | ||
"allow_amend": False, | ||
"environment": { | ||
"internet": True, | ||
"aleph_api": True, | ||
"reproducible": False, | ||
"shared_cache": False | ||
}, | ||
"authorized_keys": [ | ||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHlGJRaIv/EzNT0eNqNB5DiGEbii28Fb2zCjuO/bMu7y [email protected]" | ||
] | ||
} | ||
|
||
return InstanceContent.parse_obj(content) | ||
|
||
|
||
def test_compute_cost(fixture_instance_message): | ||
file_db = StoredFileDb() | ||
mock = Mock() | ||
mock.patch('_get_file_from_ref', return_value=file_db) | ||
cost = compute_cost(content=fixture_instance_message, session=DbSession()) | ||
assert cost == 2000 | ||
|
||
|
||
def test_get_additional_storage_price(fixture_instance_message): | ||
file_db = StoredFileDb() | ||
mock = Mock() | ||
mock.patch('_get_file_from_ref', return_value=file_db) | ||
cost = get_additional_storage_price(content=fixture_instance_message, session=DbSession()) | ||
assert cost == 0 | ||
|
||
|
||
def test_compute_cost_complete(fixture_instance_message_complete): | ||
file_db = StoredFileDb() | ||
mock = Mock() | ||
mock.patch('_get_file_from_ref', return_value=file_db) | ||
cost = compute_cost(content=fixture_instance_message_complete, session=DbSession()) | ||
assert cost == 2017.50 |