|
20 | 20 | from argparse import SUPPRESS, ArgumentTypeError |
21 | 21 | from uuid import UUID |
22 | 22 |
|
| 23 | +# isort: THIRDPARTY |
| 24 | +from justbytes import MiB, Range |
| 25 | + |
23 | 26 | from .._actions import BindActions, PoolActions |
24 | | -from .._constants import Clevis, EncryptionMethod, UnlockMethod, YesOrNo |
| 27 | +from .._constants import ( |
| 28 | + Clevis, |
| 29 | + EncryptionMethod, |
| 30 | + IntegrityOption, |
| 31 | + IntegrityTagSpec, |
| 32 | + UnlockMethod, |
| 33 | + YesOrNo, |
| 34 | +) |
25 | 35 | from .._error_codes import PoolErrorCode |
26 | 36 | from ._bind import BIND_SUBCMDS, REBIND_SUBCMDS |
27 | 37 | from ._debug import POOL_DEBUG_SUBCMDS |
28 | | -from ._range import RejectAction |
| 38 | +from ._range import DefaultAction, RejectAction, parse_range |
29 | 39 |
|
30 | 40 |
|
31 | 41 | class ClevisEncryptionOptions: # pylint: disable=too-few-public-methods |
@@ -81,6 +91,62 @@ def verify(self, namespace, parser): |
81 | 91 | namespace.clevis = None if self.clevis is None else self |
82 | 92 |
|
83 | 93 |
|
| 94 | +class IntegrityOptions: # pylint: disable=too-few-public-methods |
| 95 | + """ |
| 96 | + Gathers and verifies integrity options. |
| 97 | + """ |
| 98 | + |
| 99 | + def __init__(self, namespace): |
| 100 | + self.integrity = copy.copy(namespace.integrity) |
| 101 | + del namespace.integrity |
| 102 | + |
| 103 | + self.journal_size = copy.copy(namespace.journal_size) |
| 104 | + del namespace.journal_size |
| 105 | + |
| 106 | + self.journal_size_default = getattr(namespace, "journal_size_default", True) |
| 107 | + |
| 108 | + self.tag_spec = copy.copy(namespace.tag_spec) |
| 109 | + del namespace.tag_spec |
| 110 | + |
| 111 | + self.tag_spec_default = getattr(namespace, "tag_spec_default", True) |
| 112 | + |
| 113 | + def verify(self, namespace, parser): |
| 114 | + """ |
| 115 | + Do supplementary parsing of conditional arguments. |
| 116 | + """ |
| 117 | + |
| 118 | + if self.integrity is IntegrityOption.NO and not self.journal_size_default: |
| 119 | + parser.error( |
| 120 | + f'--integrity value "{IntegrityOption.NO}" and --journal-size ' |
| 121 | + "option can not be specified together" |
| 122 | + ) |
| 123 | + |
| 124 | + if self.integrity is IntegrityOption.NO and not self.tag_spec_default: |
| 125 | + parser.error( |
| 126 | + f'--integrity value "{IntegrityOption.NO}" and --tag-spec ' |
| 127 | + "option can not be specified together" |
| 128 | + ) |
| 129 | + |
| 130 | + namespace.integrity = self |
| 131 | + |
| 132 | + |
| 133 | +class CreateOptions: # pylint: disable=too-few-public-methods |
| 134 | + """ |
| 135 | + Gathers and verifies options specified on pool create. |
| 136 | + """ |
| 137 | + |
| 138 | + def __init__(self, namespace): |
| 139 | + self.clevis_encryption_options = ClevisEncryptionOptions(namespace) |
| 140 | + self.integrity_options = IntegrityOptions(namespace) |
| 141 | + |
| 142 | + def verify(self, namespace, parser): |
| 143 | + """ |
| 144 | + Verify that create command-line is formed correctly. |
| 145 | + """ |
| 146 | + self.clevis_encryption_options.verify(namespace, parser) |
| 147 | + self.integrity_options.verify(namespace, parser) |
| 148 | + |
| 149 | + |
84 | 150 | def _ensure_nat(arg): |
85 | 151 | """ |
86 | 152 | Raise error if argument is not an natural number. |
@@ -110,7 +176,7 @@ def _ensure_nat(arg): |
110 | 176 | "--post-parser", |
111 | 177 | { |
112 | 178 | "action": RejectAction, |
113 | | - "default": ClevisEncryptionOptions, |
| 179 | + "default": CreateOptions, |
114 | 180 | "help": SUPPRESS, |
115 | 181 | "nargs": "?", |
116 | 182 | }, |
@@ -163,7 +229,75 @@ def _ensure_nat(arg): |
163 | 229 | ) |
164 | 230 | ], |
165 | 231 | }, |
166 | | - ) |
| 232 | + ), |
| 233 | + ( |
| 234 | + "integrity", |
| 235 | + { |
| 236 | + "description": ( |
| 237 | + "Optional parameters for configuring integrity " |
| 238 | + "metadata pre-allocation" |
| 239 | + ), |
| 240 | + "args": [ |
| 241 | + ( |
| 242 | + "--integrity", |
| 243 | + { |
| 244 | + "help": ( |
| 245 | + "Integrity options for this pool. If " |
| 246 | + f'"{IntegrityOption.NO}" no space will ' |
| 247 | + "be allocated for integrity metadata " |
| 248 | + "and it will never be possible to turn " |
| 249 | + "on integrity functionality for this " |
| 250 | + "pool. " |
| 251 | + f'If "{IntegrityOption.PRE_ALLOCATE}" ' |
| 252 | + "then space will be allocated for " |
| 253 | + "integrity metadata and it will be " |
| 254 | + "possible to switch on integrity " |
| 255 | + "functionality in future. The default " |
| 256 | + 'is "%(default)s".' |
| 257 | + ), |
| 258 | + "choices": list(IntegrityOption), |
| 259 | + "default": IntegrityOption.PRE_ALLOCATE, |
| 260 | + "type": IntegrityOption, |
| 261 | + }, |
| 262 | + ), |
| 263 | + ( |
| 264 | + "--journal-size", |
| 265 | + { |
| 266 | + "help": ( |
| 267 | + "Size of integrity device's journal. " |
| 268 | + "Each block is written to this journal " |
| 269 | + "before being written to its address. " |
| 270 | + "The default is %(default)s." |
| 271 | + ), |
| 272 | + "action": DefaultAction, |
| 273 | + "default": Range(128, MiB), |
| 274 | + "type": parse_range, |
| 275 | + }, |
| 276 | + ), |
| 277 | + ( |
| 278 | + "--tag-spec", |
| 279 | + { |
| 280 | + "help": ( |
| 281 | + "Integrity tag specification defining " |
| 282 | + "the size of the tag used to store a " |
| 283 | + "checksum or other value for each " |
| 284 | + "block on a device. All size " |
| 285 | + "specifications are in bits. The " |
| 286 | + "default is %(default)s." |
| 287 | + ), |
| 288 | + "action": DefaultAction, |
| 289 | + "default": IntegrityTagSpec.B512, |
| 290 | + "choices": [ |
| 291 | + x |
| 292 | + for x in list(IntegrityTagSpec) |
| 293 | + if x is not IntegrityTagSpec.B0 |
| 294 | + ], |
| 295 | + "type": IntegrityTagSpec, |
| 296 | + }, |
| 297 | + ), |
| 298 | + ], |
| 299 | + }, |
| 300 | + ), |
167 | 301 | ], |
168 | 302 | "args": [ |
169 | 303 | ("pool_name", {"help": "Name of new pool"}), |
|
0 commit comments