Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Volume type standard #351

Merged
merged 39 commits into from
Apr 10, 2024
Merged
Show file tree
Hide file tree
Changes from 32 commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
6f03aac
Create scs-0112-v1-volume-type-standard.md
josephineSei Jul 25, 2023
7cccebd
Update scs-0112-v1-volume-type-standard.md
josephineSei Sep 28, 2023
7380a31
Update scs-0112-v1-volume-type-standard.md
josephineSei Sep 29, 2023
28acb9e
Update scs-0112-v1-volume-type-standard.md
josephineSei Sep 29, 2023
fa964a9
Apply suggestions from code review
josephineSei Oct 6, 2023
4f00047
Update scs-0112-v1-volume-type-standard.md
josephineSei Oct 6, 2023
8c8dc01
Update scs-0112-v1-volume-type-standard.md
josephineSei Nov 6, 2023
7a1d2ca
Update Standards/scs-0112-v1-volume-type-standard.md
josephineSei Nov 6, 2023
59b66c6
Update Standards/scs-0112-v1-volume-type-standard.md
josephineSei Nov 9, 2023
b5e5ed7
Apply suggestions from code review
josephineSei Nov 9, 2023
0792426
Update Standards/scs-0112-v1-volume-type-standard.md
josephineSei Nov 10, 2023
021a3c2
Update scs-0112-v1-volume-type-standard.md
josephineSei Nov 28, 2023
f410211
Update scs-0112-v1-volume-type-standard.md
josephineSei Nov 28, 2023
2ac3269
Update scs-0112-v1-volume-type-standard.md
josephineSei Nov 28, 2023
c4c4d6b
Apply suggestions from code review
josephineSei Dec 1, 2023
4e2f0fd
Update scs-0112-v1-volume-type-standard.md
josephineSei Dec 1, 2023
ee2678d
Update scs-0112-v1-volume-type-standard.md
josephineSei Dec 1, 2023
bc77c1c
Apply suggestions from code review
josephineSei Jan 12, 2024
374e8c5
Update scs-0112-v1-volume-type-standard.md
josephineSei Jan 12, 2024
6a59573
Update scs-0112-v1-volume-type-standard.md
josephineSei Feb 12, 2024
f616d54
Rename scs-0112-v1-volume-type-standard.md to scs-XXXX-v1-volume-type…
josephineSei Feb 14, 2024
8a2b0d1
Update scs-XXXX-v1-volume-type-standard.md
josephineSei Mar 6, 2024
8620598
Update scs-XXXX-v1-volume-type-standard.md
josephineSei Mar 6, 2024
ff5d6f9
Merge branch 'main' into volume-type-standard
josephineSei Mar 7, 2024
3ac8ed5
Create volume-types-check.py
josephineSei Mar 12, 2024
03cc149
Update volume-types-check.py
josephineSei Mar 12, 2024
427a286
Apply suggestions from code review
josephineSei Mar 14, 2024
504c48c
Update scs-XXXX-v1-volume-type-standard.md
josephineSei Mar 14, 2024
4b479d5
Update scs-XXXX-v1-volume-type-standard.md
josephineSei Mar 18, 2024
aa68c77
Apply suggestions from code review
josephineSei Mar 18, 2024
80940e5
Update volume-types-check.py
josephineSei Mar 19, 2024
fd1eed8
Update volume-types-check.py
josephineSei Mar 19, 2024
9f6fa4c
Apply suggestions from code review
josephineSei Mar 19, 2024
311eac3
Update scs-XXXX-v1-volume-type-standard.md
josephineSei Mar 19, 2024
bd3a0e5
Merge branch 'main' into volume-type-standard
josephineSei Mar 19, 2024
50cf788
shortened paragraph of default volume type
josephineSei Mar 21, 2024
d0b05bd
Merge branch 'main' into volume-type-standard
josephineSei Mar 21, 2024
2f8b68c
Merge branch 'main' into volume-type-standard
josephineSei Apr 10, 2024
3b3f3f0
add correct standard number before merge
josephineSei Apr 10, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
139 changes: 139 additions & 0 deletions Standards/scs-XXXX-v1-volume-type-standard.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
---
title: Volume Type Standard
type: Standard
status: Draft
track: IaaS
---

