@@ -71,6 +71,53 @@ struct CrucibleDataInner {
71
71
used_ports : HashSet < u16 > ,
72
72
}
73
73
74
+ /// Returns Some with a string if there's a mismatch
75
+ pub fn mismatch ( params : & CreateRegion , r : & Region ) -> Option < String > {
76
+ if params. block_size != r. block_size {
77
+ Some ( format ! (
78
+ "requested block size {} instead of {}" ,
79
+ params. block_size, r. block_size
80
+ ) )
81
+ } else if params. extent_size != r. extent_size {
82
+ Some ( format ! (
83
+ "requested extent size {} instead of {}" ,
84
+ params. extent_size, r. extent_size
85
+ ) )
86
+ } else if params. extent_count != r. extent_count {
87
+ Some ( format ! (
88
+ "requested extent count {} instead of {}" ,
89
+ params. extent_count, r. extent_count
90
+ ) )
91
+ } else if params. encrypted != r. encrypted {
92
+ Some ( format ! (
93
+ "requested encrypted {} instead of {}" ,
94
+ params. encrypted, r. encrypted
95
+ ) )
96
+ } else if params. cert_pem != r. cert_pem {
97
+ Some ( format ! (
98
+ "requested cert_pem {:?} instead of {:?}" ,
99
+ params. cert_pem, r. cert_pem
100
+ ) )
101
+ } else if params. key_pem != r. key_pem {
102
+ Some ( format ! (
103
+ "requested key_pem {:?} instead of {:?}" ,
104
+ params. key_pem, r. key_pem
105
+ ) )
106
+ } else if params. root_pem != r. root_pem {
107
+ Some ( format ! (
108
+ "requested root_pem {:?} instead of {:?}" ,
109
+ params. root_pem, r. root_pem
110
+ ) )
111
+ } else if params. source != r. source {
112
+ Some ( format ! (
113
+ "requested source {:?} instead of {:?}" ,
114
+ params. source, r. source
115
+ ) )
116
+ } else {
117
+ None
118
+ }
119
+ }
120
+
74
121
impl CrucibleDataInner {
75
122
fn new ( log : Logger , start_port : u16 , end_port : u16 ) -> Self {
76
123
Self {
@@ -108,7 +155,7 @@ impl CrucibleDataInner {
108
155
panic ! ( "no free ports for simulated crucible agent!" ) ;
109
156
}
110
157
111
- fn create ( & mut self , params : CreateRegion ) -> Result < Region > {
158
+ fn create ( & mut self , params : CreateRegion ) -> Result < Region , HttpError > {
112
159
let id = Uuid :: from_str ( & params. id . 0 ) . unwrap ( ) ;
113
160
114
161
let state = if let Some ( on_create) = & self . on_create {
@@ -118,7 +165,23 @@ impl CrucibleDataInner {
118
165
} ;
119
166
120
167
if self . region_creation_error {
121
- bail ! ( "region creation error!" ) ;
168
+ return Err ( HttpError :: for_internal_error (
169
+ "region creation error!" . to_string ( ) ,
170
+ ) ) ;
171
+ }
172
+
173
+ if let Some ( region) = self . regions . get ( & id) {
174
+ if let Some ( mismatch) = mismatch ( & params, & region) {
175
+ let s = format ! (
176
+ "region {region:?} already exists as {params:?}: {mismatch}"
177
+ ) ;
178
+ warn ! ( self . log, "{s}" ) ;
179
+ return Err ( HttpError :: for_client_error (
180
+ None ,
181
+ dropshot:: ClientErrorStatusCode :: CONFLICT ,
182
+ s,
183
+ ) ) ;
184
+ }
122
185
}
123
186
124
187
let read_only = params. source . is_some ( ) ;
@@ -131,10 +194,10 @@ impl CrucibleDataInner {
131
194
// NOTE: This is a lie - no server is running.
132
195
port_number : self . get_free_port ( ) ,
133
196
state,
134
- encrypted : false ,
135
- cert_pem : None ,
136
- key_pem : None ,
137
- root_pem : None ,
197
+ encrypted : params . encrypted ,
198
+ cert_pem : params . cert_pem ,
199
+ key_pem : params . key_pem ,
200
+ root_pem : params . root_pem ,
138
201
source : params. source ,
139
202
read_only,
140
203
} ;
@@ -933,7 +996,7 @@ impl CrucibleData {
933
996
self . inner . lock ( ) . unwrap ( ) . list ( )
934
997
}
935
998
936
- pub fn create ( & self , params : CreateRegion ) -> Result < Region > {
999
+ pub fn create ( & self , params : CreateRegion ) -> Result < Region , HttpError > {
937
1000
self . inner . lock ( ) . unwrap ( ) . create ( params)
938
1001
}
939
1002
0 commit comments