python-doniclient 1.0.3__tar.gz → 1.0.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- python_doniclient-1.0.4/PKG-INFO +110 -0
- python_doniclient-1.0.4/README.md +90 -0
- {python-doniclient-1.0.3 → python_doniclient-1.0.4}/doniclient/osc/cli.py +193 -58
- {python-doniclient-1.0.3 → python_doniclient-1.0.4}/doniclient/osc/common.py +11 -0
- {python-doniclient-1.0.3 → python_doniclient-1.0.4}/doniclient/v1/resource_fields.py +0 -1
- python_doniclient-1.0.4/pyproject.toml +60 -0
- python_doniclient-1.0.4/python_doniclient.egg-info/PKG-INFO +110 -0
- python_doniclient-1.0.4/python_doniclient.egg-info/SOURCES.txt +16 -0
- python_doniclient-1.0.4/python_doniclient.egg-info/dependency_links.txt +1 -0
- python_doniclient-1.0.4/python_doniclient.egg-info/entry_points.txt +16 -0
- python_doniclient-1.0.4/python_doniclient.egg-info/requires.txt +4 -0
- python_doniclient-1.0.4/python_doniclient.egg-info/top_level.txt +1 -0
- python_doniclient-1.0.4/setup.cfg +4 -0
- python-doniclient-1.0.3/PKG-INFO +0 -33
- python-doniclient-1.0.3/README.md +0 -5
- python-doniclient-1.0.3/doniclient/tests/__init__.py +0 -0
- python-doniclient-1.0.3/doniclient/tests/osc/__init__.py +0 -0
- python-doniclient-1.0.3/doniclient/tests/osc/fakes.py +0 -57
- python-doniclient-1.0.3/doniclient/tests/osc/test_hardware.py +0 -168
- python-doniclient-1.0.3/doniclient/tests/v1/__init__.py +0 -0
- python-doniclient-1.0.3/pyproject.toml +0 -71
- python-doniclient-1.0.3/setup.py +0 -61
- {python-doniclient-1.0.3 → python_doniclient-1.0.4}/doniclient/__init__.py +0 -0
- {python-doniclient-1.0.3 → python_doniclient-1.0.4}/doniclient/osc/__init__.py +0 -0
- {python-doniclient-1.0.3 → python_doniclient-1.0.4}/doniclient/osc/availability.py +0 -0
- {python-doniclient-1.0.3 → python_doniclient-1.0.4}/doniclient/osc/plugin.py +0 -0
- {python-doniclient-1.0.3 → python_doniclient-1.0.4}/doniclient/v1/client.py +0 -0
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: python-doniclient
|
|
3
|
+
Version: 1.0.4
|
|
4
|
+
Summary: This is a plugin for the openstack commandline client, to enable support for the Doni hardware inventory project
|
|
5
|
+
Author-email: Chameleon Cloud <contact@chameleoncloud.org>
|
|
6
|
+
License-Expression: Apache-2.0
|
|
7
|
+
Project-URL: Repository, https://github.com/ChameleonCloud/python-doniclient
|
|
8
|
+
Classifier: Environment :: OpenStack
|
|
9
|
+
Classifier: Intended Audience :: Information Technology
|
|
10
|
+
Classifier: Intended Audience :: System Administrators
|
|
11
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
14
|
+
Requires-Python: >=3.9
|
|
15
|
+
Description-Content-Type: text/markdown
|
|
16
|
+
Requires-Dist: osc-lib
|
|
17
|
+
Requires-Dist: python-dateutil
|
|
18
|
+
Requires-Dist: PyYAML>=5.4.1
|
|
19
|
+
Requires-Dist: keystoneauth1
|
|
20
|
+
|
|
21
|
+
# ChameleonCloud Python Doniclient CLI
|
|
22
|
+
|
|
23
|
+

