5
5
//! Tests basic disk support in the API
6
6
7
7
use super :: instances:: instance_wait_for_state;
8
- use super :: metrics_querier:: MetricsNotYet ;
9
- use super :: metrics_querier:: MetricsQuerier ;
10
- use chrono:: Utc ;
11
8
use dropshot:: HttpErrorResponseBody ;
12
9
use dropshot:: test_util:: ClientTestContext ;
13
10
use http:: StatusCode ;
@@ -22,36 +19,30 @@ use nexus_db_queries::db::datastore::RegionAllocationParameters;
22
19
use nexus_db_queries:: db:: fixed_data:: FLEET_ID ;
23
20
use nexus_test_utils:: SLED_AGENT_UUID ;
24
21
use nexus_test_utils:: http_testing:: AuthnMode ;
25
- use nexus_test_utils:: http_testing:: Collection ;
26
22
use nexus_test_utils:: http_testing:: NexusRequest ;
27
23
use nexus_test_utils:: http_testing:: RequestBuilder ;
28
24
use nexus_test_utils:: identity_eq;
29
25
use nexus_test_utils:: resource_helpers:: create_default_ip_pool;
30
26
use nexus_test_utils:: resource_helpers:: create_disk;
31
27
use nexus_test_utils:: resource_helpers:: create_instance;
32
- use nexus_test_utils:: resource_helpers:: create_instance_with;
33
28
use nexus_test_utils:: resource_helpers:: create_project;
34
- use nexus_test_utils:: resource_helpers:: objects_list_page_authz;
35
- use nexus_test_utils:: wait_for_producer;
36
29
use nexus_test_utils_macros:: nexus_test;
37
30
use nexus_types:: external_api:: params;
38
31
use nexus_types:: identity:: Asset ;
39
32
use nexus_types:: silo:: DEFAULT_SILO_ID ;
33
+ use omicron_common:: api:: external:: ByteCount ;
40
34
use omicron_common:: api:: external:: Disk ;
41
35
use omicron_common:: api:: external:: DiskState ;
42
36
use omicron_common:: api:: external:: IdentityMetadataCreateParams ;
43
37
use omicron_common:: api:: external:: Instance ;
44
38
use omicron_common:: api:: external:: InstanceState ;
45
39
use omicron_common:: api:: external:: Name ;
46
40
use omicron_common:: api:: external:: NameOrId ;
47
- use omicron_common:: api:: external:: { ByteCount , SimpleIdentityOrName as _} ;
48
41
use omicron_nexus:: Nexus ;
49
42
use omicron_nexus:: TestInterfaces as _;
50
43
use omicron_nexus:: app:: { MAX_DISK_SIZE_BYTES , MIN_DISK_SIZE_BYTES } ;
51
44
use omicron_uuid_kinds:: VolumeUuid ;
52
45
use omicron_uuid_kinds:: { GenericUuid , InstanceUuid } ;
53
- use oximeter:: types:: Datum ;
54
- use oximeter:: types:: Measurement ;
55
46
use sled_agent_client:: TestInterfaces as _;
56
47
use std:: collections:: HashSet ;
57
48
use std:: sync:: Arc ;
@@ -1752,193 +1743,6 @@ async fn test_multiple_disks_multiple_zpools(
1752
1743
. unwrap ( ) ;
1753
1744
}
1754
1745
1755
- async fn create_instance_with_disk ( client : & ClientTestContext ) {
1756
- create_instance_with (
1757
- & client,
1758
- PROJECT_NAME ,
1759
- INSTANCE_NAME ,
1760
- & params:: InstanceNetworkInterfaceAttachment :: Default ,
1761
- vec ! [ params:: InstanceDiskAttachment :: Attach (
1762
- params:: InstanceDiskAttach { name: DISK_NAME . parse( ) . unwrap( ) } ,
1763
- ) ] ,
1764
- Vec :: < params:: ExternalIpCreate > :: new ( ) ,
1765
- true ,
1766
- Default :: default ( ) ,
1767
- )
1768
- . await ;
1769
- }
1770
-
1771
- const ALL_METRICS : [ & ' static str ; 6 ] =
1772
- [ "activated" , "read" , "write" , "read_bytes" , "write_bytes" , "flush" ] ;
1773
-
1774
- #[ nexus_test]
1775
- async fn test_disk_metrics ( cptestctx : & ControlPlaneTestContext ) {
1776
- let metrics_querier = MetricsQuerier :: new ( cptestctx) ;
1777
- let client = & cptestctx. external_client ;
1778
- DiskTest :: new ( & cptestctx) . await ;
1779
- let project_id = create_project_and_pool ( client) . await ;
1780
- let disk = create_disk ( & client, PROJECT_NAME , DISK_NAME ) . await ;
1781
-
1782
- // When grabbing a metric, we look for data points going back to the
1783
- // start of this test all the way up to the current time.
1784
- let metric_url = |metric : & str | {
1785
- format ! (
1786
- "/v1/disks/{}/metrics/{}?start_time={:?}&end_time={:?}&project={}" ,
1787
- DISK_NAME ,
1788
- metric,
1789
- cptestctx. start_time,
1790
- Utc :: now( ) ,
1791
- PROJECT_NAME ,
1792
- )
1793
- } ;
1794
-
1795
- // Try accessing metrics before we attach the disk to an instance.
1796
- //
1797
- // Observe that no metrics exist yet; no "upstairs" should have been
1798
- // instantiated on a sled.
1799
- let measurements =
1800
- objects_list_page_authz :: < Measurement > ( client, & metric_url ( "read" ) )
1801
- . await ;
1802
- assert ! ( measurements. items. is_empty( ) ) ;
1803
-
1804
- metrics_querier
1805
- . wait_for_latest_silo_metric (
1806
- "virtual_disk_space_provisioned" ,
1807
- Some ( project_id) ,
1808
- |measurement| {
1809
- if measurement == i64:: from ( disk. size ) {
1810
- Ok ( ( ) )
1811
- } else {
1812
- Err ( MetricsNotYet :: new ( format ! (
1813
- "waiting for virtual_disk_space_provisioned={} \
1814
- (currently {measurement})",
1815
- disk. size,
1816
- ) ) )
1817
- }
1818
- } ,
1819
- )
1820
- . await ;
1821
-
1822
- // Create an instance, attach the disk to it.
1823
- create_instance_with_disk ( client) . await ;
1824
- wait_for_producer ( & cptestctx. oximeter , disk. id ( ) ) . await ;
1825
-
1826
- for metric in & ALL_METRICS {
1827
- metrics_querier
1828
- . wait_for_disk_metric ( PROJECT_NAME , DISK_NAME , metric, |items| {
1829
- if items. is_empty ( ) {
1830
- return Err ( MetricsNotYet :: new ( format ! (
1831
- "waiting for at least one item for metric={metric}"
1832
- ) ) ) ;
1833
- }
1834
- for item in & items {
1835
- let cumulative = match item. datum ( ) {
1836
- Datum :: CumulativeI64 ( c) => c,
1837
- _ => panic ! ( "Unexpected datum type {:?}" , item. datum( ) ) ,
1838
- } ;
1839
- assert ! ( cumulative. start_time( ) <= item. timestamp( ) ) ;
1840
- }
1841
- Ok ( ( ) )
1842
- } )
1843
- . await ;
1844
- }
1845
-
1846
- // Check the utilization info for the whole project too.
1847
- metrics_querier
1848
- . wait_for_latest_silo_metric (
1849
- "virtual_disk_space_provisioned" ,
1850
- Some ( project_id) ,
1851
- |measurement| {
1852
- if measurement == i64:: from ( disk. size ) {
1853
- Ok ( ( ) )
1854
- } else {
1855
- Err ( MetricsNotYet :: new ( format ! (
1856
- "waiting for virtual_disk_space_provisioned={} \
1857
- (currently {measurement})",
1858
- disk. size,
1859
- ) ) )
1860
- }
1861
- } ,
1862
- )
1863
- . await ;
1864
- }
1865
-
1866
- #[ nexus_test]
1867
- async fn test_disk_metrics_paginated ( cptestctx : & ControlPlaneTestContext ) {
1868
- let client = & cptestctx. external_client ;
1869
- DiskTest :: new ( & cptestctx) . await ;
1870
- create_project_and_pool ( client) . await ;
1871
- let disk = create_disk ( & client, PROJECT_NAME , DISK_NAME ) . await ;
1872
- create_instance_with_disk ( client) . await ;
1873
- wait_for_producer ( & cptestctx. oximeter , disk. id ( ) ) . await ;
1874
-
1875
- let metrics_querier = MetricsQuerier :: new ( cptestctx) ;
1876
- for metric in & ALL_METRICS {
1877
- // Wait until we have at least two measurements.
1878
- metrics_querier
1879
- . wait_for_disk_metric (
1880
- PROJECT_NAME ,
1881
- DISK_NAME ,
1882
- metric,
1883
- |measurements| {
1884
- let num_measurements = measurements. len ( ) ;
1885
- if num_measurements >= 2 {
1886
- Ok ( ( ) )
1887
- } else {
1888
- Err ( MetricsNotYet :: new ( format ! (
1889
- "waiting for at least 2 measurements \
1890
- (currently {num_measurements})"
1891
- ) ) )
1892
- }
1893
- } ,
1894
- )
1895
- . await ;
1896
-
1897
- let collection_url = format ! (
1898
- "/v1/disks/{}/metrics/{}?project={}" ,
1899
- DISK_NAME , metric, PROJECT_NAME
1900
- ) ;
1901
- let initial_params = format ! (
1902
- "start_time={:?}&end_time={:?}" ,
1903
- cptestctx. start_time,
1904
- Utc :: now( ) ,
1905
- ) ;
1906
-
1907
- let measurements_paginated: Collection < Measurement > =
1908
- NexusRequest :: iter_collection_authn (
1909
- client,
1910
- & collection_url,
1911
- & initial_params,
1912
- Some ( 10 ) ,
1913
- )
1914
- . await
1915
- . expect ( "failed to iterate over metrics" ) ;
1916
- assert ! ( !measurements_paginated. all_items. is_empty( ) ) ;
1917
-
1918
- let mut last_timestamp = None ;
1919
- let mut last_value = None ;
1920
- for item in & measurements_paginated. all_items {
1921
- let cumulative = match item. datum ( ) {
1922
- Datum :: CumulativeI64 ( c) => c,
1923
- _ => panic ! ( "Unexpected datum type {:?}" , item. datum( ) ) ,
1924
- } ;
1925
- assert ! ( cumulative. start_time( ) <= item. timestamp( ) ) ;
1926
-
1927
- // Validate that the timestamps are non-decreasing.
1928
- if let Some ( last_ts) = last_timestamp {
1929
- assert ! ( last_ts <= item. timestamp( ) ) ;
1930
- }
1931
- // Validate that the values increase.
1932
- if let Some ( last_value) = last_value {
1933
- assert ! ( last_value < cumulative. value( ) ) ;
1934
- }
1935
-
1936
- last_timestamp = Some ( item. timestamp ( ) ) ;
1937
- last_value = Some ( cumulative. value ( ) ) ;
1938
- }
1939
- }
1940
- }
1941
-
1942
1746
#[ nexus_test]
1943
1747
async fn test_disk_create_for_importing ( cptestctx : & ControlPlaneTestContext ) {
1944
1748
let client = & cptestctx. external_client ;
0 commit comments