## Introduction

A volume is a virtual drive that is to be used by an instance (i. e., a virtual machine). With OpenStack,
each volume is created per a type that determines basic features of the volume as provided by the backend,
such as encryption, replication, or quality of service. As of the writing of this document, presence or absence of these
features can not be discovered with full certainty by non-privileged users via the OpenStack API.

### Glossary

The following special terms are used throughout this standard document:
| Term | Meaning |
|---|---|
| volume | OpenStack ressource, virtual drive which usually resides in a network storage backend |
josephineSei marked this conversation as resolved.
Show resolved Hide resolved
| volume feature | A certain feature a volume can possess |
| aspect | part of a volume type that will activate a corresponding feature in a created volume |
josephineSei marked this conversation as resolved.
Show resolved Hide resolved
| AZ | Availability Zone |
| Volume QoS | Quality of Service object for Volumes |

## Motivation
josephineSei marked this conversation as resolved.
Show resolved Hide resolved

As an SCS user, I want to be able to create volumes with certain common features, such as encryption or
replication, and to do so in a standardized manner as well as programmatically.
This standard outlines a way of formally advertising these common aspects for a volume type to
non-privileged users, so that the most suitable volume type can be discovered and selected easily — both by
the human user and by a program.

## Design Considerations

All considerations can be looked up in detail in the [Decision Record for the Volume Type Standard.](https://github.com/SovereignCloudStack/standards/blob/main/Standards/scs-0111-v1-volume-type-decisions.md)

### Systematic Description of Volume Types

To test whether a deployment has volume types with certain aspects, the discoverability of the parameters in the volume type has to be given. As for the time this standard is created, there is no way for users to discover all aspects through OpenStack commands. Therefore the aspects, that are fulfilled within a volume type, should be stated in the beginning of the **description** of a volume type in the following manner:
josephineSei marked this conversation as resolved.
Show resolved Hide resolved

`[scs:aspect1, aspect2, ..., aspectN]...`
mbuechse marked this conversation as resolved.
Show resolved Hide resolved

The mentioned aspects MUST be sorted alphebetically and every aspect should only be mentioned to the maximal amount of one.

### Standardized Aspects

The following table shows, which aspects are considered in this standard. The last column shows how the description of the volume type has to be adjusted, if the aspect is fulfilled:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see the value of the additional column. The introductory paragraph is not very good though: the comma is wrong, and it's quite verbose. Why not use my proposal, which simply said

The following features are recognized.

Or if you must

The following features are recognized by this standard.

(But to my taste this is already a bit redundant; it's the point of the standard to state what's in the standard, so we need not repeat "in this standard" or "by this standard" all the time.)

josephineSei marked this conversation as resolved.
Show resolved Hide resolved

| Aspect | Requirement | standardized description | comment |
| ---- | ---- | ------ | ------ |
| Encryption | **Recommended** | **"[scs:encrypted]"** | used to encrypt the volume |
josephineSei marked this conversation as resolved.
Show resolved Hide resolved
| Replication | **Recommended** | **"[scs:replicated]"** | volume is replicated to aviod data loss in a case of hardware failure |
josephineSei marked this conversation as resolved.
Show resolved Hide resolved

It is possible to use multiple of those aspects within one volume type. There don't have to be different volume types for each aspect.
For instance, one volume type that uses LUKS-encryption with a ceph storage with inherent replication would fulfill all recommendations of this standard.

## DEFAULT volume type

There is always a default volume type defined in an OpenStack deployment. This volume type is created in the setup of cinder and will always be present in any OpenStack deployments under the name `__default__`. This standard does not have any requirements about this volume type at this moment, instead deployers are free to choose what fits best in their environment. Conversely, a cloud user can not expect any specific behavior or properties from volume types named `__default__`.

The parameters of volume types described in this standard do not have to be applied to the chosen default volume type. And this standard will not make any assumptions about parameters being present in the default volume type.
josephineSei marked this conversation as resolved.
Show resolved Hide resolved

## REQUIRED volume types

Currently, this standard will not require volume types with certain specification.

## RECOMMENDED volume types

This standard recommends to have one or more volume types, that feature encryption and replication.

## OPTIONAL volume types

Any other aspects of volume types, that can be found in the decision record are OPTIONAL. They SHOULD NOT be referenced in the way this standard describes. Some of them already are natively discoverable by users, while others could be described in the name or description of a volume type. Users should look into the provided volume types of the CSPs, if they want to use some of these other aspects.
josephineSei marked this conversation as resolved.
Show resolved Hide resolved

## Implementation Details

### Encryption

Encryption for volumes is an option which has to be configured within the volume type. As an admin it is possible to set encryption-provider, key size, cipher and control location. Additionally to be discoverable by users an admin has to edit the description and add `[scs:encrypted]` at the beginning or after another scs aspect. It should look like this example:
josephineSei marked this conversation as resolved.
Show resolved Hide resolved

```text
openstack volume type show LUKS
+--------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Field | Value |
+--------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------+
| access_project_ids | None |
| description | [scs:encrypted] This volume uses LUKS-encryption |
| id | d63307fb-167a-4aa0-9066-66595ea9fb21 |
| is_public | True |
| name | LUKS |
| qos_specs_id | None |
+--------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------+
```

### Replication

Replication states, whether or not there are multiple replicas of a volume. Thus answers the question, whether the data could survive a node outage. Unfortunately there are two ways replication can be achieved:
josephineSei marked this conversation as resolved.
Show resolved Hide resolved

1. In the configuration of a volume type. It then is visible as extra_spec in the properties of a volume type.
2. Via the used backend. Ceph for example provides automatic replication, that does not need to be specified in the volume type. This is currently not visible for users.

To fulfill this recommentation for now, the admin needs to add `[scs:replicated]` at the beginning or after any other scs aspect into the descriotion of the volume type.
Copy link
Contributor

@mbuechse mbuechse Mar 13, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This sentence is redundant: it states something that has been stated before quite clearly, and I do fear that we risk inconsistencies and make people uncertain as to where to find authoritative information at all.

edit I realize that the way I phrased this comment before was inappropriate, and therefore I rephrased it.

josephineSei marked this conversation as resolved.
Show resolved Hide resolved

### Example
mbuechse marked this conversation as resolved.
Show resolved Hide resolved

One volume type that is configured as an encrypted volume type in a ceph backend, with automated replication would fit both recommendations and will be enough to comply to this part of the volume type standard.

It should look like the following part:

```text
+--------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Field | Value |
+--------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------+
| access_project_ids | None |
| description | [scs:encrypted, replicated] Content will be replicated three times to ensure consistency and availability for your data. LUKS encryption is used. |
| id | d63307fb-167a-4aa0-9066-66595ea9fb21 |
| is_public | True |
| name | hdd-three-replicas-LUKS |
| properties | |
| qos_specs_id | None |
+--------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------+
```

## Related Documents

- corresponding [decision record document](https://github.com/SovereignCloudStack/standards/blob/main/Standards/scs-0111-v1-volume-type-decisions.md)

## Conformance Tests

The script `/Tests/iaas/volume-types/volume-types-check.py` connects to an OpenStack environment and tests
the following:

- for each volume type: if its description starts with `[scs:....]`, then this prefix is a feature list
(sorted, each entry at most once), and each entry is one of the possible features described here,
- the recommended volume types are present (otherwise, a WARNING is produced).

The return code is zero precisely when the test could be performed and the conditions are satisfied.
Otherwise, detailed errors and warnings are output to stderr.
148 changes: 148 additions & 0 deletions Tests/iaas/volume-types/volume-types-check.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
#!/usr/bin/env python3
"""Volume types checker

Check given cloud for conformance with SCS standard regarding
volume types, to be found under /Standards/scs-0112-v1-volume-types.md

Return code is 0 precisely when it could be verified that the standard is satisfied.
Otherwise the return code is the number of errors that occurred (up to 127 due to OS
restrictions); for further information, see the log messages on various channels:
CRITICAL for problems preventing the test to complete,
ERROR for violations of requirements,
INFO for violations of recommendations,
DEBUG for background information and problems that don't hinder the test.
"""
from collections import Counter, defaultdict
import getopt
import logging
import os
import re
import sys

import openstack
import openstack.cloud


logger = logging.getLogger(__name__)
RECOGNIZED_FEATURES = ('encrypted', 'replicated')


def extract_feature_list(description, pattern=re.compile(r"\[scs:([^\[\]]*)\]")):
"""Extract feature-list-like prefix

If given `description` starts with a feature-list-like prefix, return list of features,
otherwise None. To be more precise, we look for a string of this form:

`[scs:`feat1`, `...`, `...featN`]`

where N >= 1 and featJ is a string that doesn't contain any comma or brackets. We return
the list [feat1, ..., featN] of substrings.
"""
if not description:
# The description can be None or empty - we need to catch this here
return
match = pattern.match(description)
if not match:
return
fs = match.group(1)
if not fs:
return []
return fs.split(", ")
josephineSei marked this conversation as resolved.
Show resolved Hide resolved


def test_feature_list(type_name: str, fl: list[str], recognized=RECOGNIZED_FEATURES):
"""Test given list of features and report errors to error channel"""
if not fl:
# either None (no feature list) or empty feature list: nothing to check
return
if fl != sorted(fl):
logger.error(f"{type_name}: feature list not sorted")
ctr = Counter(fl)
duplicates = [key for key, c in ctr.items() if c > 1]
if duplicates:
logger.error(f"{type_name}: duplicate features: {', '.join(duplicates)}")
unrecognized = [f for f in ctr if f not in recognized]
if unrecognized:
logger.error(f"{type_name}: unrecognized features: {', '.join(unrecognized)}")


def print_usage(file=sys.stderr):
"""Help output"""
print("""Usage: entropy-check.py [options]
josephineSei marked this conversation as resolved.
Show resolved Hide resolved
This tool checks volume types according to the SCS Standard 0112 "Volume Types".
Options:
[-c/--os-cloud OS_CLOUD] sets cloud environment (default from OS_CLOUD env)
[-d/--debug] enables DEBUG logging channel
""", end='', file=file)


class CountingHandler(logging.Handler):
def __init__(self, level=logging.NOTSET):
super().__init__(level=level)
self.bylevel = Counter()

def handle(self, record):
self.bylevel[record.levelno] += 1


def main(argv):
# configure logging
logging.basicConfig(format='%(levelname)s: %(message)s', level=logging.INFO)
openstack.enable_logging(debug=False)
# count the number of log records per level (used for summary and return code)
counting_handler = CountingHandler(level=logging.INFO)
logger.addHandler(counting_handler)

try:
opts, args = getopt.gnu_getopt(argv, "c:i:hd", ["os-cloud=", "help", "debug"])
except getopt.GetoptError as exc:
logger.critical(f"{exc}")
print_usage()
return 1

cloud = os.environ.get("OS_CLOUD")
for opt in opts:
if opt[0] == "-h" or opt[0] == "--help":
print_usage()
return 0
if opt[0] == "-c" or opt[0] == "--os-cloud":
cloud = opt[1]
if opt[0] == "-d" or opt[0] == "--debug":
logging.getLogger().setLevel(logging.DEBUG)

if not cloud:
logger.critical("You need to have OS_CLOUD set or pass --os-cloud=CLOUD.")
return 1

try:
logger.debug(f"Connecting to cloud '{cloud}'")
with openstack.connect(cloud=cloud, timeout=32) as conn:
volume_types = conn.list_volume_types()
# collect volume types according to features
by_feature = defaultdict(list)
for typ in volume_types:
fl = extract_feature_list(typ.description)
if fl is None:
continue
logger.debug(f"{typ.name}: feature list {fl!r}")
test_feature_list(typ.name, fl)
for feat in fl:
by_feature[feat].append(typ.name)
logger.debug(f"volume types by feature: {dict(by_feature)}")
for feat in ('encrypted', 'replicated'):
if not by_feature[feat]:
logger.warning(f"Recommendation violated: missing {feat} volume type")
except BaseException as e:
logger.critical(f"{e!r}")
logger.debug("Exception info", exc_info=True)

c = counting_handler.bylevel
logger.debug(
"Total critical / error / warning: "
f"{c[logging.CRITICAL]} / {c[logging.ERROR]} / {c[logging.WARNING]}"
)
return min(127, c[logging.CRITICAL] + c[logging.ERROR]) # cap at 127 due to OS restrictions


if __name__ == "__main__":
sys.exit(main(sys.argv[1:]))
Loading