|
|
24
|
+
|
|
25
|
+
Welcome to the ChameleonCloud Python Doniclient CLI repository! This command-line interface (CLI) provides a convenient way to interact with ChameleonCloud's Doni hardware inventory project, enabling you to manage and automate various hardware-related tasks.
|
|
26
|
+
|
|
27
|
+
## Table of Contents
|
|
28
|
+
|
|
29
|
+
- [Installation](#installation)
|
|
30
|
+
- [Authentication](#authentication)
|
|
31
|
+
- [Usage](#usage)
|
|
32
|
+
- [Testing](#testing)
|
|
33
|
+
- [Contributing](#contributing)
|
|
34
|
+
|
|
35
|
+
## Installation
|
|
36
|
+
|
|
37
|
+
You can install the ChameleonCloud Python Doniclient CLI using pip:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
pip install python-doniclient
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Cython sources issue
|
|
44
|
+
if you encounter an error message citing cython sources, please run the following to downgrade cython to a compatible version and use PyYaml 6.0+
|
|
45
|
+
```pip install "cython<3.0.0"```
|
|
46
|
+
|
|
47
|
+
## Authentication
|
|
48
|
+
Environment variables are the primary authentication method. Please refer to the [documentation on OpenRC scripts](https://chameleoncloud.readthedocs.io/en/latest/technical/cli.html#the-openstack-rc-script) to learn more about how to download and source your authentication credentials for the CLI;
|
|
49
|
+
|
|
50
|
+
## Usage
|
|
51
|
+
To use the CLI, you can run the `openstack hardware` command followed by the desired subcommand. `openstack hardware --help` shows all the subcommands available. Here's a basic usage examples:
|
|
52
|
+
|
|
53
|
+
### List all hardware in the Doni database.
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
openstack hardware list
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Options:
|
|
60
|
+
|
|
61
|
+
- --all: List hardware from all owners (requires admin rights).
|
|
62
|
+
- --long: Include all columns in the output.
|
|
63
|
+
- --worker-type <worker_type>: Filter by worker type.
|
|
64
|
+
- --worker-state <worker_state>: Filter by worker state (choices: PENDING, IN_PROGRESS, ERROR, STEADY).
|
|
65
|
+
|
|
66
|
+
For more details on specific commands and their options use --help or -h
|
|
67
|
+
|
|
68
|
+
### Create hardware in the Doni database
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
openstack hardware create --name <hardware_name> --hardware-type <hardware_type> --property <property_name>=<property_value>
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### List specific hardware item in Doni using name or uuid.
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
openstack hardware get <hardware_uuid>
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
openstack hardware get <hardware_name>
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### Set properties and name of an existing hardware item.
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
openstack hardware set <hardware_uuid> --name <new_hardware_name> --property <property_name>=<new_property_value>
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Sets new name and property for the item `<hardware_uuid>`
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
openstack hardware set <hardware_name> --property <property_name>=<new_property_value>
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Sets property for the item `<hardware_name`
|
|
97
|
+
|
|
98
|
+
### Unset properties of an existing hardware item.
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
openstack hardware unset <hardware_uuid> --property <property_name>
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Unsets property `<property_name>` for the item `<hardware_uuid`
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
openstack hardware update <hardware_name> --property <property_name>=<new_property_value>
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Unsets property `<property_name>` for the item `<hardware_name>`
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# ChameleonCloud Python Doniclient CLI
|
|
2
|
+
|
|
3
|
+

|
|
4
|
+
|
|
5
|
+
Welcome to the ChameleonCloud Python Doniclient CLI repository! This command-line interface (CLI) provides a convenient way to interact with ChameleonCloud's Doni hardware inventory project, enabling you to manage and automate various hardware-related tasks.
|
|
6
|
+
|
|
7
|
+
## Table of Contents
|
|
8
|
+
|
|
9
|
+
- [Installation](#installation)
|
|
10
|
+
- [Authentication](#authentication)
|
|
11
|
+
- [Usage](#usage)
|
|
12
|
+
- [Testing](#testing)
|
|
13
|
+
- [Contributing](#contributing)
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
You can install the ChameleonCloud Python Doniclient CLI using pip:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
pip install python-doniclient
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### Cython sources issue
|
|
24
|
+
if you encounter an error message citing cython sources, please run the following to downgrade cython to a compatible version and use PyYaml 6.0+
|
|
25
|
+
```pip install "cython<3.0.0"```
|
|
26
|
+
|
|
27
|
+
## Authentication
|
|
28
|
+
Environment variables are the primary authentication method. Please refer to the [documentation on OpenRC scripts](https://chameleoncloud.readthedocs.io/en/latest/technical/cli.html#the-openstack-rc-script) to learn more about how to download and source your authentication credentials for the CLI;
|
|
29
|
+
|
|
30
|
+
## Usage
|
|
31
|
+
To use the CLI, you can run the `openstack hardware` command followed by the desired subcommand. `openstack hardware --help` shows all the subcommands available. Here's a basic usage examples:
|
|
32
|
+
|
|
33
|
+
### List all hardware in the Doni database.
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
openstack hardware list
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Options:
|
|
40
|
+
|
|
41
|
+
- --all: List hardware from all owners (requires admin rights).
|
|
42
|
+
- --long: Include all columns in the output.
|
|
43
|
+
- --worker-type <worker_type>: Filter by worker type.
|
|
44
|
+
- --worker-state <worker_state>: Filter by worker state (choices: PENDING, IN_PROGRESS, ERROR, STEADY).
|
|
45
|
+
|
|
46
|
+
For more details on specific commands and their options use --help or -h
|
|
47
|
+
|
|
48
|
+
### Create hardware in the Doni database
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
openstack hardware create --name <hardware_name> --hardware-type <hardware_type> --property <property_name>=<property_value>
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### List specific hardware item in Doni using name or uuid.
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
openstack hardware get <hardware_uuid>
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
openstack hardware get <hardware_name>
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Set properties and name of an existing hardware item.
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
openstack hardware set <hardware_uuid> --name <new_hardware_name> --property <property_name>=<new_property_value>
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Sets new name and property for the item `<hardware_uuid>`
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
openstack hardware set <hardware_name> --property <property_name>=<new_property_value>
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Sets property for the item `<hardware_name`
|
|
77
|
+
|
|
78
|
+
### Unset properties of an existing hardware item.
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
openstack hardware unset <hardware_uuid> --property <property_name>
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Unsets property `<property_name>` for the item `<hardware_uuid`
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
openstack hardware update <hardware_name> --property <property_name>=<new_property_value>
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Unsets property `<property_name>` for the item `<hardware_name>`
|
|
@@ -13,6 +13,7 @@ from osc_lib.command import command
|
|
|
13
13
|
from doniclient.osc.common import (
|
|
14
14
|
BaseParser,
|
|
15
15
|
ExpandDotNotation,
|
|
16
|
+
ExpandDotNotationAndStoreTrue,
|
|
16
17
|
HardwarePatchCommand,
|
|
17
18
|
conditional_action,
|
|
18
19
|
)
|
|
@@ -40,32 +41,98 @@ class ListHardware(BaseParser, command.Lister):
|
|
|
40
41
|
help="Include all columns.",
|
|
41
42
|
action="store_true",
|
|
42
43
|
)
|
|
44
|
+
parser.add_argument(
|
|
45
|
+
"--worker-type",
|
|
46
|
+
metavar="<worker_type>",
|
|
47
|
+
help="Filter by worker type",
|
|
48
|
+
required=False,
|
|
49
|
+
default="",
|
|
50
|
+
)
|
|
51
|
+
parser.add_argument(
|
|
52
|
+
"--worker-state",
|
|
53
|
+
help="Filter by worker state",
|
|
54
|
+
choices=["PENDING", "IN_PROGRESS", "ERROR", "STEADY"],
|
|
55
|
+
required=False,
|
|
56
|
+
default="",
|
|
57
|
+
)
|
|
43
58
|
return parser
|
|
44
59
|
|
|
60
|
+
def extract_workers_state(self, workers):
|
|
61
|
+
# Extract worker types and their corresponding states and last errors from workers list
|
|
62
|
+
worker_details = {}
|
|
63
|
+
for worker in workers:
|
|
64
|
+
worker_type = worker.get("worker_type")
|
|
65
|
+
state = worker.get("state")
|
|
66
|
+
last_error = worker.get("state_details", {}).get("last_error")
|
|
67
|
+
if worker_type and (state or last_error):
|
|
68
|
+
if worker_type not in worker_details:
|
|
69
|
+
worker_details[worker_type] = {}
|
|
70
|
+
if state:
|
|
71
|
+
worker_details[worker_type]["state"] = state
|
|
72
|
+
if last_error:
|
|
73
|
+
worker_details[worker_type]["last_error"] = last_error
|
|
74
|
+
return worker_details
|
|
75
|
+
|
|
45
76
|
def take_action(self, parsed_args):
|
|
46
|
-
"""List all
|
|
77
|
+
"""List all hardware items in Doni."""
|
|
78
|
+
|
|
47
79
|
hw_client = self.app.client_manager.inventory
|
|
48
80
|
columns = res_fields.HARDWARE_RESOURCE.fields
|
|
49
|
-
labels = res_fields.HARDWARE_RESOURCE.labels
|
|
81
|
+
labels = list(res_fields.HARDWARE_RESOURCE.labels) # Convert tuple to list
|
|
50
82
|
|
|
51
83
|
if parsed_args.long:
|
|
52
84
|
columns = res_fields.HARDWARE_DETAILED_RESOURCE.fields
|
|
53
|
-
labels =
|
|
85
|
+
labels = list(
|
|
86
|
+
res_fields.HARDWARE_DETAILED_RESOURCE.labels
|
|
87
|
+
) # Convert tuple to list
|
|
54
88
|
|
|
89
|
+
# Fetch hardware data based on --all option
|
|
55
90
|
if parsed_args.all:
|
|
56
91
|
data = hw_client.export()
|
|
57
92
|
else:
|
|
58
93
|
data = hw_client.list()
|
|
59
94
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
95
|
+
worker_types = []
|
|
96
|
+
output_data = []
|
|
97
|
+
|
|
98
|
+
# Extract filter values for better readability
|
|
99
|
+
worker_type_filter = parsed_args.worker_type
|
|
100
|
+
worker_state_filter = parsed_args.worker_state
|
|
101
|
+
|
|
102
|
+
for hardware in data:
|
|
103
|
+
workers = hardware.get("workers", [])
|
|
104
|
+
worker_details = self.extract_workers_state(workers)
|
|
105
|
+
|
|
106
|
+
# Apply worker type and state filters
|
|
107
|
+
if (worker_type_filter and worker_type_filter not in worker_details) or (
|
|
108
|
+
worker_state_filter
|
|
109
|
+
and all(worker_state_filter != details["state"] for details in worker_details.values())
|
|
110
|
+
):
|
|
111
|
+
continue
|
|
112
|
+
|
|
113
|
+
output_item = oscutils.get_dict_properties(hardware, columns)
|
|
114
|
+
|
|
115
|
+
# Apply combined worker type and state filter
|
|
116
|
+
if worker_type_filter and worker_state_filter:
|
|
117
|
+
details = worker_details.get(worker_type_filter, {})
|
|
118
|
+
if worker_state_filter not in details["state"]:
|
|
119
|
+
continue
|
|
120
|
+
|
|
121
|
+
for worker_type, details in worker_details.items():
|
|
122
|
+
worker_state = details.get("state", "-")
|
|
123
|
+
worker_error = details.get("last_error", "-")
|
|
124
|
+
output_item = output_item + (worker_state,)
|
|
125
|
+
output_item = output_item + (worker_error,)
|
|
126
|
+
|
|
127
|
+
if worker_type not in worker_types:
|
|
128
|
+
worker_types.append(worker_type)
|
|
129
|
+
worker_types.append(worker_type + " last error")
|
|
130
|
+
|
|
131
|
+
output_data.append(output_item)
|
|
132
|
+
|
|
133
|
+
labels += worker_types # Add worker types to labels list
|
|
134
|
+
return labels, output_data
|
|
135
|
+
|
|
69
136
|
|
|
70
137
|
|
|
71
138
|
class GetHardware(BaseParser, command.ShowOne):
|
|
@@ -93,7 +160,13 @@ class DeleteHardware(BaseParser):
|
|
|
93
160
|
def take_action(self, parsed_args):
|
|
94
161
|
hw_client = self.app.client_manager.inventory
|
|
95
162
|
try:
|
|
96
|
-
|
|
163
|
+
data = oscutils.find_resource(hw_client, parsed_args.uuid)
|
|
164
|
+
except HttpError as ex:
|
|
165
|
+
LOG.error(ex.response.text)
|
|
166
|
+
raise ex
|
|
167
|
+
uuid = data["uuid"]
|
|
168
|
+
try:
|
|
169
|
+
hw_client.delete(uuid)
|
|
97
170
|
except HttpError as ex:
|
|
98
171
|
LOG.error(ex.response.text)
|
|
99
172
|
raise ex
|
|
@@ -107,15 +180,20 @@ class SyncHardware(BaseParser):
|
|
|
107
180
|
def take_action(self, parsed_args):
|
|
108
181
|
hw_client = self.app.client_manager.inventory
|
|
109
182
|
try:
|
|
110
|
-
|
|
183
|
+
data = oscutils.find_resource(hw_client, parsed_args.uuid)
|
|
184
|
+
except HttpError as ex:
|
|
185
|
+
LOG.error(ex.response.text)
|
|
186
|
+
raise ex
|
|
187
|
+
uuid = data["uuid"]
|
|
188
|
+
try:
|
|
189
|
+
hw_client.sync(uuid)
|
|
111
190
|
except HttpError as ex:
|
|
112
191
|
LOG.error(ex.response.text)
|
|
113
192
|
raise ex
|
|
114
193
|
|
|
115
194
|
|
|
116
|
-
def _add_prop_flag_group(parser, hardware_type, prop_flags):
|
|
195
|
+
def _add_prop_flag_group(parser, hardware_type, prop_flags, prog_name):
|
|
117
196
|
"""Register a mapping of flags for corresponding hardware properties.
|
|
118
|
-
|
|
119
197
|
Args:
|
|
120
198
|
parser (argparse.Parser): the parent parser
|
|
121
199
|
group_name (str): the name of the new argument grouping. This is just used
|
|
@@ -124,21 +202,70 @@ def _add_prop_flag_group(parser, hardware_type, prop_flags):
|
|
|
124
202
|
containing information about how the flag should be displayed and parsed.
|
|
125
203
|
Importantly, the property name MUST match some field on the ``properties``
|
|
126
204
|
dict on the target hardware type.
|
|
205
|
+
prog_name (str): command executed (openstack hardware <set/unset>)
|
|
127
206
|
"""
|
|
128
207
|
# Only store this flag in the resulting args if the hardware_type is in effect.
|
|
129
208
|
condition_fn = lambda args: args.hardware_type == hardware_type
|
|
130
209
|
group = parser.add_argument_group(f"{hardware_type} properties")
|
|
131
210
|
for prop_name, flag in prop_flags.items():
|
|
211
|
+
argument_params = {}
|
|
212
|
+
argument_params["type"] = flag.type
|
|
213
|
+
argument_params["default"] = flag.default
|
|
214
|
+
argument_params["metavar"] = f"<{flag.flag}>"
|
|
215
|
+
argument_params["dest"] = f"properties.{prop_name}"
|
|
216
|
+
argument_params["action"] = conditional_action(ExpandDotNotation, condition_fn)
|
|
217
|
+
if 'unset' in prog_name:
|
|
218
|
+
argument_params["nargs"] = 0
|
|
219
|
+
argument_params["type"] = None
|
|
220
|
+
argument_params["default"] = None
|
|
221
|
+
argument_params["metavar"] = None
|
|
222
|
+
argument_params["action"] = conditional_action(ExpandDotNotationAndStoreTrue, condition_fn)
|
|
132
223
|
group.add_argument(
|
|
133
224
|
f"--{flag.flag}",
|
|
134
|
-
|
|
135
|
-
default=flag.default,
|
|
136
|
-
metavar=f"<{flag.flag}>",
|
|
137
|
-
dest=f"properties.{prop_name}",
|
|
138
|
-
action=conditional_action(ExpandDotNotation, condition_fn),
|
|
225
|
+
**argument_params
|
|
139
226
|
)
|
|
140
227
|
|
|
141
228
|
|
|
229
|
+
class HardwarePropertyFlags:
|
|
230
|
+
baremetal_property_flags = {
|
|
231
|
+
"management_address": PropertyFlag("management_address", str, None),
|
|
232
|
+
"ipmi_username": PropertyFlag("ipmi_username", str, None),
|
|
233
|
+
"ipmi_password": PropertyFlag("ipmi_password", str, None),
|
|
234
|
+
"ipmi_terminal_port": PropertyFlag("ipmi_terminal_port", int, None),
|
|
235
|
+
"baremetal_deploy_kernel_image": PropertyFlag(
|
|
236
|
+
"deploy_kernel", str, None
|
|
237
|
+
),
|
|
238
|
+
"baremetal_deploy_ramdisk_image": PropertyFlag(
|
|
239
|
+
"deploy_ramdisk", str, None
|
|
240
|
+
),
|
|
241
|
+
# FIXME(jason): why is the flag named ironic_?
|
|
242
|
+
"baremetal_driver": PropertyFlag("ironic_driver", str, None),
|
|
243
|
+
"baremetal_resource_class": PropertyFlag(
|
|
244
|
+
"resource_class", str, "baremetal"
|
|
245
|
+
),
|
|
246
|
+
"baremetal_capabilities": PropertyFlag(
|
|
247
|
+
"capabilities", json.loads, None
|
|
248
|
+
),
|
|
249
|
+
"cpu_arch": PropertyFlag("cpu_arch", str, "x86_64"),
|
|
250
|
+
"node_type": PropertyFlag("blazar_node_type", str, None),
|
|
251
|
+
"su_factor": PropertyFlag("blazar_su_factor", float, 1.0),
|
|
252
|
+
"placement": PropertyFlag("placement", json.loads, None),
|
|
253
|
+
"interfaces": PropertyFlag("interfaces", json.loads, {}),
|
|
254
|
+
}
|
|
255
|
+
device_property_flags = {
|
|
256
|
+
"machine_name": PropertyFlag("machine-name", str, None),
|
|
257
|
+
"contact_email": PropertyFlag("contact-email", str, None),
|
|
258
|
+
"channels": PropertyFlag("channels", json.loads, None),
|
|
259
|
+
"application_credential_id": PropertyFlag(
|
|
260
|
+
"application-credential-id", str, None
|
|
261
|
+
),
|
|
262
|
+
"application_credential_secret": PropertyFlag(
|
|
263
|
+
"application-credential-secret", str, None
|
|
264
|
+
),
|
|
265
|
+
"local_egress": PropertyFlag("local-egress", str, None),
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
|
|
142
269
|
class CreateOrUpdateParser(BaseParser):
|
|
143
270
|
def get_parser(self, prog_name):
|
|
144
271
|
parser = super().get_parser(prog_name)
|
|
@@ -162,48 +289,15 @@ class CreateOrUpdateParser(BaseParser):
|
|
|
162
289
|
_add_prop_flag_group(
|
|
163
290
|
parser,
|
|
164
291
|
"baremetal",
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
"ipmi_username": PropertyFlag("ipmi_username", str, None),
|
|
168
|
-
"ipmi_password": PropertyFlag("ipmi_password", str, None),
|
|
169
|
-
"ipmi_terminal_port": PropertyFlag("ipmi_terminal_port", int, None),
|
|
170
|
-
"baremetal_deploy_kernel_image": PropertyFlag(
|
|
171
|
-
"deploy_kernel", str, None
|
|
172
|
-
),
|
|
173
|
-
"baremetal_deploy_ramdisk_image": PropertyFlag(
|
|
174
|
-
"deploy_ramdisk", str, None
|
|
175
|
-
),
|
|
176
|
-
# FIXME(jason): why is the flag named ironic_?
|
|
177
|
-
"baremetal_driver": PropertyFlag("ironic_driver", str, None),
|
|
178
|
-
"baremetal_resource_class": PropertyFlag(
|
|
179
|
-
"resource_class", str, "baremetal"
|
|
180
|
-
),
|
|
181
|
-
"baremetal_capabilities": PropertyFlag(
|
|
182
|
-
"capabilities", json.loads, None
|
|
183
|
-
),
|
|
184
|
-
"cpu_arch": PropertyFlag("cpu_arch", str, "x86_64"),
|
|
185
|
-
"node_type": PropertyFlag("blazar_node_type", str, None),
|
|
186
|
-
"su_factor": PropertyFlag("blazar_su_factor", float, 1.0),
|
|
187
|
-
"placement": PropertyFlag("placement", json.loads, None),
|
|
188
|
-
"interfaces": PropertyFlag("interfaces", json.loads, {}),
|
|
189
|
-
},
|
|
292
|
+
HardwarePropertyFlags.baremetal_property_flags,
|
|
293
|
+
prog_name
|
|
190
294
|
)
|
|
191
295
|
|
|
192
296
|
_add_prop_flag_group(
|
|
193
297
|
parser,
|
|
194
298
|
"device",
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
"contact_email": PropertyFlag("contact-email", str, None),
|
|
198
|
-
"channels": PropertyFlag("channels", json.loads, None),
|
|
199
|
-
"application_credential_id": PropertyFlag(
|
|
200
|
-
"application-credential-id", str, None
|
|
201
|
-
),
|
|
202
|
-
"application_credential_secret": PropertyFlag(
|
|
203
|
-
"application-credential-secret", str, None
|
|
204
|
-
),
|
|
205
|
-
"local_egress": PropertyFlag("local-egress", str, None),
|
|
206
|
-
},
|
|
299
|
+
HardwarePropertyFlags.device_property_flags,
|
|
300
|
+
prog_name
|
|
207
301
|
)
|
|
208
302
|
|
|
209
303
|
return parser
|
|
@@ -284,6 +378,21 @@ class UpdateHardware(CreateOrUpdateParser, HardwarePatchCommand):
|
|
|
284
378
|
|
|
285
379
|
return patch
|
|
286
380
|
|
|
381
|
+
def take_action(self, parsed_args):
|
|
382
|
+
hw_client = self.app.client_manager.inventory
|
|
383
|
+
try:
|
|
384
|
+
data = oscutils.find_resource(hw_client, parsed_args.uuid)
|
|
385
|
+
except HttpError as ex:
|
|
386
|
+
LOG.error(ex.response.text)
|
|
387
|
+
raise ex
|
|
388
|
+
uuid = data["uuid"]
|
|
389
|
+
patch = self.get_patch(parsed_args)
|
|
390
|
+
try:
|
|
391
|
+
hw_client.update(uuid, patch)
|
|
392
|
+
except HttpError as ex:
|
|
393
|
+
LOG.error(ex.response.text)
|
|
394
|
+
raise ex
|
|
395
|
+
|
|
287
396
|
|
|
288
397
|
class ImportHardware(BaseParser):
|
|
289
398
|
def get_parser(self, prog_name):
|
|
@@ -313,3 +422,29 @@ class ImportHardware(BaseParser):
|
|
|
313
422
|
raise ex
|
|
314
423
|
else:
|
|
315
424
|
LOG.debug(data)
|
|
425
|
+
|
|
426
|
+
|
|
427
|
+
class UnsetHardware(UpdateHardware):
|
|
428
|
+
"""Unset properties of existing hardware item."""
|
|
429
|
+
|
|
430
|
+
needs_uuid = True
|
|
431
|
+
|
|
432
|
+
def get_patch(self, parsed_args):
|
|
433
|
+
patch = []
|
|
434
|
+
|
|
435
|
+
field_map = {
|
|
436
|
+
"name": "name",
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
for key, val in field_map.items():
|
|
440
|
+
arg = getattr(parsed_args, key, None)
|
|
441
|
+
if arg:
|
|
442
|
+
patch.append({"op": "remove", "path": f"/{val}", "value": arg})
|
|
443
|
+
|
|
444
|
+
try:
|
|
445
|
+
for key, val in parsed_args.properties.items():
|
|
446
|
+
patch.append({"op": "remove", "path": f"/properties/{key}", "value": val})
|
|
447
|
+
except AttributeError:
|
|
448
|
+
pass
|
|
449
|
+
|
|
450
|
+
return patch
|
|
@@ -63,6 +63,17 @@ class ExpandDotNotation(argparse.Action):
|
|
|
63
63
|
getattr(namespace, group).update({dest: values})
|
|
64
64
|
|
|
65
65
|
|
|
66
|
+
class ExpandDotNotationAndStoreTrue(argparse.Action):
|
|
67
|
+
"""Set property based on dest.key."""
|
|
68
|
+
|
|
69
|
+
def __call__(self, parser, namespace, values, option_string=None):
|
|
70
|
+
group, dest = self.dest.split(".", 2)
|
|
71
|
+
|
|
72
|
+
if not hasattr(namespace, group):
|
|
73
|
+
setattr(namespace, group, {})
|
|
74
|
+
getattr(namespace, group).update({dest: True})
|
|
75
|
+
|
|
76
|
+
|
|
66
77
|
class BaseParser(command.Command):
|
|
67
78
|
"""Base Parser for use with Doni commands.
|
|
68
79
|
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "python-doniclient"
|
|
3
|
+
version = "1.0.4"
|
|
4
|
+
description = "This is a plugin for the openstack commandline client, to enable support for the Doni hardware inventory project"
|
|
5
|
+
authors = [{ name = "Chameleon Cloud", email = "contact@chameleoncloud.org" }]
|
|
6
|
+
requires-python = ">=3.9"
|
|
7
|
+
readme = "README.md"
|
|
8
|
+
license = "Apache-2.0"
|
|
9
|
+
classifiers = [
|
|
10
|
+
"Environment :: OpenStack",
|
|
11
|
+
"Intended Audience :: Information Technology",
|
|
12
|
+
"Intended Audience :: System Administrators",
|
|
13
|
+
"Operating System :: POSIX :: Linux",
|
|
14
|
+
"Programming Language :: Python :: 3",
|
|
15
|
+
"Programming Language :: Python :: 3.9",
|
|
16
|
+
|
|
17
|
+
]
|
|
18
|
+
dependencies = [
|
|
19
|
+
"osc-lib",
|
|
20
|
+
"python-dateutil",
|
|
21
|
+
"PyYAML>=5.4.1",
|
|
22
|
+
"keystoneauth1",
|
|
23
|
+
]
|
|
24
|
+
|
|
25
|
+
[project.urls]
|
|
26
|
+
Repository = "https://github.com/ChameleonCloud/python-doniclient"
|
|
27
|
+
|
|
28
|
+
[project.entry-points."openstack.cli.extension"]
|
|
29
|
+
inventory = "doniclient.osc.plugin"
|
|
30
|
+
|
|
31
|
+
[project.entry-points."openstack.inventory.v1"]
|
|
32
|
+
hardware_list = "doniclient.osc.cli:ListHardware"
|
|
33
|
+
hardware_import = "doniclient.osc.cli:ImportHardware"
|
|
34
|
+
hardware_show = "doniclient.osc.cli:GetHardware"
|
|
35
|
+
hardware_create = "doniclient.osc.cli:CreateHardware"
|
|
36
|
+
hardware_set = "doniclient.osc.cli:UpdateHardware"
|
|
37
|
+
hardware_unset = "doniclient.osc.cli:UnsetHardware"
|
|
38
|
+
hardware_delete = "doniclient.osc.cli:DeleteHardware"
|
|
39
|
+
hardware_sync = "doniclient.osc.cli:SyncHardware"
|
|
40
|
+
hardware_availability_list = "doniclient.osc.availability:ListHardwareAvailability"
|
|
41
|
+
hardware_availability_set = "doniclient.osc.availability:UpdateHardwareAvailability"
|
|
42
|
+
hardware_availability_add = "doniclient.osc.availability:AddHardwareAvailability"
|
|
43
|
+
hardware_availability_remove = "doniclient.osc.availability:RemoveHardwareAvailability"
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
[dependency-groups]
|
|
47
|
+
dev = [
|
|
48
|
+
"oslotest",
|
|
49
|
+
"python-openstackclient",
|
|
50
|
+
"ruff",
|
|
51
|
+
"stestr",
|
|
52
|
+
]
|
|
53
|
+
|
|
54
|
+
[build-system]
|
|
55
|
+
requires = ["setuptools>=64"]
|
|
56
|
+
build-backend = "setuptools.build_meta"
|
|
57
|
+
|
|
58
|
+
[tool.setuptools.packages.find]
|
|
59
|
+
include = ["doniclient*"]
|
|
60
|
+
exclude = ["doniclient.tests*"]
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: python-doniclient
|
|
3
|
+
Version: 1.0.4
|
|
4
|
+
Summary: This is a plugin for the openstack commandline client, to enable support for the Doni hardware inventory project
|
|
5
|
+
Author-email: Chameleon Cloud <contact@chameleoncloud.org>
|
|
6
|
+
License-Expression: Apache-2.0
|
|
7
|
+
Project-URL: Repository, https://github.com/ChameleonCloud/python-doniclient
|
|
8
|
+
Classifier: Environment :: OpenStack
|
|
9
|
+
Classifier: Intended Audience :: Information Technology
|
|
10
|
+
Classifier: Intended Audience :: System Administrators
|
|
11
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
14
|
+
Requires-Python: >=3.9
|
|
15
|
+
Description-Content-Type: text/markdown
|
|
16
|
+
Requires-Dist: osc-lib
|
|
17
|
+
Requires-Dist: python-dateutil
|
|
18
|
+
Requires-Dist: PyYAML>=5.4.1
|
|
19
|
+
Requires-Dist: keystoneauth1
|
|
20
|
+
|
|
21
|
+
# ChameleonCloud Python Doniclient CLI
|
|
22
|
+
|
|
23
|
+

|
|
24
|
+
|
|
25
|
+
Welcome to the ChameleonCloud Python Doniclient CLI repository! This command-line interface (CLI) provides a convenient way to interact with ChameleonCloud's Doni hardware inventory project, enabling you to manage and automate various hardware-related tasks.
|
|
26
|
+
|
|
27
|
+
## Table of Contents
|
|
28
|
+
|
|
29
|
+
- [Installation](#installation)
|
|
30
|
+
- [Authentication](#authentication)
|
|
31
|
+
- [Usage](#usage)
|
|
32
|
+
- [Testing](#testing)
|
|
33
|
+
- [Contributing](#contributing)
|
|
34
|
+
|
|
35
|
+
## Installation
|
|
36
|
+
|
|
37
|
+
You can install the ChameleonCloud Python Doniclient CLI using pip:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
pip install python-doniclient
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Cython sources issue
|
|
44
|
+
if you encounter an error message citing cython sources, please run the following to downgrade cython to a compatible version and use PyYaml 6.0+
|
|
45
|
+
```pip install "cython<3.0.0"```
|
|
46
|
+
|
|
47
|
+
## Authentication
|
|
48
|
+
Environment variables are the primary authentication method. Please refer to the [documentation on OpenRC scripts](https://chameleoncloud.readthedocs.io/en/latest/technical/cli.html#the-openstack-rc-script) to learn more about how to download and source your authentication credentials for the CLI;
|
|
49
|
+
|
|
50
|
+
## Usage
|
|
51
|
+
To use the CLI, you can run the `openstack hardware` command followed by the desired subcommand. `openstack hardware --help` shows all the subcommands available. Here's a basic usage examples:
|
|
52
|
+
|
|
53
|
+
### List all hardware in the Doni database.
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
openstack hardware list
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Options:
|
|
60
|
+
|
|
61
|
+
- --all: List hardware from all owners (requires admin rights).
|
|
62
|
+
- --long: Include all columns in the output.
|
|
63
|
+
- --worker-type <worker_type>: Filter by worker type.
|
|
64
|
+
- --worker-state <worker_state>: Filter by worker state (choices: PENDING, IN_PROGRESS, ERROR, STEADY).
|
|
65
|
+
|
|
66
|
+
For more details on specific commands and their options use --help or -h
|
|
67
|
+
|
|
68
|
+
### Create hardware in the Doni database
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
openstack hardware create --name <hardware_name> --hardware-type <hardware_type> --property <property_name>=<property_value>
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### List specific hardware item in Doni using name or uuid.
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
openstack hardware get <hardware_uuid>
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
openstack hardware get <hardware_name>
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### Set properties and name of an existing hardware item.
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
openstack hardware set <hardware_uuid> --name <new_hardware_name> --property <property_name>=<new_property_value>
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Sets new name and property for the item `<hardware_uuid>`
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
openstack hardware set <hardware_name> --property <property_name>=<new_property_value>
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Sets property for the item `<hardware_name`
|
|
97
|
+
|
|
98
|
+
### Unset properties of an existing hardware item.
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
openstack hardware unset <hardware_uuid> --property <property_name>
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Unsets property `<property_name>` for the item `<hardware_uuid`
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
openstack hardware update <hardware_name> --property <property_name>=<new_property_value>
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Unsets property `<property_name>` for the item `<hardware_name>`
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
README.md
|
|
2
|
+
pyproject.toml
|
|
3
|
+
doniclient/__init__.py
|
|
4
|
+
doniclient/osc/__init__.py
|
|
5
|
+
doniclient/osc/availability.py
|
|
6
|
+
doniclient/osc/cli.py
|
|
7
|
+
doniclient/osc/common.py
|
|
8
|
+
doniclient/osc/plugin.py
|
|
9
|
+
doniclient/v1/client.py
|
|
10
|
+
doniclient/v1/resource_fields.py
|
|
11
|
+
python_doniclient.egg-info/PKG-INFO
|
|
12
|
+
python_doniclient.egg-info/SOURCES.txt
|
|
13
|
+
python_doniclient.egg-info/dependency_links.txt
|
|
14
|
+
python_doniclient.egg-info/entry_points.txt
|
|
15
|
+
python_doniclient.egg-info/requires.txt
|
|
16
|
+
python_doniclient.egg-info/top_level.txt
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
[openstack.cli.extension]
|
|
2
|
+
inventory = doniclient.osc.plugin
|
|
3
|
+
|
|
4
|
+
[openstack.inventory.v1]
|
|
5
|
+
hardware_availability_add = doniclient.osc.availability:AddHardwareAvailability
|
|
6
|
+
hardware_availability_list = doniclient.osc.availability:ListHardwareAvailability
|
|
7
|
+
hardware_availability_remove = doniclient.osc.availability:RemoveHardwareAvailability
|
|
8
|
+
hardware_availability_set = doniclient.osc.availability:UpdateHardwareAvailability
|
|
9
|
+
hardware_create = doniclient.osc.cli:CreateHardware
|
|
10
|
+
hardware_delete = doniclient.osc.cli:DeleteHardware
|
|
11
|
+
hardware_import = doniclient.osc.cli:ImportHardware
|
|
12
|
+
hardware_list = doniclient.osc.cli:ListHardware
|
|
13
|
+
hardware_set = doniclient.osc.cli:UpdateHardware
|
|
14
|
+
hardware_show = doniclient.osc.cli:GetHardware
|
|
15
|
+
hardware_sync = doniclient.osc.cli:SyncHardware
|
|
16
|
+
hardware_unset = doniclient.osc.cli:UnsetHardware
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
doniclient
|
python-doniclient-1.0.3/PKG-INFO
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.1
|
|
2
|
-
Name: python-doniclient
|
|
3
|
-
Version: 1.0.3
|
|
4
|
-
Summary: This is a plugin for the openstack commandline client, to enable support for the Doni hardware inventory project
|
|
5
|
-
Home-page: https://github.com/ChameleonCloud/python-doniclient
|
|
6
|
-
License: Apache-2.0
|
|
7
|
-
Author: Chameleon Cloud
|
|
8
|
-
Author-email: contact@chameleoncloud.org
|
|
9
|
-
Requires-Python: >=3.7,<4.0
|
|
10
|
-
Classifier: Environment :: OpenStack
|
|
11
|
-
Classifier: Intended Audience :: Information Technology
|
|
12
|
-
Classifier: Intended Audience :: System Administrators
|
|
13
|
-
Classifier: License :: OSI Approved :: Apache Software License
|
|
14
|
-
Classifier: Operating System :: POSIX :: Linux
|
|
15
|
-
Classifier: Programming Language :: Python :: 3
|
|
16
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
-
Classifier: Programming Language :: Python :: 3.7
|
|
18
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
19
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
20
|
-
Requires-Dist: PyYAML (<=5.4.1)
|
|
21
|
-
Requires-Dist: keystoneauth1 (<=4.4.0)
|
|
22
|
-
Requires-Dist: osc-lib (<=2.4.2)
|
|
23
|
-
Requires-Dist: python-dateutil (<=2.8.2)
|
|
24
|
-
Requires-Dist: python-openstackclient[cli] (<=5.6.0)
|
|
25
|
-
Project-URL: Repository, https://github.com/ChameleonCloud/python-doniclient
|
|
26
|
-
Description-Content-Type: text/markdown
|
|
27
|
-
|
|
28
|
-
# python-doniclient
|
|
29
|
-
|
|
30
|
-
Client for Chameleon Registration Service
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
File without changes
|
|
File without changes
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
"""Define fake objects for Doni CLI tests."""
|
|
2
|
-
|
|
3
|
-
import copy
|
|
4
|
-
import datetime
|
|
5
|
-
import uuid
|
|
6
|
-
from unittest import mock
|
|
7
|
-
|
|
8
|
-
from openstackclient.tests.unit import fakes, utils
|
|
9
|
-
|
|
10
|
-
hardware_uuid = uuid.uuid4().hex
|
|
11
|
-
hardware_name = "fake name"
|
|
12
|
-
hardware_project_id = uuid.uuid4().hex
|
|
13
|
-
hardware_created_at = datetime.datetime.utcnow().isoformat()
|
|
14
|
-
hardware_updated_at = datetime.datetime.utcnow().isoformat()
|
|
15
|
-
hardware_baremetal_type = "baremetal"
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
class FakeHardware(object):
|
|
19
|
-
@staticmethod
|
|
20
|
-
def create_one_hardware(attrs=None):
|
|
21
|
-
"""Create a fake hw item."""
|
|
22
|
-
attrs = attrs or {}
|
|
23
|
-
|
|
24
|
-
hw_info = {
|
|
25
|
-
"created_at": hardware_created_at,
|
|
26
|
-
"hardware_type": hardware_baremetal_type,
|
|
27
|
-
"name": hardware_name,
|
|
28
|
-
"project_id": hardware_project_id,
|
|
29
|
-
"properties": {},
|
|
30
|
-
"updated_at": hardware_updated_at,
|
|
31
|
-
"uuid": hardware_uuid,
|
|
32
|
-
"workers": [],
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
hw_info.update(attrs)
|
|
36
|
-
# TODO: client currently returns Dicts, not Resource objects.
|
|
37
|
-
# hw_item = fakes.FakeResource(info=copy.deepcopy(hw_info), loaded=True)
|
|
38
|
-
return hw_info
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
class FakeHardwareClient(object):
|
|
42
|
-
def __init__(self, **kwargs) -> None:
|
|
43
|
-
self.hardware = mock.Mock()
|
|
44
|
-
self.hardware.resource_class = fakes.FakeResource(None, {})
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
class TestHardware(utils.TestCommand):
|
|
48
|
-
def setUp(self):
|
|
49
|
-
super(TestHardware, self).setUp()
|
|
50
|
-
|
|
51
|
-
self.app.client_manager.auth_ref = mock.Mock(auth_token="TOKEN")
|
|
52
|
-
self.app.client_manager.inventory = mock.Mock()
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
class FakeHardwareResource(fakes.FakeResource):
|
|
56
|
-
def get_keys(self):
|
|
57
|
-
return {"property": "value"}
|
|
@@ -1,168 +0,0 @@
|
|
|
1
|
-
from doniclient.osc import cli as hardware_cli
|
|
2
|
-
from doniclient.tests.osc import fakes as hardware_fakes
|
|
3
|
-
|
|
4
|
-
FAKE_HARDWARE_UUID = hardware_fakes.hardware_uuid
|
|
5
|
-
|
|
6
|
-
UPDATE_PARAMS = [
|
|
7
|
-
(
|
|
8
|
-
"baremetal",
|
|
9
|
-
"--mgmt_addr",
|
|
10
|
-
"mgmt_addr",
|
|
11
|
-
"/properties/mgmt_addr",
|
|
12
|
-
"fake-mgmt_addr",
|
|
13
|
-
),
|
|
14
|
-
(
|
|
15
|
-
"device",
|
|
16
|
-
"--machine-name",
|
|
17
|
-
"machine_name",
|
|
18
|
-
"/properties/machine_name",
|
|
19
|
-
"jetson-nano",
|
|
20
|
-
),
|
|
21
|
-
(
|
|
22
|
-
"device",
|
|
23
|
-
"--contact-email",
|
|
24
|
-
"contact_email",
|
|
25
|
-
"/properties/contact_email",
|
|
26
|
-
"test@foo.bar",
|
|
27
|
-
),
|
|
28
|
-
("device", "--local-egress", "local_egress", "/properties/local_egress", "allow"),
|
|
29
|
-
]
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
class TestHardware(hardware_fakes.TestHardware):
|
|
33
|
-
def setUp(self):
|
|
34
|
-
super(TestHardware, self).setUp()
|
|
35
|
-
|
|
36
|
-
# Get a shortcut to the baremetal manager mock
|
|
37
|
-
self.hardware_mock = self.app.client_manager.inventory
|
|
38
|
-
self.hardware_mock.reset_mock()
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
class TestHardwareShow(TestHardware):
|
|
42
|
-
def setUp(self):
|
|
43
|
-
super().setUp()
|
|
44
|
-
|
|
45
|
-
self.hardware_mock.get_by_uuid.return_value = (
|
|
46
|
-
hardware_fakes.FakeHardware.create_one_hardware()
|
|
47
|
-
)
|
|
48
|
-
|
|
49
|
-
self.cmd = hardware_cli.GetHardware(self.app, None)
|
|
50
|
-
|
|
51
|
-
def test_hardware_show(self):
|
|
52
|
-
arglist = [FAKE_HARDWARE_UUID]
|
|
53
|
-
verifylist = []
|
|
54
|
-
|
|
55
|
-
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
|
56
|
-
|
|
57
|
-
# DisplayCommandBase.take_action() returns two tuples
|
|
58
|
-
columns, data = self.cmd.take_action(parsed_args)
|
|
59
|
-
|
|
60
|
-
# Set expected values
|
|
61
|
-
args = [FAKE_HARDWARE_UUID]
|
|
62
|
-
|
|
63
|
-
self.hardware_mock.get_by_uuid.assert_called_with(*args)
|
|
64
|
-
|
|
65
|
-
collist = (
|
|
66
|
-
"created_at",
|
|
67
|
-
"hardware_type",
|
|
68
|
-
"name",
|
|
69
|
-
"project_id",
|
|
70
|
-
"properties",
|
|
71
|
-
"updated_at",
|
|
72
|
-
"uuid",
|
|
73
|
-
"workers",
|
|
74
|
-
)
|
|
75
|
-
self.assertEqual(collist, columns)
|
|
76
|
-
|
|
77
|
-
datalist = (
|
|
78
|
-
hardware_fakes.hardware_created_at,
|
|
79
|
-
hardware_fakes.hardware_baremetal_type,
|
|
80
|
-
hardware_fakes.hardware_name,
|
|
81
|
-
hardware_fakes.hardware_project_id,
|
|
82
|
-
{},
|
|
83
|
-
hardware_fakes.hardware_updated_at,
|
|
84
|
-
hardware_fakes.hardware_uuid,
|
|
85
|
-
[],
|
|
86
|
-
)
|
|
87
|
-
self.assertEqual(datalist, tuple(data))
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
class TestHardwareList(TestHardware):
|
|
91
|
-
def setUp(self):
|
|
92
|
-
super().setUp()
|
|
93
|
-
|
|
94
|
-
self.hardware_mock.list.return_value = list(
|
|
95
|
-
hardware_fakes.FakeHardware.create_one_hardware()
|
|
96
|
-
)
|
|
97
|
-
|
|
98
|
-
self.cmd = hardware_cli.ListHardware(self.app, None)
|
|
99
|
-
|
|
100
|
-
def test_hardware_list(self):
|
|
101
|
-
arglist = []
|
|
102
|
-
verifylist = []
|
|
103
|
-
|
|
104
|
-
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
|
105
|
-
|
|
106
|
-
# DisplayCommandBase.take_action() returns two tuples
|
|
107
|
-
columns, data = self.cmd.take_action(parsed_args)
|
|
108
|
-
|
|
109
|
-
# Set expected values
|
|
110
|
-
args = []
|
|
111
|
-
|
|
112
|
-
self.hardware_mock.list.assert_called_with(*args)
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
class TestHardwareCreate(TestHardware):
|
|
116
|
-
def setUp(self):
|
|
117
|
-
super().setUp()
|
|
118
|
-
self.cmd = hardware_cli.CreateHardware(self.app, None)
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
class TestHardwareDelete(TestHardware):
|
|
122
|
-
def setUp(self):
|
|
123
|
-
super().setUp()
|
|
124
|
-
self.cmd = hardware_cli.DeleteHardware(self.app, None)
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
class TestHardwareSetMeta(type):
|
|
128
|
-
"""Metaclass to generate list of test cases."""
|
|
129
|
-
|
|
130
|
-
def __new__(mcs, name, bases, dict):
|
|
131
|
-
def gen_test(hw_type, arg, prop, path, value):
|
|
132
|
-
def test(self):
|
|
133
|
-
self.hardware_mock.update.return_value = (
|
|
134
|
-
hardware_fakes.FakeHardware.create_one_hardware()
|
|
135
|
-
)
|
|
136
|
-
arglist = [
|
|
137
|
-
FAKE_HARDWARE_UUID,
|
|
138
|
-
"--hardware_type",
|
|
139
|
-
hw_type,
|
|
140
|
-
arg,
|
|
141
|
-
value,
|
|
142
|
-
]
|
|
143
|
-
parsed_args = self.check_parser(self.cmd, arglist, [])
|
|
144
|
-
assert parsed_args.properties == {prop: value}
|
|
145
|
-
|
|
146
|
-
self.cmd.take_action(parsed_args)
|
|
147
|
-
self.hardware_mock.update.assert_called_with(
|
|
148
|
-
FAKE_HARDWARE_UUID, [{"op": "add", "path": path, "value": value}]
|
|
149
|
-
)
|
|
150
|
-
|
|
151
|
-
return test
|
|
152
|
-
|
|
153
|
-
for hw_type, arg, prop, path, value in UPDATE_PARAMS:
|
|
154
|
-
test_name = "test_device_update_%s" % prop
|
|
155
|
-
dict[test_name] = gen_test(hw_type, arg, prop, path, value)
|
|
156
|
-
return type.__new__(mcs, name, bases, dict)
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
class TestHardwareSet(TestHardware, metaclass=TestHardwareSetMeta):
|
|
160
|
-
def setUp(self):
|
|
161
|
-
super().setUp()
|
|
162
|
-
self.cmd = hardware_cli.UpdateHardware(self.app, None)
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
class TestHardwareSync(TestHardware):
|
|
166
|
-
def setUp(self):
|
|
167
|
-
super().setUp()
|
|
168
|
-
self.cmd = hardware_cli.SyncHardware(self.app, None)
|
|
File without changes
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
[tool.black]
|
|
2
|
-
# Set line length explicitly.
|
|
3
|
-
# See https://black.readthedocs.io/en/stable/the_black_code_style.html#line-length for more details
|
|
4
|
-
line-length = 88
|
|
5
|
-
|
|
6
|
-
[tool.pytest.ini_options]
|
|
7
|
-
log_cli = true
|
|
8
|
-
log_cli_level = "INFO"
|
|
9
|
-
log_cli_format = "%(asctime)s [%(levelname)8s] %(message)s (%(filename)s:%(lineno)s)"
|
|
10
|
-
log_cli_date_format = "%Y-%m-%d %H:%M:%S"
|
|
11
|
-
filterwarnings = ["ignore::DeprecationWarning"]
|
|
12
|
-
|
|
13
|
-
[tool.isort]
|
|
14
|
-
known_first_party = "doniclient"
|
|
15
|
-
|
|
16
|
-
[tool.poetry]
|
|
17
|
-
name = "python-doniclient"
|
|
18
|
-
version = "1.0.3"
|
|
19
|
-
description = "This is a plugin for the openstack commandline client, to enable support for the Doni hardware inventory project"
|
|
20
|
-
license = "Apache-2.0"
|
|
21
|
-
authors = ["Chameleon Cloud <contact@chameleoncloud.org>"]
|
|
22
|
-
readme = "README.md"
|
|
23
|
-
repository = "https://github.com/ChameleonCloud/python-doniclient"
|
|
24
|
-
|
|
25
|
-
classifiers = [
|
|
26
|
-
"Environment :: OpenStack",
|
|
27
|
-
"Intended Audience :: Information Technology",
|
|
28
|
-
"Intended Audience :: System Administrators",
|
|
29
|
-
"Operating System :: POSIX :: Linux",
|
|
30
|
-
]
|
|
31
|
-
|
|
32
|
-
packages = [{ include = "doniclient" }]
|
|
33
|
-
|
|
34
|
-
[tool.poetry.dependencies]
|
|
35
|
-
python = "^3.7"
|
|
36
|
-
osc-lib = "<=2.4.2"
|
|
37
|
-
python-openstackclient = { version = "<=5.6.0", extras = ["cli"] }
|
|
38
|
-
python-dateutil = "<=2.8.2"
|
|
39
|
-
PyYAML = "<=5.4.1"
|
|
40
|
-
keystoneauth1 = "<=4.4.0"
|
|
41
|
-
|
|
42
|
-
[tool.poetry.dev-dependencies]
|
|
43
|
-
pytest = "^6.2"
|
|
44
|
-
black = "^22.10"
|
|
45
|
-
flake8 = "^3.9.0"
|
|
46
|
-
flake8-bugbear = "^21.4.1"
|
|
47
|
-
pytest-mock = "^3.5.1"
|
|
48
|
-
isort = "^5.8.0"
|
|
49
|
-
pydocstyle = "^6.0.0"
|
|
50
|
-
oslotest = "^4.4.1"
|
|
51
|
-
stestr = "^3.2.1"
|
|
52
|
-
|
|
53
|
-
[build-system]
|
|
54
|
-
requires = ["poetry-core>=1.0.0"]
|
|
55
|
-
build-backend = "poetry.core.masonry.api"
|
|
56
|
-
|
|
57
|
-
[tool.poetry.plugins."openstack.cli.extension"]
|
|
58
|
-
inventory = "doniclient.osc.plugin"
|
|
59
|
-
|
|
60
|
-
[tool.poetry.plugins."openstack.inventory.v1"]
|
|
61
|
-
hardware_list = "doniclient.osc.cli:ListHardware"
|
|
62
|
-
hardware_import = "doniclient.osc.cli:ImportHardware"
|
|
63
|
-
hardware_show = "doniclient.osc.cli:GetHardware"
|
|
64
|
-
hardware_create = "doniclient.osc.cli:CreateHardware"
|
|
65
|
-
hardware_set = "doniclient.osc.cli:UpdateHardware"
|
|
66
|
-
hardware_delete = "doniclient.osc.cli:DeleteHardware"
|
|
67
|
-
hardware_sync = "doniclient.osc.cli:SyncHardware"
|
|
68
|
-
hardware_availability_list = "doniclient.osc.availability:ListHardwareAvailability"
|
|
69
|
-
hardware_availability_set = "doniclient.osc.availability:UpdateHardwareAvailability"
|
|
70
|
-
hardware_availability_add = "doniclient.osc.availability:AddHardwareAvailability"
|
|
71
|
-
hardware_availability_remove = "doniclient.osc.availability:RemoveHardwareAvailability"
|
python-doniclient-1.0.3/setup.py
DELETED
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
|
-
from setuptools import setup
|
|
3
|
-
|
|
4
|
-
packages = \
|
|
5
|
-
['doniclient',
|
|
6
|
-
'doniclient.osc',
|
|
7
|
-
'doniclient.tests',
|
|
8
|
-
'doniclient.tests.osc',
|
|
9
|
-
'doniclient.tests.v1',
|
|
10
|
-
'doniclient.v1']
|
|
11
|
-
|
|
12
|
-
package_data = \
|
|
13
|
-
{'': ['*']}
|
|
14
|
-
|
|
15
|
-
install_requires = \
|
|
16
|
-
['PyYAML<=5.4.1',
|
|
17
|
-
'keystoneauth1<=4.4.0',
|
|
18
|
-
'osc-lib<=2.4.2',
|
|
19
|
-
'python-dateutil<=2.8.2',
|
|
20
|
-
'python-openstackclient[cli]<=5.6.0']
|
|
21
|
-
|
|
22
|
-
entry_points = \
|
|
23
|
-
{'openstack.cli.extension': ['inventory = doniclient.osc.plugin'],
|
|
24
|
-
'openstack.inventory.v1': ['hardware_availability_add = '
|
|
25
|
-
'doniclient.osc.availability:AddHardwareAvailability',
|
|
26
|
-
'hardware_availability_list = '
|
|
27
|
-
'doniclient.osc.availability:ListHardwareAvailability',
|
|
28
|
-
'hardware_availability_remove = '
|
|
29
|
-
'doniclient.osc.availability:RemoveHardwareAvailability',
|
|
30
|
-
'hardware_availability_set = '
|
|
31
|
-
'doniclient.osc.availability:UpdateHardwareAvailability',
|
|
32
|
-
'hardware_create = '
|
|
33
|
-
'doniclient.osc.cli:CreateHardware',
|
|
34
|
-
'hardware_delete = '
|
|
35
|
-
'doniclient.osc.cli:DeleteHardware',
|
|
36
|
-
'hardware_import = '
|
|
37
|
-
'doniclient.osc.cli:ImportHardware',
|
|
38
|
-
'hardware_list = doniclient.osc.cli:ListHardware',
|
|
39
|
-
'hardware_set = doniclient.osc.cli:UpdateHardware',
|
|
40
|
-
'hardware_show = doniclient.osc.cli:GetHardware',
|
|
41
|
-
'hardware_sync = doniclient.osc.cli:SyncHardware']}
|
|
42
|
-
|
|
43
|
-
setup_kwargs = {
|
|
44
|
-
'name': 'python-doniclient',
|
|
45
|
-
'version': '1.0.3',
|
|
46
|
-
'description': 'This is a plugin for the openstack commandline client, to enable support for the Doni hardware inventory project',
|
|
47
|
-
'long_description': '# python-doniclient\n\nClient for Chameleon Registration Service\n\n\n',
|
|
48
|
-
'author': 'Chameleon Cloud',
|
|
49
|
-
'author_email': 'contact@chameleoncloud.org',
|
|
50
|
-
'maintainer': None,
|
|
51
|
-
'maintainer_email': None,
|
|
52
|
-
'url': 'https://github.com/ChameleonCloud/python-doniclient',
|
|
53
|
-
'packages': packages,
|
|
54
|
-
'package_data': package_data,
|
|
55
|
-
'install_requires': install_requires,
|
|
56
|
-
'entry_points': entry_points,
|
|
57
|
-
'python_requires': '>=3.7,<4.0',
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
setup(**setup_kwargs)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|