Compare commits
3 Commits
3ed60ac1c1
...
bcabfa9d70
| Author | SHA1 | Date | |
|---|---|---|---|
| bcabfa9d70 | |||
| 2dc2055cfa | |||
| 5bd2bd468a |
4
.flake8
4
.flake8
@@ -3,7 +3,9 @@
|
|||||||
# * W503 (line break before binary operator): Black moves these to new lines
|
# * W503 (line break before binary operator): Black moves these to new lines
|
||||||
# * E501 (line too long): Long lines are a fact of life in comment blocks; Black handles active instances of this
|
# * E501 (line too long): Long lines are a fact of life in comment blocks; Black handles active instances of this
|
||||||
# * E203 (whitespace before ':'): Black recommends this as disabled
|
# * E203 (whitespace before ':'): Black recommends this as disabled
|
||||||
ignore = W503, E501
|
# * F403 (import * used; unable to detect undefined names): We use a wildcard for helpers
|
||||||
|
# * F405 (possibly undefined name): We use a wildcard for helpers
|
||||||
|
ignore = W503, E501, F403, F405
|
||||||
extend-ignore = E203
|
extend-ignore = E203
|
||||||
# We exclude the Debian, migrations, and provisioner examples
|
# We exclude the Debian, migrations, and provisioner examples
|
||||||
exclude = debian,api-daemon/migrations/versions,api-daemon/provisioner/examples,node-daemon/monitoring
|
exclude = debian,api-daemon/migrations/versions,api-daemon/provisioner/examples,node-daemon/monitoring
|
||||||
|
|||||||
@@ -1,116 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
|
|
||||||
# cluster.py - PVC CLI client function library, cluster management
|
|
||||||
# Part of the Parallel Virtual Cluster (PVC) system
|
|
||||||
#
|
|
||||||
# Copyright (C) 2018-2022 Joshua M. Boniface <joshua@boniface.me>
|
|
||||||
#
|
|
||||||
# This program is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU General Public License as published by
|
|
||||||
# the Free Software Foundation, version 3.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
#
|
|
||||||
###############################################################################
|
|
||||||
|
|
||||||
import json
|
|
||||||
|
|
||||||
from pvc.lib.common import call_api
|
|
||||||
|
|
||||||
|
|
||||||
def initialize(config, overwrite=False):
|
|
||||||
"""
|
|
||||||
Initialize the PVC cluster
|
|
||||||
|
|
||||||
API endpoint: GET /api/v1/initialize
|
|
||||||
API arguments: overwrite, yes-i-really-mean-it
|
|
||||||
API schema: {json_data_object}
|
|
||||||
"""
|
|
||||||
params = {"yes-i-really-mean-it": "yes", "overwrite": overwrite}
|
|
||||||
response = call_api(config, "post", "/initialize", params=params)
|
|
||||||
|
|
||||||
if response.status_code == 200:
|
|
||||||
retstatus = True
|
|
||||||
else:
|
|
||||||
retstatus = False
|
|
||||||
|
|
||||||
return retstatus, response.json().get("message", "")
|
|
||||||
|
|
||||||
|
|
||||||
def backup(config):
|
|
||||||
"""
|
|
||||||
Get a JSON backup of the cluster
|
|
||||||
|
|
||||||
API endpoint: GET /api/v1/backup
|
|
||||||
API arguments:
|
|
||||||
API schema: {json_data_object}
|
|
||||||
"""
|
|
||||||
response = call_api(config, "get", "/backup")
|
|
||||||
|
|
||||||
if response.status_code == 200:
|
|
||||||
return True, response.json()
|
|
||||||
else:
|
|
||||||
return False, response.json().get("message", "")
|
|
||||||
|
|
||||||
|
|
||||||
def restore(config, cluster_data):
|
|
||||||
"""
|
|
||||||
Restore a JSON backup to the cluster
|
|
||||||
|
|
||||||
API endpoint: POST /api/v1/restore
|
|
||||||
API arguments: yes-i-really-mean-it
|
|
||||||
API schema: {json_data_object}
|
|
||||||
"""
|
|
||||||
cluster_data_json = json.dumps(cluster_data)
|
|
||||||
|
|
||||||
params = {"yes-i-really-mean-it": "yes"}
|
|
||||||
data = {"cluster_data": cluster_data_json}
|
|
||||||
response = call_api(config, "post", "/restore", params=params, data=data)
|
|
||||||
|
|
||||||
if response.status_code == 200:
|
|
||||||
retstatus = True
|
|
||||||
else:
|
|
||||||
retstatus = False
|
|
||||||
|
|
||||||
return retstatus, response.json().get("message", "")
|
|
||||||
|
|
||||||
|
|
||||||
def maintenance_mode(config, state):
|
|
||||||
"""
|
|
||||||
Enable or disable PVC cluster maintenance mode
|
|
||||||
|
|
||||||
API endpoint: POST /api/v1/status
|
|
||||||
API arguments: {state}={state}
|
|
||||||
API schema: {json_data_object}
|
|
||||||
"""
|
|
||||||
params = {"state": state}
|
|
||||||
response = call_api(config, "post", "/status", params=params)
|
|
||||||
|
|
||||||
if response.status_code == 200:
|
|
||||||
retstatus = True
|
|
||||||
else:
|
|
||||||
retstatus = False
|
|
||||||
|
|
||||||
return retstatus, response.json().get("message", "")
|
|
||||||
|
|
||||||
|
|
||||||
def get_info(config):
|
|
||||||
"""
|
|
||||||
Get status of the PVC cluster
|
|
||||||
|
|
||||||
API endpoint: GET /api/v1/status
|
|
||||||
API arguments:
|
|
||||||
API schema: {json_data_object}
|
|
||||||
"""
|
|
||||||
response = call_api(config, "get", "/status")
|
|
||||||
|
|
||||||
if response.status_code == 200:
|
|
||||||
return True, response.json()
|
|
||||||
else:
|
|
||||||
return False, response.json().get("message", "")
|
|
||||||
33
client-cli-old/pvc.py
Executable file
33
client-cli-old/pvc.py
Executable file
@@ -0,0 +1,33 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
# pvc.py - PVC client command-line interface (stub testing interface)
|
||||||
|
# Part of the Parallel Virtual Cluster (PVC) system
|
||||||
|
#
|
||||||
|
# Copyright (C) 2018-2022 Joshua M. Boniface <joshua@boniface.me>
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, version 3.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
import pvc.pvc
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Main entry point
|
||||||
|
#
|
||||||
|
def main():
|
||||||
|
return pvc.pvc.cli(obj={})
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
@@ -27,8 +27,8 @@ from requests_toolbelt.multipart.encoder import (
|
|||||||
MultipartEncoderMonitor,
|
MultipartEncoderMonitor,
|
||||||
)
|
)
|
||||||
|
|
||||||
import pvc.cli_lib.ansiprint as ansiprint
|
import pvc.lib.ansiprint as ansiprint
|
||||||
from pvc.cli_lib.common import UploadProgressBar, call_api
|
from pvc.lib.common import UploadProgressBar, call_api
|
||||||
|
|
||||||
#
|
#
|
||||||
# Supplemental functions
|
# Supplemental functions
|
||||||
313
client-cli-old/pvc/lib/cluster.py
Normal file
313
client-cli-old/pvc/lib/cluster.py
Normal file
@@ -0,0 +1,313 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
# cluster.py - PVC CLI client function library, cluster management
|
||||||
|
# Part of the Parallel Virtual Cluster (PVC) system
|
||||||
|
#
|
||||||
|
# Copyright (C) 2018-2022 Joshua M. Boniface <joshua@boniface.me>
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, version 3.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
import json
|
||||||
|
|
||||||
|
import pvc.lib.ansiprint as ansiprint
|
||||||
|
from pvc.lib.common import call_api
|
||||||
|
|
||||||
|
|
||||||
|
def initialize(config, overwrite=False):
|
||||||
|
"""
|
||||||
|
Initialize the PVC cluster
|
||||||
|
|
||||||
|
API endpoint: GET /api/v1/initialize
|
||||||
|
API arguments: overwrite, yes-i-really-mean-it
|
||||||
|
API schema: {json_data_object}
|
||||||
|
"""
|
||||||
|
params = {"yes-i-really-mean-it": "yes", "overwrite": overwrite}
|
||||||
|
response = call_api(config, "post", "/initialize", params=params)
|
||||||
|
|
||||||
|
if response.status_code == 200:
|
||||||
|
retstatus = True
|
||||||
|
else:
|
||||||
|
retstatus = False
|
||||||
|
|
||||||
|
return retstatus, response.json().get("message", "")
|
||||||
|
|
||||||
|
|
||||||
|
def backup(config):
|
||||||
|
"""
|
||||||
|
Get a JSON backup of the cluster
|
||||||
|
|
||||||
|
API endpoint: GET /api/v1/backup
|
||||||
|
API arguments:
|
||||||
|
API schema: {json_data_object}
|
||||||
|
"""
|
||||||
|
response = call_api(config, "get", "/backup")
|
||||||
|
|
||||||
|
if response.status_code == 200:
|
||||||
|
return True, response.json()
|
||||||
|
else:
|
||||||
|
return False, response.json().get("message", "")
|
||||||
|
|
||||||
|
|
||||||
|
def restore(config, cluster_data):
|
||||||
|
"""
|
||||||
|
Restore a JSON backup to the cluster
|
||||||
|
|
||||||
|
API endpoint: POST /api/v1/restore
|
||||||
|
API arguments: yes-i-really-mean-it
|
||||||
|
API schema: {json_data_object}
|
||||||
|
"""
|
||||||
|
cluster_data_json = json.dumps(cluster_data)
|
||||||
|
|
||||||
|
params = {"yes-i-really-mean-it": "yes"}
|
||||||
|
data = {"cluster_data": cluster_data_json}
|
||||||
|
response = call_api(config, "post", "/restore", params=params, data=data)
|
||||||
|
|
||||||
|
if response.status_code == 200:
|
||||||
|
retstatus = True
|
||||||
|
else:
|
||||||
|
retstatus = False
|
||||||
|
|
||||||
|
return retstatus, response.json().get("message", "")
|
||||||
|
|
||||||
|
|
||||||
|
def maintenance_mode(config, state):
|
||||||
|
"""
|
||||||
|
Enable or disable PVC cluster maintenance mode
|
||||||
|
|
||||||
|
API endpoint: POST /api/v1/status
|
||||||
|
API arguments: {state}={state}
|
||||||
|
API schema: {json_data_object}
|
||||||
|
"""
|
||||||
|
params = {"state": state}
|
||||||
|
response = call_api(config, "post", "/status", params=params)
|
||||||
|
|
||||||
|
if response.status_code == 200:
|
||||||
|
retstatus = True
|
||||||
|
else:
|
||||||
|
retstatus = False
|
||||||
|
|
||||||
|
return retstatus, response.json().get("message", "")
|
||||||
|
|
||||||
|
|
||||||
|
def get_info(config):
|
||||||
|
"""
|
||||||
|
Get status of the PVC cluster
|
||||||
|
|
||||||
|
API endpoint: GET /api/v1/status
|
||||||
|
API arguments:
|
||||||
|
API schema: {json_data_object}
|
||||||
|
"""
|
||||||
|
response = call_api(config, "get", "/status")
|
||||||
|
|
||||||
|
if response.status_code == 200:
|
||||||
|
return True, response.json()
|
||||||
|
else:
|
||||||
|
return False, response.json().get("message", "")
|
||||||
|
|
||||||
|
|
||||||
|
def format_info(cluster_information, oformat):
|
||||||
|
if oformat == "json":
|
||||||
|
return json.dumps(cluster_information)
|
||||||
|
|
||||||
|
if oformat == "json-pretty":
|
||||||
|
return json.dumps(cluster_information, indent=4)
|
||||||
|
|
||||||
|
# Plain formatting, i.e. human-readable
|
||||||
|
if (
|
||||||
|
cluster_information.get("maintenance") == "true"
|
||||||
|
or cluster_information.get("cluster_health", {}).get("health", "N/A") == "N/A"
|
||||||
|
):
|
||||||
|
health_colour = ansiprint.blue()
|
||||||
|
elif cluster_information.get("cluster_health", {}).get("health", 100) > 90:
|
||||||
|
health_colour = ansiprint.green()
|
||||||
|
elif cluster_information.get("cluster_health", {}).get("health", 100) > 50:
|
||||||
|
health_colour = ansiprint.yellow()
|
||||||
|
else:
|
||||||
|
health_colour = ansiprint.red()
|
||||||
|
|
||||||
|
ainformation = []
|
||||||
|
|
||||||
|
ainformation.append(
|
||||||
|
"{}PVC cluster status:{}".format(ansiprint.bold(), ansiprint.end())
|
||||||
|
)
|
||||||
|
ainformation.append("")
|
||||||
|
|
||||||
|
health_text = (
|
||||||
|
f"{cluster_information.get('cluster_health', {}).get('health', 'N/A')}"
|
||||||
|
)
|
||||||
|
if health_text != "N/A":
|
||||||
|
health_text += "%"
|
||||||
|
if cluster_information.get("maintenance") == "true":
|
||||||
|
health_text += " (maintenance on)"
|
||||||
|
|
||||||
|
ainformation.append(
|
||||||
|
"{}Cluster health:{} {}{}{}".format(
|
||||||
|
ansiprint.purple(),
|
||||||
|
ansiprint.end(),
|
||||||
|
health_colour,
|
||||||
|
health_text,
|
||||||
|
ansiprint.end(),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
if cluster_information.get("cluster_health", {}).get("messages"):
|
||||||
|
health_messages = "\n > ".join(
|
||||||
|
sorted(cluster_information["cluster_health"]["messages"])
|
||||||
|
)
|
||||||
|
ainformation.append(
|
||||||
|
"{}Health messages:{} > {}".format(
|
||||||
|
ansiprint.purple(),
|
||||||
|
ansiprint.end(),
|
||||||
|
health_messages,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
ainformation.append(
|
||||||
|
"{}Health messages:{} N/A".format(
|
||||||
|
ansiprint.purple(),
|
||||||
|
ansiprint.end(),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
if oformat == "short":
|
||||||
|
return "\n".join(ainformation)
|
||||||
|
|
||||||
|
ainformation.append("")
|
||||||
|
ainformation.append(
|
||||||
|
"{}Primary node:{} {}".format(
|
||||||
|
ansiprint.purple(), ansiprint.end(), cluster_information["primary_node"]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
ainformation.append(
|
||||||
|
"{}PVC version:{} {}".format(
|
||||||
|
ansiprint.purple(),
|
||||||
|
ansiprint.end(),
|
||||||
|
cluster_information.get("pvc_version", "N/A"),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
ainformation.append(
|
||||||
|
"{}Cluster upstream IP:{} {}".format(
|
||||||
|
ansiprint.purple(), ansiprint.end(), cluster_information["upstream_ip"]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
ainformation.append("")
|
||||||
|
ainformation.append(
|
||||||
|
"{}Total nodes:{} {}".format(
|
||||||
|
ansiprint.purple(), ansiprint.end(), cluster_information["nodes"]["total"]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
ainformation.append(
|
||||||
|
"{}Total VMs:{} {}".format(
|
||||||
|
ansiprint.purple(), ansiprint.end(), cluster_information["vms"]["total"]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
ainformation.append(
|
||||||
|
"{}Total networks:{} {}".format(
|
||||||
|
ansiprint.purple(), ansiprint.end(), cluster_information["networks"]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
ainformation.append(
|
||||||
|
"{}Total OSDs:{} {}".format(
|
||||||
|
ansiprint.purple(), ansiprint.end(), cluster_information["osds"]["total"]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
ainformation.append(
|
||||||
|
"{}Total pools:{} {}".format(
|
||||||
|
ansiprint.purple(), ansiprint.end(), cluster_information["pools"]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
ainformation.append(
|
||||||
|
"{}Total volumes:{} {}".format(
|
||||||
|
ansiprint.purple(), ansiprint.end(), cluster_information["volumes"]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
ainformation.append(
|
||||||
|
"{}Total snapshots:{} {}".format(
|
||||||
|
ansiprint.purple(), ansiprint.end(), cluster_information["snapshots"]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
nodes_string = "{}Nodes:{} {}/{} {}ready,run{}".format(
|
||||||
|
ansiprint.purple(),
|
||||||
|
ansiprint.end(),
|
||||||
|
cluster_information["nodes"].get("run,ready", 0),
|
||||||
|
cluster_information["nodes"].get("total", 0),
|
||||||
|
ansiprint.green(),
|
||||||
|
ansiprint.end(),
|
||||||
|
)
|
||||||
|
for state, count in cluster_information["nodes"].items():
|
||||||
|
if state == "total" or state == "run,ready":
|
||||||
|
continue
|
||||||
|
|
||||||
|
nodes_string += " {}/{} {}{}{}".format(
|
||||||
|
count,
|
||||||
|
cluster_information["nodes"]["total"],
|
||||||
|
ansiprint.yellow(),
|
||||||
|
state,
|
||||||
|
ansiprint.end(),
|
||||||
|
)
|
||||||
|
|
||||||
|
ainformation.append("")
|
||||||
|
ainformation.append(nodes_string)
|
||||||
|
|
||||||
|
vms_string = "{}VMs:{} {}/{} {}start{}".format(
|
||||||
|
ansiprint.purple(),
|
||||||
|
ansiprint.end(),
|
||||||
|
cluster_information["vms"].get("start", 0),
|
||||||
|
cluster_information["vms"].get("total", 0),
|
||||||
|
ansiprint.green(),
|
||||||
|
ansiprint.end(),
|
||||||
|
)
|
||||||
|
for state, count in cluster_information["vms"].items():
|
||||||
|
if state == "total" or state == "start":
|
||||||
|
continue
|
||||||
|
|
||||||
|
if state in ["disable", "migrate", "unmigrate", "provision"]:
|
||||||
|
colour = ansiprint.blue()
|
||||||
|
else:
|
||||||
|
colour = ansiprint.yellow()
|
||||||
|
|
||||||
|
vms_string += " {}/{} {}{}{}".format(
|
||||||
|
count, cluster_information["vms"]["total"], colour, state, ansiprint.end()
|
||||||
|
)
|
||||||
|
|
||||||
|
ainformation.append("")
|
||||||
|
ainformation.append(vms_string)
|
||||||
|
|
||||||
|
if cluster_information["osds"]["total"] > 0:
|
||||||
|
osds_string = "{}Ceph OSDs:{} {}/{} {}up,in{}".format(
|
||||||
|
ansiprint.purple(),
|
||||||
|
ansiprint.end(),
|
||||||
|
cluster_information["osds"].get("up,in", 0),
|
||||||
|
cluster_information["osds"].get("total", 0),
|
||||||
|
ansiprint.green(),
|
||||||
|
ansiprint.end(),
|
||||||
|
)
|
||||||
|
for state, count in cluster_information["osds"].items():
|
||||||
|
if state == "total" or state == "up,in":
|
||||||
|
continue
|
||||||
|
|
||||||
|
osds_string += " {}/{} {}{}{}".format(
|
||||||
|
count,
|
||||||
|
cluster_information["osds"]["total"],
|
||||||
|
ansiprint.yellow(),
|
||||||
|
state,
|
||||||
|
ansiprint.end(),
|
||||||
|
)
|
||||||
|
|
||||||
|
ainformation.append("")
|
||||||
|
ainformation.append(osds_string)
|
||||||
|
|
||||||
|
ainformation.append("")
|
||||||
|
return "\n".join(ainformation)
|
||||||
@@ -542,16 +542,11 @@ def net_sriov_vf_info(config, node, vf):
|
|||||||
return False, "VF not found."
|
return False, "VF not found."
|
||||||
else:
|
else:
|
||||||
# Return a single instance if the response is a list
|
# Return a single instance if the response is a list
|
||||||
data = dict()
|
|
||||||
data["node"] = node
|
|
||||||
if isinstance(response.json(), list):
|
if isinstance(response.json(), list):
|
||||||
data = dict()
|
return True, response.json()[0]
|
||||||
data["vf_information"] = response.json()[0]
|
|
||||||
return True, data
|
|
||||||
# This shouldn't happen, but is here just in case
|
# This shouldn't happen, but is here just in case
|
||||||
else:
|
else:
|
||||||
data["vf_information"] = response.json()
|
return True, response.json()
|
||||||
return True, data
|
|
||||||
else:
|
else:
|
||||||
return False, response.json().get("message", "")
|
return False, response.json().get("message", "")
|
||||||
|
|
||||||
@@ -719,7 +714,7 @@ def format_info(config, network_information, long_output):
|
|||||||
)
|
)
|
||||||
ainformation.append("")
|
ainformation.append("")
|
||||||
if retcode:
|
if retcode:
|
||||||
firewall_rules_string = format_list_acl(config, firewall_rules_list)
|
firewall_rules_string = format_list_acl(firewall_rules_list)
|
||||||
for line in firewall_rules_string.split("\n"):
|
for line in firewall_rules_string.split("\n"):
|
||||||
ainformation.append(line)
|
ainformation.append(line)
|
||||||
else:
|
else:
|
||||||
@@ -893,7 +888,7 @@ def format_list(config, network_list):
|
|||||||
return "\n".join(network_list_output)
|
return "\n".join(network_list_output)
|
||||||
|
|
||||||
|
|
||||||
def format_list_dhcp(config, dhcp_lease_list):
|
def format_list_dhcp(dhcp_lease_list):
|
||||||
dhcp_lease_list_output = []
|
dhcp_lease_list_output = []
|
||||||
|
|
||||||
# Determine optimal column widths
|
# Determine optimal column widths
|
||||||
@@ -992,7 +987,7 @@ def format_list_dhcp(config, dhcp_lease_list):
|
|||||||
return "\n".join(dhcp_lease_list_output)
|
return "\n".join(dhcp_lease_list_output)
|
||||||
|
|
||||||
|
|
||||||
def format_list_acl(config, acl_list):
|
def format_list_acl(acl_list):
|
||||||
# Handle when we get an empty entry
|
# Handle when we get an empty entry
|
||||||
if not acl_list:
|
if not acl_list:
|
||||||
acl_list = list()
|
acl_list = list()
|
||||||
@@ -1091,7 +1086,7 @@ def format_list_acl(config, acl_list):
|
|||||||
return "\n".join(acl_list_output)
|
return "\n".join(acl_list_output)
|
||||||
|
|
||||||
|
|
||||||
def format_list_sriov_pf(config, pf_list):
|
def format_list_sriov_pf(pf_list):
|
||||||
# The maximum column width of the VFs column
|
# The maximum column width of the VFs column
|
||||||
max_vfs_length = 70
|
max_vfs_length = 70
|
||||||
|
|
||||||
@@ -1211,7 +1206,7 @@ def format_list_sriov_pf(config, pf_list):
|
|||||||
return "\n".join(pf_list_output)
|
return "\n".join(pf_list_output)
|
||||||
|
|
||||||
|
|
||||||
def format_list_sriov_vf(config, vf_list):
|
def format_list_sriov_vf(vf_list):
|
||||||
# Handle when we get an empty entry
|
# Handle when we get an empty entry
|
||||||
if not vf_list:
|
if not vf_list:
|
||||||
vf_list = list()
|
vf_list = list()
|
||||||
@@ -1343,13 +1338,10 @@ def format_list_sriov_vf(config, vf_list):
|
|||||||
return "\n".join(vf_list_output)
|
return "\n".join(vf_list_output)
|
||||||
|
|
||||||
|
|
||||||
def format_info_sriov_vf(config, data):
|
def format_info_sriov_vf(config, vf_information, node):
|
||||||
if not data or not data["vf_information"]:
|
if not vf_information:
|
||||||
return "No VF found"
|
return "No VF found"
|
||||||
|
|
||||||
node = data["node"]
|
|
||||||
vf_information = data["vf_information"]
|
|
||||||
|
|
||||||
# Get information on the using VM if applicable
|
# Get information on the using VM if applicable
|
||||||
if vf_information["usage"]["used"] == "True" and vf_information["usage"]["domain"]:
|
if vf_information["usage"]["used"] == "True" and vf_information["usage"]["domain"]:
|
||||||
vm_information = call_api(
|
vm_information = call_api(
|
||||||
@@ -52,7 +52,7 @@ def node_coordinator_state(config, node, action):
|
|||||||
return retstatus, response.json().get("message", "")
|
return retstatus, response.json().get("message", "")
|
||||||
|
|
||||||
|
|
||||||
def node_domain_state(config, node, action):
|
def node_domain_state(config, node, action, wait):
|
||||||
"""
|
"""
|
||||||
Set node domain state state (flush/ready)
|
Set node domain state state (flush/ready)
|
||||||
|
|
||||||
@@ -60,7 +60,7 @@ def node_domain_state(config, node, action):
|
|||||||
API arguments: action={action}, wait={wait}
|
API arguments: action={action}, wait={wait}
|
||||||
API schema: {"message": "{data}"}
|
API schema: {"message": "{data}"}
|
||||||
"""
|
"""
|
||||||
params = {"state": action}
|
params = {"state": action, "wait": str(wait).lower()}
|
||||||
response = call_api(
|
response = call_api(
|
||||||
config, "post", "/node/{node}/domain-state".format(node=node), params=params
|
config, "post", "/node/{node}/domain-state".format(node=node), params=params
|
||||||
)
|
)
|
||||||
@@ -273,7 +273,7 @@ def getOutputColours(node_information):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def format_info(config, node_information, long_output):
|
def format_info(node_information, long_output):
|
||||||
(
|
(
|
||||||
health_colour,
|
health_colour,
|
||||||
daemon_state_colour,
|
daemon_state_colour,
|
||||||
@@ -442,9 +442,12 @@ def format_info(config, node_information, long_output):
|
|||||||
return "\n".join(ainformation)
|
return "\n".join(ainformation)
|
||||||
|
|
||||||
|
|
||||||
def format_list(config, node_list):
|
def format_list(node_list, raw):
|
||||||
if node_list == "Node not found.":
|
if raw:
|
||||||
return node_list
|
ainformation = list()
|
||||||
|
for node in sorted(item["name"] for item in node_list):
|
||||||
|
ainformation.append(node)
|
||||||
|
return "\n".join(ainformation)
|
||||||
|
|
||||||
node_list_output = []
|
node_list_output = []
|
||||||
|
|
||||||
@@ -750,11 +750,24 @@ def task_status(config, task_id=None, is_watching=False):
|
|||||||
if response.status_code == 200:
|
if response.status_code == 200:
|
||||||
retvalue = True
|
retvalue = True
|
||||||
respjson = response.json()
|
respjson = response.json()
|
||||||
|
|
||||||
if is_watching:
|
if is_watching:
|
||||||
# Just return the raw JSON to the watching process instead of including value
|
# Just return the raw JSON to the watching process instead of formatting it
|
||||||
return respjson
|
return respjson
|
||||||
|
|
||||||
|
job_state = respjson["state"]
|
||||||
|
if job_state == "RUNNING":
|
||||||
|
retdata = "Job state: RUNNING\nStage: {}/{}\nStatus: {}".format(
|
||||||
|
respjson["current"], respjson["total"], respjson["status"]
|
||||||
|
)
|
||||||
|
elif job_state == "FAILED":
|
||||||
|
retdata = "Job state: FAILED\nStatus: {}".format(respjson["status"])
|
||||||
|
elif job_state == "COMPLETED":
|
||||||
|
retdata = "Job state: COMPLETED\nStatus: {}".format(respjson["status"])
|
||||||
else:
|
else:
|
||||||
return retvalue, respjson
|
retdata = "Job state: {}\nStatus: {}".format(
|
||||||
|
respjson["state"], respjson["status"]
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
retvalue = False
|
retvalue = False
|
||||||
retdata = response.json().get("message", "")
|
retdata = response.json().get("message", "")
|
||||||
@@ -801,7 +814,7 @@ def task_status(config, task_id=None, is_watching=False):
|
|||||||
#
|
#
|
||||||
# Format functions
|
# Format functions
|
||||||
#
|
#
|
||||||
def format_list_template(config, template_data, template_type=None):
|
def format_list_template(template_data, template_type=None):
|
||||||
"""
|
"""
|
||||||
Format the returned template template
|
Format the returned template template
|
||||||
|
|
||||||
@@ -1317,12 +1330,7 @@ def format_list_template_storage(template_template):
|
|||||||
return "\n".join(template_list_output)
|
return "\n".join(template_list_output)
|
||||||
|
|
||||||
|
|
||||||
def format_list_userdata(config, userdata_data):
|
def format_list_userdata(userdata_data, lines=None):
|
||||||
if not config.get("long_output"):
|
|
||||||
lines = 4
|
|
||||||
else:
|
|
||||||
lines = None
|
|
||||||
|
|
||||||
if isinstance(userdata_data, dict):
|
if isinstance(userdata_data, dict):
|
||||||
userdata_data = [userdata_data]
|
userdata_data = [userdata_data]
|
||||||
|
|
||||||
@@ -1424,12 +1432,7 @@ def format_list_userdata(config, userdata_data):
|
|||||||
return "\n".join(userdata_list_output)
|
return "\n".join(userdata_list_output)
|
||||||
|
|
||||||
|
|
||||||
def format_list_script(config, script_data):
|
def format_list_script(script_data, lines=None):
|
||||||
if not config.get("long_output"):
|
|
||||||
lines = 4
|
|
||||||
else:
|
|
||||||
lines = None
|
|
||||||
|
|
||||||
if isinstance(script_data, dict):
|
if isinstance(script_data, dict):
|
||||||
script_data = [script_data]
|
script_data = [script_data]
|
||||||
|
|
||||||
@@ -1528,7 +1531,7 @@ def format_list_script(config, script_data):
|
|||||||
return "\n".join(script_list_output)
|
return "\n".join(script_list_output)
|
||||||
|
|
||||||
|
|
||||||
def format_list_ova(config, ova_data):
|
def format_list_ova(ova_data):
|
||||||
if isinstance(ova_data, dict):
|
if isinstance(ova_data, dict):
|
||||||
ova_data = [ova_data]
|
ova_data = [ova_data]
|
||||||
|
|
||||||
@@ -1675,7 +1678,7 @@ def format_list_ova(config, ova_data):
|
|||||||
return "\n".join(ova_list_output)
|
return "\n".join(ova_list_output)
|
||||||
|
|
||||||
|
|
||||||
def format_list_profile(config, profile_data):
|
def format_list_profile(profile_data):
|
||||||
if isinstance(profile_data, dict):
|
if isinstance(profile_data, dict):
|
||||||
profile_data = [profile_data]
|
profile_data = [profile_data]
|
||||||
|
|
||||||
@@ -1864,23 +1867,7 @@ def format_list_profile(config, profile_data):
|
|||||||
return "\n".join(profile_list_output)
|
return "\n".join(profile_list_output)
|
||||||
|
|
||||||
|
|
||||||
def format_list_task(config, task_data):
|
def format_list_task(task_data):
|
||||||
if not isinstance(task_data, list):
|
|
||||||
job_state = task_data["state"]
|
|
||||||
if job_state == "RUNNING":
|
|
||||||
retdata = "Job state: RUNNING\nStage: {}/{}\nStatus: {}".format(
|
|
||||||
task_data["current"], task_data["total"], task_data["status"]
|
|
||||||
)
|
|
||||||
elif job_state == "FAILED":
|
|
||||||
retdata = "Job state: FAILED\nStatus: {}".format(task_data["status"])
|
|
||||||
elif job_state == "COMPLETED":
|
|
||||||
retdata = "Job state: COMPLETED\nStatus: {}".format(task_data["status"])
|
|
||||||
else:
|
|
||||||
retdata = "Job state: {}\nStatus: {}".format(
|
|
||||||
task_data["state"], task_data["status"]
|
|
||||||
)
|
|
||||||
return retdata
|
|
||||||
|
|
||||||
task_list_output = []
|
task_list_output = []
|
||||||
|
|
||||||
# Determine optimal column widths
|
# Determine optimal column widths
|
||||||
@@ -286,18 +286,20 @@ def vm_tag_set(config, vm, action, tag, protected=False):
|
|||||||
return retstatus, response.json().get("message", "")
|
return retstatus, response.json().get("message", "")
|
||||||
|
|
||||||
|
|
||||||
def format_vm_tags(config, data):
|
def format_vm_tags(config, name, tags):
|
||||||
"""
|
"""
|
||||||
Format the output of a tags dictionary in a nice table
|
Format the output of a tags dictionary in a nice table
|
||||||
"""
|
"""
|
||||||
|
|
||||||
tags = data.get("tags", [])
|
|
||||||
|
|
||||||
if len(tags) < 1:
|
if len(tags) < 1:
|
||||||
return "No tags found."
|
return "No tags found."
|
||||||
|
|
||||||
output_list = []
|
output_list = []
|
||||||
|
|
||||||
|
name_length = 5
|
||||||
|
_name_length = len(name) + 1
|
||||||
|
if _name_length > name_length:
|
||||||
|
name_length = _name_length
|
||||||
|
|
||||||
tags_name_length = 4
|
tags_name_length = 4
|
||||||
tags_type_length = 5
|
tags_type_length = 5
|
||||||
tags_protected_length = 10
|
tags_protected_length = 10
|
||||||
@@ -493,38 +495,44 @@ def vm_vcpus_get(config, vm):
|
|||||||
except Exception:
|
except Exception:
|
||||||
return False, "ERROR: Failed to parse XML data."
|
return False, "ERROR: Failed to parse XML data."
|
||||||
|
|
||||||
data = dict()
|
vm_vcpus = int(parsed_xml.vcpu.text)
|
||||||
data["name"] = vm
|
vm_sockets = parsed_xml.cpu.topology.attrib.get("sockets")
|
||||||
data["vcpus"] = int(parsed_xml.vcpu.text)
|
vm_cores = parsed_xml.cpu.topology.attrib.get("cores")
|
||||||
data["sockets"] = parsed_xml.cpu.topology.attrib.get("sockets")
|
vm_threads = parsed_xml.cpu.topology.attrib.get("threads")
|
||||||
data["cores"] = parsed_xml.cpu.topology.attrib.get("cores")
|
|
||||||
data["threads"] = parsed_xml.cpu.topology.attrib.get("threads")
|
|
||||||
|
|
||||||
return True, data
|
return True, (vm_vcpus, (vm_sockets, vm_cores, vm_threads))
|
||||||
|
|
||||||
|
|
||||||
def format_vm_vcpus(config, data):
|
def format_vm_vcpus(config, name, vcpus):
|
||||||
"""
|
"""
|
||||||
Format the output of a vCPU value in a nice table
|
Format the output of a vCPU value in a nice table
|
||||||
"""
|
"""
|
||||||
output_list = []
|
output_list = []
|
||||||
|
|
||||||
|
name_length = 5
|
||||||
|
_name_length = len(name) + 1
|
||||||
|
if _name_length > name_length:
|
||||||
|
name_length = _name_length
|
||||||
|
|
||||||
vcpus_length = 6
|
vcpus_length = 6
|
||||||
sockets_length = 8
|
sockets_length = 8
|
||||||
cores_length = 6
|
cores_length = 6
|
||||||
threads_length = 8
|
threads_length = 8
|
||||||
|
|
||||||
output_list.append(
|
output_list.append(
|
||||||
"{bold}{vcpus: <{vcpus_length}} \
|
"{bold}{name: <{name_length}} \
|
||||||
|
{vcpus: <{vcpus_length}} \
|
||||||
{sockets: <{sockets_length}} \
|
{sockets: <{sockets_length}} \
|
||||||
{cores: <{cores_length}} \
|
{cores: <{cores_length}} \
|
||||||
{threads: <{threads_length}}{end_bold}".format(
|
{threads: <{threads_length}}{end_bold}".format(
|
||||||
|
name_length=name_length,
|
||||||
vcpus_length=vcpus_length,
|
vcpus_length=vcpus_length,
|
||||||
sockets_length=sockets_length,
|
sockets_length=sockets_length,
|
||||||
cores_length=cores_length,
|
cores_length=cores_length,
|
||||||
threads_length=threads_length,
|
threads_length=threads_length,
|
||||||
bold=ansiprint.bold(),
|
bold=ansiprint.bold(),
|
||||||
end_bold=ansiprint.end(),
|
end_bold=ansiprint.end(),
|
||||||
|
name="Name",
|
||||||
vcpus="vCPUs",
|
vcpus="vCPUs",
|
||||||
sockets="Sockets",
|
sockets="Sockets",
|
||||||
cores="Cores",
|
cores="Cores",
|
||||||
@@ -532,20 +540,23 @@ def format_vm_vcpus(config, data):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
output_list.append(
|
output_list.append(
|
||||||
"{bold}{vcpus: <{vcpus_length}} \
|
"{bold}{name: <{name_length}} \
|
||||||
|
{vcpus: <{vcpus_length}} \
|
||||||
{sockets: <{sockets_length}} \
|
{sockets: <{sockets_length}} \
|
||||||
{cores: <{cores_length}} \
|
{cores: <{cores_length}} \
|
||||||
{threads: <{threads_length}}{end_bold}".format(
|
{threads: <{threads_length}}{end_bold}".format(
|
||||||
|
name_length=name_length,
|
||||||
vcpus_length=vcpus_length,
|
vcpus_length=vcpus_length,
|
||||||
sockets_length=sockets_length,
|
sockets_length=sockets_length,
|
||||||
cores_length=cores_length,
|
cores_length=cores_length,
|
||||||
threads_length=threads_length,
|
threads_length=threads_length,
|
||||||
bold="",
|
bold="",
|
||||||
end_bold="",
|
end_bold="",
|
||||||
vcpus=data["vcpus"],
|
name=name,
|
||||||
sockets=data["sockets"],
|
vcpus=vcpus[0],
|
||||||
cores=data["cores"],
|
sockets=vcpus[1][0],
|
||||||
threads=data["threads"],
|
cores=vcpus[1][1],
|
||||||
|
threads=vcpus[1][2],
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
return "\n".join(output_list)
|
return "\n".join(output_list)
|
||||||
@@ -608,35 +619,44 @@ def vm_memory_get(config, vm):
|
|||||||
except Exception:
|
except Exception:
|
||||||
return False, "ERROR: Failed to parse XML data."
|
return False, "ERROR: Failed to parse XML data."
|
||||||
|
|
||||||
data = dict()
|
vm_memory = int(parsed_xml.memory.text)
|
||||||
data["name"] = vm
|
|
||||||
data["memory"] = int(parsed_xml.memory.text)
|
|
||||||
|
|
||||||
return True, data
|
return True, vm_memory
|
||||||
|
|
||||||
|
|
||||||
def format_vm_memory(config, data):
|
def format_vm_memory(config, name, memory):
|
||||||
"""
|
"""
|
||||||
Format the output of a memory value in a nice table
|
Format the output of a memory value in a nice table
|
||||||
"""
|
"""
|
||||||
output_list = []
|
output_list = []
|
||||||
|
|
||||||
|
name_length = 5
|
||||||
|
_name_length = len(name) + 1
|
||||||
|
if _name_length > name_length:
|
||||||
|
name_length = _name_length
|
||||||
|
|
||||||
memory_length = 6
|
memory_length = 6
|
||||||
|
|
||||||
output_list.append(
|
output_list.append(
|
||||||
"{bold}{memory: <{memory_length}}{end_bold}".format(
|
"{bold}{name: <{name_length}} \
|
||||||
|
{memory: <{memory_length}}{end_bold}".format(
|
||||||
|
name_length=name_length,
|
||||||
memory_length=memory_length,
|
memory_length=memory_length,
|
||||||
bold=ansiprint.bold(),
|
bold=ansiprint.bold(),
|
||||||
end_bold=ansiprint.end(),
|
end_bold=ansiprint.end(),
|
||||||
|
name="Name",
|
||||||
memory="RAM (M)",
|
memory="RAM (M)",
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
output_list.append(
|
output_list.append(
|
||||||
"{bold}{memory: <{memory_length}}{end_bold}".format(
|
"{bold}{name: <{name_length}} \
|
||||||
|
{memory: <{memory_length}}{end_bold}".format(
|
||||||
|
name_length=name_length,
|
||||||
memory_length=memory_length,
|
memory_length=memory_length,
|
||||||
bold="",
|
bold="",
|
||||||
end_bold="",
|
end_bold="",
|
||||||
memory=data["memory"],
|
name=name,
|
||||||
|
memory=memory,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
return "\n".join(output_list)
|
return "\n".join(output_list)
|
||||||
@@ -926,9 +946,7 @@ def vm_networks_get(config, vm):
|
|||||||
except Exception:
|
except Exception:
|
||||||
return False, "ERROR: Failed to parse XML data."
|
return False, "ERROR: Failed to parse XML data."
|
||||||
|
|
||||||
data = dict()
|
network_data = list()
|
||||||
data["name"] = vm
|
|
||||||
data["networks"] = list()
|
|
||||||
for interface in parsed_xml.devices.find("interface"):
|
for interface in parsed_xml.devices.find("interface"):
|
||||||
mac_address = interface.mac.attrib.get("address")
|
mac_address = interface.mac.attrib.get("address")
|
||||||
model = interface.model.attrib.get("type")
|
model = interface.model.attrib.get("type")
|
||||||
@@ -942,65 +960,76 @@ def vm_networks_get(config, vm):
|
|||||||
elif interface_type == "hostdev":
|
elif interface_type == "hostdev":
|
||||||
network = "hostdev:{}".format(interface.source.attrib.get("dev"))
|
network = "hostdev:{}".format(interface.source.attrib.get("dev"))
|
||||||
|
|
||||||
data["networks"].append(
|
network_data.append((network, mac_address, model))
|
||||||
{"network": network, "mac_address": mac_address, "model": model}
|
|
||||||
)
|
|
||||||
|
|
||||||
return True, data
|
return True, network_data
|
||||||
|
|
||||||
|
|
||||||
def format_vm_networks(config, data):
|
def format_vm_networks(config, name, networks):
|
||||||
"""
|
"""
|
||||||
Format the output of a network list in a nice table
|
Format the output of a network list in a nice table
|
||||||
"""
|
"""
|
||||||
output_list = []
|
output_list = []
|
||||||
|
|
||||||
network_length = 8
|
name_length = 5
|
||||||
|
vni_length = 8
|
||||||
macaddr_length = 12
|
macaddr_length = 12
|
||||||
model_length = 6
|
model_length = 6
|
||||||
|
|
||||||
for network in data["networks"]:
|
_name_length = len(name) + 1
|
||||||
_network_length = len(network["network"]) + 1
|
if _name_length > name_length:
|
||||||
if _network_length > network_length:
|
name_length = _name_length
|
||||||
network_length = _network_length
|
|
||||||
|
|
||||||
_macaddr_length = len(network["mac_address"]) + 1
|
for network in networks:
|
||||||
|
_vni_length = len(network[0]) + 1
|
||||||
|
if _vni_length > vni_length:
|
||||||
|
vni_length = _vni_length
|
||||||
|
|
||||||
|
_macaddr_length = len(network[1]) + 1
|
||||||
if _macaddr_length > macaddr_length:
|
if _macaddr_length > macaddr_length:
|
||||||
macaddr_length = _macaddr_length
|
macaddr_length = _macaddr_length
|
||||||
|
|
||||||
_model_length = len(network["model"]) + 1
|
_model_length = len(network[2]) + 1
|
||||||
if _model_length > model_length:
|
if _model_length > model_length:
|
||||||
model_length = _model_length
|
model_length = _model_length
|
||||||
|
|
||||||
output_list.append(
|
output_list.append(
|
||||||
"{bold}{network: <{network_length}} \
|
"{bold}{name: <{name_length}} \
|
||||||
|
{vni: <{vni_length}} \
|
||||||
{macaddr: <{macaddr_length}} \
|
{macaddr: <{macaddr_length}} \
|
||||||
{model: <{model_length}}{end_bold}".format(
|
{model: <{model_length}}{end_bold}".format(
|
||||||
network_length=network_length,
|
name_length=name_length,
|
||||||
|
vni_length=vni_length,
|
||||||
macaddr_length=macaddr_length,
|
macaddr_length=macaddr_length,
|
||||||
model_length=model_length,
|
model_length=model_length,
|
||||||
bold=ansiprint.bold(),
|
bold=ansiprint.bold(),
|
||||||
end_bold=ansiprint.end(),
|
end_bold=ansiprint.end(),
|
||||||
network="Network",
|
name="Name",
|
||||||
|
vni="Network",
|
||||||
macaddr="MAC Address",
|
macaddr="MAC Address",
|
||||||
model="Model",
|
model="Model",
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
count = 0
|
count = 0
|
||||||
for network in data["networks"]:
|
for network in networks:
|
||||||
|
if count > 0:
|
||||||
|
name = ""
|
||||||
count += 1
|
count += 1
|
||||||
output_list.append(
|
output_list.append(
|
||||||
"{bold}{network: <{network_length}} \
|
"{bold}{name: <{name_length}} \
|
||||||
|
{vni: <{vni_length}} \
|
||||||
{macaddr: <{macaddr_length}} \
|
{macaddr: <{macaddr_length}} \
|
||||||
{model: <{model_length}}{end_bold}".format(
|
{model: <{model_length}}{end_bold}".format(
|
||||||
network_length=network_length,
|
name_length=name_length,
|
||||||
|
vni_length=vni_length,
|
||||||
macaddr_length=macaddr_length,
|
macaddr_length=macaddr_length,
|
||||||
model_length=model_length,
|
model_length=model_length,
|
||||||
bold="",
|
bold="",
|
||||||
end_bold="",
|
end_bold="",
|
||||||
network=network["network"],
|
name=name,
|
||||||
macaddr=network["mac_address"],
|
vni=network[0],
|
||||||
model=network["model"],
|
macaddr=network[1],
|
||||||
|
model=network[2],
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
return "\n".join(output_list)
|
return "\n".join(output_list)
|
||||||
@@ -1241,9 +1270,7 @@ def vm_volumes_get(config, vm):
|
|||||||
except Exception:
|
except Exception:
|
||||||
return False, "ERROR: Failed to parse XML data."
|
return False, "ERROR: Failed to parse XML data."
|
||||||
|
|
||||||
data = dict()
|
volume_data = list()
|
||||||
data["name"] = vm
|
|
||||||
data["volumes"] = list()
|
|
||||||
for disk in parsed_xml.devices.find("disk"):
|
for disk in parsed_xml.devices.find("disk"):
|
||||||
protocol = disk.attrib.get("type")
|
protocol = disk.attrib.get("type")
|
||||||
disk_id = disk.target.attrib.get("dev")
|
disk_id = disk.target.attrib.get("dev")
|
||||||
@@ -1258,52 +1285,58 @@ def vm_volumes_get(config, vm):
|
|||||||
protocol = "unknown"
|
protocol = "unknown"
|
||||||
source = "unknown"
|
source = "unknown"
|
||||||
|
|
||||||
data["volumes"].append(
|
volume_data.append((source, disk_id, protocol, bus))
|
||||||
{"volume": source, "disk_id": disk_id, "protocol": protocol, "bus": bus}
|
|
||||||
)
|
|
||||||
|
|
||||||
return True, data
|
return True, volume_data
|
||||||
|
|
||||||
|
|
||||||
def format_vm_volumes(config, data):
|
def format_vm_volumes(config, name, volumes):
|
||||||
"""
|
"""
|
||||||
Format the output of a volume value in a nice table
|
Format the output of a volume value in a nice table
|
||||||
"""
|
"""
|
||||||
output_list = []
|
output_list = []
|
||||||
|
|
||||||
|
name_length = 5
|
||||||
volume_length = 7
|
volume_length = 7
|
||||||
disk_id_length = 4
|
disk_id_length = 4
|
||||||
protocol_length = 5
|
protocol_length = 5
|
||||||
bus_length = 4
|
bus_length = 4
|
||||||
|
|
||||||
for volume in data["volumes"]:
|
_name_length = len(name) + 1
|
||||||
_volume_length = len(volume["volume"]) + 1
|
if _name_length > name_length:
|
||||||
|
name_length = _name_length
|
||||||
|
|
||||||
|
for volume in volumes:
|
||||||
|
_volume_length = len(volume[0]) + 1
|
||||||
if _volume_length > volume_length:
|
if _volume_length > volume_length:
|
||||||
volume_length = _volume_length
|
volume_length = _volume_length
|
||||||
|
|
||||||
_disk_id_length = len(volume["disk_id"]) + 1
|
_disk_id_length = len(volume[1]) + 1
|
||||||
if _disk_id_length > disk_id_length:
|
if _disk_id_length > disk_id_length:
|
||||||
disk_id_length = _disk_id_length
|
disk_id_length = _disk_id_length
|
||||||
|
|
||||||
_protocol_length = len(volume["protocol"]) + 1
|
_protocol_length = len(volume[2]) + 1
|
||||||
if _protocol_length > protocol_length:
|
if _protocol_length > protocol_length:
|
||||||
protocol_length = _protocol_length
|
protocol_length = _protocol_length
|
||||||
|
|
||||||
_bus_length = len(volume["bus"]) + 1
|
_bus_length = len(volume[3]) + 1
|
||||||
if _bus_length > bus_length:
|
if _bus_length > bus_length:
|
||||||
bus_length = _bus_length
|
bus_length = _bus_length
|
||||||
|
|
||||||
output_list.append(
|
output_list.append(
|
||||||
"{bold}{volume: <{volume_length}} \
|
"{bold}{name: <{name_length}} \
|
||||||
|
{volume: <{volume_length}} \
|
||||||
{disk_id: <{disk_id_length}} \
|
{disk_id: <{disk_id_length}} \
|
||||||
{protocol: <{protocol_length}} \
|
{protocol: <{protocol_length}} \
|
||||||
{bus: <{bus_length}}{end_bold}".format(
|
{bus: <{bus_length}}{end_bold}".format(
|
||||||
|
name_length=name_length,
|
||||||
volume_length=volume_length,
|
volume_length=volume_length,
|
||||||
disk_id_length=disk_id_length,
|
disk_id_length=disk_id_length,
|
||||||
protocol_length=protocol_length,
|
protocol_length=protocol_length,
|
||||||
bus_length=bus_length,
|
bus_length=bus_length,
|
||||||
bold=ansiprint.bold(),
|
bold=ansiprint.bold(),
|
||||||
end_bold=ansiprint.end(),
|
end_bold=ansiprint.end(),
|
||||||
|
name="Name",
|
||||||
volume="Volume",
|
volume="Volume",
|
||||||
disk_id="Dev",
|
disk_id="Dev",
|
||||||
protocol="Type",
|
protocol="Type",
|
||||||
@@ -1311,23 +1344,28 @@ def format_vm_volumes(config, data):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
count = 0
|
count = 0
|
||||||
for volume in data["volumes"]:
|
for volume in volumes:
|
||||||
|
if count > 0:
|
||||||
|
name = ""
|
||||||
count += 1
|
count += 1
|
||||||
output_list.append(
|
output_list.append(
|
||||||
"{bold}{volume: <{volume_length}} \
|
"{bold}{name: <{name_length}} \
|
||||||
|
{volume: <{volume_length}} \
|
||||||
{disk_id: <{disk_id_length}} \
|
{disk_id: <{disk_id_length}} \
|
||||||
{protocol: <{protocol_length}} \
|
{protocol: <{protocol_length}} \
|
||||||
{bus: <{bus_length}}{end_bold}".format(
|
{bus: <{bus_length}}{end_bold}".format(
|
||||||
|
name_length=name_length,
|
||||||
volume_length=volume_length,
|
volume_length=volume_length,
|
||||||
disk_id_length=disk_id_length,
|
disk_id_length=disk_id_length,
|
||||||
protocol_length=protocol_length,
|
protocol_length=protocol_length,
|
||||||
bus_length=bus_length,
|
bus_length=bus_length,
|
||||||
bold="",
|
bold="",
|
||||||
end_bold="",
|
end_bold="",
|
||||||
volume=volume["volume"],
|
name=name,
|
||||||
disk_id=volume["disk_id"],
|
volume=volume[0],
|
||||||
protocol=volume["protocol"],
|
disk_id=volume[1],
|
||||||
bus=volume["bus"],
|
protocol=volume[2],
|
||||||
|
bus=volume[3],
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
return "\n".join(output_list)
|
return "\n".join(output_list)
|
||||||
@@ -1831,7 +1869,7 @@ def format_info(config, domain_information, long_output):
|
|||||||
return "\n".join(ainformation)
|
return "\n".join(ainformation)
|
||||||
|
|
||||||
|
|
||||||
def format_list(config, vm_list):
|
def format_list(config, vm_list, raw):
|
||||||
# Function to strip the "br" off of nets and return a nicer list
|
# Function to strip the "br" off of nets and return a nicer list
|
||||||
def getNiceNetID(domain_information):
|
def getNiceNetID(domain_information):
|
||||||
# Network list
|
# Network list
|
||||||
@@ -1850,6 +1888,13 @@ def format_list(config, vm_list):
|
|||||||
tag_list.append(tag["name"])
|
tag_list.append(tag["name"])
|
||||||
return tag_list
|
return tag_list
|
||||||
|
|
||||||
|
# Handle raw mode since it just lists the names
|
||||||
|
if raw:
|
||||||
|
ainformation = list()
|
||||||
|
for vm in sorted(item["name"] for item in vm_list):
|
||||||
|
ainformation.append(vm)
|
||||||
|
return "\n".join(ainformation)
|
||||||
|
|
||||||
vm_list_output = []
|
vm_list_output = []
|
||||||
|
|
||||||
# Determine optimal column widths
|
# Determine optimal column widths
|
||||||
@@ -21,8 +21,7 @@
|
|||||||
|
|
||||||
import json
|
import json
|
||||||
|
|
||||||
import pvc.cli_lib.ansiprint as ansiprint
|
from pvc.lib.common import call_api
|
||||||
from pvc.cli_lib.common import call_api
|
|
||||||
|
|
||||||
|
|
||||||
def initialize(config, overwrite=False):
|
def initialize(config, overwrite=False):
|
||||||
@@ -115,199 +114,3 @@ def get_info(config):
|
|||||||
return True, response.json()
|
return True, response.json()
|
||||||
else:
|
else:
|
||||||
return False, response.json().get("message", "")
|
return False, response.json().get("message", "")
|
||||||
|
|
||||||
|
|
||||||
def format_info(cluster_information, oformat):
|
|
||||||
if oformat == "json":
|
|
||||||
return json.dumps(cluster_information)
|
|
||||||
|
|
||||||
if oformat == "json-pretty":
|
|
||||||
return json.dumps(cluster_information, indent=4)
|
|
||||||
|
|
||||||
# Plain formatting, i.e. human-readable
|
|
||||||
if (
|
|
||||||
cluster_information.get("maintenance") == "true"
|
|
||||||
or cluster_information.get("cluster_health", {}).get("health", "N/A") == "N/A"
|
|
||||||
):
|
|
||||||
health_colour = ansiprint.blue()
|
|
||||||
elif cluster_information.get("cluster_health", {}).get("health", 100) > 90:
|
|
||||||
health_colour = ansiprint.green()
|
|
||||||
elif cluster_information.get("cluster_health", {}).get("health", 100) > 50:
|
|
||||||
health_colour = ansiprint.yellow()
|
|
||||||
else:
|
|
||||||
health_colour = ansiprint.red()
|
|
||||||
|
|
||||||
ainformation = []
|
|
||||||
|
|
||||||
ainformation.append(
|
|
||||||
"{}PVC cluster status:{}".format(ansiprint.bold(), ansiprint.end())
|
|
||||||
)
|
|
||||||
ainformation.append("")
|
|
||||||
|
|
||||||
health_text = (
|
|
||||||
f"{cluster_information.get('cluster_health', {}).get('health', 'N/A')}"
|
|
||||||
)
|
|
||||||
if health_text != "N/A":
|
|
||||||
health_text += "%"
|
|
||||||
if cluster_information.get("maintenance") == "true":
|
|
||||||
health_text += " (maintenance on)"
|
|
||||||
|
|
||||||
ainformation.append(
|
|
||||||
"{}Cluster health:{} {}{}{}".format(
|
|
||||||
ansiprint.purple(),
|
|
||||||
ansiprint.end(),
|
|
||||||
health_colour,
|
|
||||||
health_text,
|
|
||||||
ansiprint.end(),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
if cluster_information.get("cluster_health", {}).get("messages"):
|
|
||||||
health_messages = "\n > ".join(
|
|
||||||
sorted(cluster_information["cluster_health"]["messages"])
|
|
||||||
)
|
|
||||||
ainformation.append(
|
|
||||||
"{}Health messages:{} > {}".format(
|
|
||||||
ansiprint.purple(),
|
|
||||||
ansiprint.end(),
|
|
||||||
health_messages,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
ainformation.append(
|
|
||||||
"{}Health messages:{} N/A".format(
|
|
||||||
ansiprint.purple(),
|
|
||||||
ansiprint.end(),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
if oformat == "short":
|
|
||||||
return "\n".join(ainformation)
|
|
||||||
|
|
||||||
ainformation.append("")
|
|
||||||
ainformation.append(
|
|
||||||
"{}Primary node:{} {}".format(
|
|
||||||
ansiprint.purple(), ansiprint.end(), cluster_information["primary_node"]
|
|
||||||
)
|
|
||||||
)
|
|
||||||
ainformation.append(
|
|
||||||
"{}PVC version:{} {}".format(
|
|
||||||
ansiprint.purple(),
|
|
||||||
ansiprint.end(),
|
|
||||||
cluster_information.get("pvc_version", "N/A"),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
ainformation.append(
|
|
||||||
"{}Cluster upstream IP:{} {}".format(
|
|
||||||
ansiprint.purple(), ansiprint.end(), cluster_information["upstream_ip"]
|
|
||||||
)
|
|
||||||
)
|
|
||||||
ainformation.append("")
|
|
||||||
ainformation.append(
|
|
||||||
"{}Total nodes:{} {}".format(
|
|
||||||
ansiprint.purple(), ansiprint.end(), cluster_information["nodes"]["total"]
|
|
||||||
)
|
|
||||||
)
|
|
||||||
ainformation.append(
|
|
||||||
"{}Total VMs:{} {}".format(
|
|
||||||
ansiprint.purple(), ansiprint.end(), cluster_information["vms"]["total"]
|
|
||||||
)
|
|
||||||
)
|
|
||||||
ainformation.append(
|
|
||||||
"{}Total networks:{} {}".format(
|
|
||||||
ansiprint.purple(), ansiprint.end(), cluster_information["networks"]
|
|
||||||
)
|
|
||||||
)
|
|
||||||
ainformation.append(
|
|
||||||
"{}Total OSDs:{} {}".format(
|
|
||||||
ansiprint.purple(), ansiprint.end(), cluster_information["osds"]["total"]
|
|
||||||
)
|
|
||||||
)
|
|
||||||
ainformation.append(
|
|
||||||
"{}Total pools:{} {}".format(
|
|
||||||
ansiprint.purple(), ansiprint.end(), cluster_information["pools"]
|
|
||||||
)
|
|
||||||
)
|
|
||||||
ainformation.append(
|
|
||||||
"{}Total volumes:{} {}".format(
|
|
||||||
ansiprint.purple(), ansiprint.end(), cluster_information["volumes"]
|
|
||||||
)
|
|
||||||
)
|
|
||||||
ainformation.append(
|
|
||||||
"{}Total snapshots:{} {}".format(
|
|
||||||
ansiprint.purple(), ansiprint.end(), cluster_information["snapshots"]
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
nodes_string = "{}Nodes:{} {}/{} {}ready,run{}".format(
|
|
||||||
ansiprint.purple(),
|
|
||||||
ansiprint.end(),
|
|
||||||
cluster_information["nodes"].get("run,ready", 0),
|
|
||||||
cluster_information["nodes"].get("total", 0),
|
|
||||||
ansiprint.green(),
|
|
||||||
ansiprint.end(),
|
|
||||||
)
|
|
||||||
for state, count in cluster_information["nodes"].items():
|
|
||||||
if state == "total" or state == "run,ready":
|
|
||||||
continue
|
|
||||||
|
|
||||||
nodes_string += " {}/{} {}{}{}".format(
|
|
||||||
count,
|
|
||||||
cluster_information["nodes"]["total"],
|
|
||||||
ansiprint.yellow(),
|
|
||||||
state,
|
|
||||||
ansiprint.end(),
|
|
||||||
)
|
|
||||||
|
|
||||||
ainformation.append("")
|
|
||||||
ainformation.append(nodes_string)
|
|
||||||
|
|
||||||
vms_string = "{}VMs:{} {}/{} {}start{}".format(
|
|
||||||
ansiprint.purple(),
|
|
||||||
ansiprint.end(),
|
|
||||||
cluster_information["vms"].get("start", 0),
|
|
||||||
cluster_information["vms"].get("total", 0),
|
|
||||||
ansiprint.green(),
|
|
||||||
ansiprint.end(),
|
|
||||||
)
|
|
||||||
for state, count in cluster_information["vms"].items():
|
|
||||||
if state == "total" or state == "start":
|
|
||||||
continue
|
|
||||||
|
|
||||||
if state in ["disable", "migrate", "unmigrate", "provision"]:
|
|
||||||
colour = ansiprint.blue()
|
|
||||||
else:
|
|
||||||
colour = ansiprint.yellow()
|
|
||||||
|
|
||||||
vms_string += " {}/{} {}{}{}".format(
|
|
||||||
count, cluster_information["vms"]["total"], colour, state, ansiprint.end()
|
|
||||||
)
|
|
||||||
|
|
||||||
ainformation.append("")
|
|
||||||
ainformation.append(vms_string)
|
|
||||||
|
|
||||||
if cluster_information["osds"]["total"] > 0:
|
|
||||||
osds_string = "{}Ceph OSDs:{} {}/{} {}up,in{}".format(
|
|
||||||
ansiprint.purple(),
|
|
||||||
ansiprint.end(),
|
|
||||||
cluster_information["osds"].get("up,in", 0),
|
|
||||||
cluster_information["osds"].get("total", 0),
|
|
||||||
ansiprint.green(),
|
|
||||||
ansiprint.end(),
|
|
||||||
)
|
|
||||||
for state, count in cluster_information["osds"].items():
|
|
||||||
if state == "total" or state == "up,in":
|
|
||||||
continue
|
|
||||||
|
|
||||||
osds_string += " {}/{} {}{}{}".format(
|
|
||||||
count,
|
|
||||||
cluster_information["osds"]["total"],
|
|
||||||
ansiprint.yellow(),
|
|
||||||
state,
|
|
||||||
ansiprint.end(),
|
|
||||||
)
|
|
||||||
|
|
||||||
ainformation.append("")
|
|
||||||
ainformation.append(osds_string)
|
|
||||||
|
|
||||||
ainformation.append("")
|
|
||||||
return "\n".join(ainformation)
|
|
||||||
|
|||||||
@@ -20,8 +20,8 @@
|
|||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
import re
|
import re
|
||||||
import pvc.cli_lib.ansiprint as ansiprint
|
import pvc.lib.ansiprint as ansiprint
|
||||||
from pvc.cli_lib.common import call_api
|
from pvc.lib.common import call_api
|
||||||
|
|
||||||
|
|
||||||
def isValidMAC(macaddr):
|
def isValidMAC(macaddr):
|
||||||
@@ -542,11 +542,16 @@ def net_sriov_vf_info(config, node, vf):
|
|||||||
return False, "VF not found."
|
return False, "VF not found."
|
||||||
else:
|
else:
|
||||||
# Return a single instance if the response is a list
|
# Return a single instance if the response is a list
|
||||||
|
data = dict()
|
||||||
|
data["node"] = node
|
||||||
if isinstance(response.json(), list):
|
if isinstance(response.json(), list):
|
||||||
return True, response.json()[0]
|
data = dict()
|
||||||
|
data["vf_information"] = response.json()[0]
|
||||||
|
return True, data
|
||||||
# This shouldn't happen, but is here just in case
|
# This shouldn't happen, but is here just in case
|
||||||
else:
|
else:
|
||||||
return True, response.json()
|
data["vf_information"] = response.json()
|
||||||
|
return True, data
|
||||||
else:
|
else:
|
||||||
return False, response.json().get("message", "")
|
return False, response.json().get("message", "")
|
||||||
|
|
||||||
@@ -714,7 +719,7 @@ def format_info(config, network_information, long_output):
|
|||||||
)
|
)
|
||||||
ainformation.append("")
|
ainformation.append("")
|
||||||
if retcode:
|
if retcode:
|
||||||
firewall_rules_string = format_list_acl(firewall_rules_list)
|
firewall_rules_string = format_list_acl(config, firewall_rules_list)
|
||||||
for line in firewall_rules_string.split("\n"):
|
for line in firewall_rules_string.split("\n"):
|
||||||
ainformation.append(line)
|
ainformation.append(line)
|
||||||
else:
|
else:
|
||||||
@@ -888,7 +893,7 @@ def format_list(config, network_list):
|
|||||||
return "\n".join(network_list_output)
|
return "\n".join(network_list_output)
|
||||||
|
|
||||||
|
|
||||||
def format_list_dhcp(dhcp_lease_list):
|
def format_list_dhcp(config, dhcp_lease_list):
|
||||||
dhcp_lease_list_output = []
|
dhcp_lease_list_output = []
|
||||||
|
|
||||||
# Determine optimal column widths
|
# Determine optimal column widths
|
||||||
@@ -987,7 +992,7 @@ def format_list_dhcp(dhcp_lease_list):
|
|||||||
return "\n".join(dhcp_lease_list_output)
|
return "\n".join(dhcp_lease_list_output)
|
||||||
|
|
||||||
|
|
||||||
def format_list_acl(acl_list):
|
def format_list_acl(config, acl_list):
|
||||||
# Handle when we get an empty entry
|
# Handle when we get an empty entry
|
||||||
if not acl_list:
|
if not acl_list:
|
||||||
acl_list = list()
|
acl_list = list()
|
||||||
@@ -1086,7 +1091,7 @@ def format_list_acl(acl_list):
|
|||||||
return "\n".join(acl_list_output)
|
return "\n".join(acl_list_output)
|
||||||
|
|
||||||
|
|
||||||
def format_list_sriov_pf(pf_list):
|
def format_list_sriov_pf(config, pf_list):
|
||||||
# The maximum column width of the VFs column
|
# The maximum column width of the VFs column
|
||||||
max_vfs_length = 70
|
max_vfs_length = 70
|
||||||
|
|
||||||
@@ -1206,7 +1211,7 @@ def format_list_sriov_pf(pf_list):
|
|||||||
return "\n".join(pf_list_output)
|
return "\n".join(pf_list_output)
|
||||||
|
|
||||||
|
|
||||||
def format_list_sriov_vf(vf_list):
|
def format_list_sriov_vf(config, vf_list):
|
||||||
# Handle when we get an empty entry
|
# Handle when we get an empty entry
|
||||||
if not vf_list:
|
if not vf_list:
|
||||||
vf_list = list()
|
vf_list = list()
|
||||||
@@ -1338,10 +1343,13 @@ def format_list_sriov_vf(vf_list):
|
|||||||
return "\n".join(vf_list_output)
|
return "\n".join(vf_list_output)
|
||||||
|
|
||||||
|
|
||||||
def format_info_sriov_vf(config, vf_information, node):
|
def format_info_sriov_vf(config, data):
|
||||||
if not vf_information:
|
if not data or not data["vf_information"]:
|
||||||
return "No VF found"
|
return "No VF found"
|
||||||
|
|
||||||
|
node = data["node"]
|
||||||
|
vf_information = data["vf_information"]
|
||||||
|
|
||||||
# Get information on the using VM if applicable
|
# Get information on the using VM if applicable
|
||||||
if vf_information["usage"]["used"] == "True" and vf_information["usage"]["domain"]:
|
if vf_information["usage"]["used"] == "True" and vf_information["usage"]["domain"]:
|
||||||
vm_information = call_api(
|
vm_information = call_api(
|
||||||
|
|||||||
@@ -21,8 +21,8 @@
|
|||||||
|
|
||||||
import time
|
import time
|
||||||
|
|
||||||
import pvc.cli_lib.ansiprint as ansiprint
|
import pvc.lib.ansiprint as ansiprint
|
||||||
from pvc.cli_lib.common import call_api
|
from pvc.lib.common import call_api
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
@@ -52,7 +52,7 @@ def node_coordinator_state(config, node, action):
|
|||||||
return retstatus, response.json().get("message", "")
|
return retstatus, response.json().get("message", "")
|
||||||
|
|
||||||
|
|
||||||
def node_domain_state(config, node, action, wait):
|
def node_domain_state(config, node, action):
|
||||||
"""
|
"""
|
||||||
Set node domain state state (flush/ready)
|
Set node domain state state (flush/ready)
|
||||||
|
|
||||||
@@ -60,7 +60,7 @@ def node_domain_state(config, node, action, wait):
|
|||||||
API arguments: action={action}, wait={wait}
|
API arguments: action={action}, wait={wait}
|
||||||
API schema: {"message": "{data}"}
|
API schema: {"message": "{data}"}
|
||||||
"""
|
"""
|
||||||
params = {"state": action, "wait": str(wait).lower()}
|
params = {"state": action}
|
||||||
response = call_api(
|
response = call_api(
|
||||||
config, "post", "/node/{node}/domain-state".format(node=node), params=params
|
config, "post", "/node/{node}/domain-state".format(node=node), params=params
|
||||||
)
|
)
|
||||||
@@ -273,7 +273,7 @@ def getOutputColours(node_information):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def format_info(node_information, long_output):
|
def format_info(config, node_information, long_output):
|
||||||
(
|
(
|
||||||
health_colour,
|
health_colour,
|
||||||
daemon_state_colour,
|
daemon_state_colour,
|
||||||
@@ -442,12 +442,9 @@ def format_info(node_information, long_output):
|
|||||||
return "\n".join(ainformation)
|
return "\n".join(ainformation)
|
||||||
|
|
||||||
|
|
||||||
def format_list(node_list, raw):
|
def format_list(config, node_list):
|
||||||
if raw:
|
if node_list == "Node not found.":
|
||||||
ainformation = list()
|
return node_list
|
||||||
for node in sorted(item["name"] for item in node_list):
|
|
||||||
ainformation.append(node)
|
|
||||||
return "\n".join(ainformation)
|
|
||||||
|
|
||||||
node_list_output = []
|
node_list_output = []
|
||||||
|
|
||||||
|
|||||||
@@ -24,8 +24,8 @@ from requests_toolbelt.multipart.encoder import (
|
|||||||
MultipartEncoderMonitor,
|
MultipartEncoderMonitor,
|
||||||
)
|
)
|
||||||
|
|
||||||
import pvc.cli_lib.ansiprint as ansiprint
|
import pvc.lib.ansiprint as ansiprint
|
||||||
from pvc.cli_lib.common import UploadProgressBar, call_api
|
from pvc.lib.common import UploadProgressBar, call_api
|
||||||
from ast import literal_eval
|
from ast import literal_eval
|
||||||
|
|
||||||
|
|
||||||
@@ -750,24 +750,11 @@ def task_status(config, task_id=None, is_watching=False):
|
|||||||
if response.status_code == 200:
|
if response.status_code == 200:
|
||||||
retvalue = True
|
retvalue = True
|
||||||
respjson = response.json()
|
respjson = response.json()
|
||||||
|
|
||||||
if is_watching:
|
if is_watching:
|
||||||
# Just return the raw JSON to the watching process instead of formatting it
|
# Just return the raw JSON to the watching process instead of including value
|
||||||
return respjson
|
return respjson
|
||||||
|
|
||||||
job_state = respjson["state"]
|
|
||||||
if job_state == "RUNNING":
|
|
||||||
retdata = "Job state: RUNNING\nStage: {}/{}\nStatus: {}".format(
|
|
||||||
respjson["current"], respjson["total"], respjson["status"]
|
|
||||||
)
|
|
||||||
elif job_state == "FAILED":
|
|
||||||
retdata = "Job state: FAILED\nStatus: {}".format(respjson["status"])
|
|
||||||
elif job_state == "COMPLETED":
|
|
||||||
retdata = "Job state: COMPLETED\nStatus: {}".format(respjson["status"])
|
|
||||||
else:
|
else:
|
||||||
retdata = "Job state: {}\nStatus: {}".format(
|
return retvalue, respjson
|
||||||
respjson["state"], respjson["status"]
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
retvalue = False
|
retvalue = False
|
||||||
retdata = response.json().get("message", "")
|
retdata = response.json().get("message", "")
|
||||||
@@ -814,7 +801,7 @@ def task_status(config, task_id=None, is_watching=False):
|
|||||||
#
|
#
|
||||||
# Format functions
|
# Format functions
|
||||||
#
|
#
|
||||||
def format_list_template(template_data, template_type=None):
|
def format_list_template(config, template_data, template_type=None):
|
||||||
"""
|
"""
|
||||||
Format the returned template template
|
Format the returned template template
|
||||||
|
|
||||||
@@ -1330,7 +1317,12 @@ def format_list_template_storage(template_template):
|
|||||||
return "\n".join(template_list_output)
|
return "\n".join(template_list_output)
|
||||||
|
|
||||||
|
|
||||||
def format_list_userdata(userdata_data, lines=None):
|
def format_list_userdata(config, userdata_data):
|
||||||
|
if not config.get("long_output"):
|
||||||
|
lines = 4
|
||||||
|
else:
|
||||||
|
lines = None
|
||||||
|
|
||||||
if isinstance(userdata_data, dict):
|
if isinstance(userdata_data, dict):
|
||||||
userdata_data = [userdata_data]
|
userdata_data = [userdata_data]
|
||||||
|
|
||||||
@@ -1432,7 +1424,12 @@ def format_list_userdata(userdata_data, lines=None):
|
|||||||
return "\n".join(userdata_list_output)
|
return "\n".join(userdata_list_output)
|
||||||
|
|
||||||
|
|
||||||
def format_list_script(script_data, lines=None):
|
def format_list_script(config, script_data):
|
||||||
|
if not config.get("long_output"):
|
||||||
|
lines = 4
|
||||||
|
else:
|
||||||
|
lines = None
|
||||||
|
|
||||||
if isinstance(script_data, dict):
|
if isinstance(script_data, dict):
|
||||||
script_data = [script_data]
|
script_data = [script_data]
|
||||||
|
|
||||||
@@ -1531,7 +1528,7 @@ def format_list_script(script_data, lines=None):
|
|||||||
return "\n".join(script_list_output)
|
return "\n".join(script_list_output)
|
||||||
|
|
||||||
|
|
||||||
def format_list_ova(ova_data):
|
def format_list_ova(config, ova_data):
|
||||||
if isinstance(ova_data, dict):
|
if isinstance(ova_data, dict):
|
||||||
ova_data = [ova_data]
|
ova_data = [ova_data]
|
||||||
|
|
||||||
@@ -1678,7 +1675,7 @@ def format_list_ova(ova_data):
|
|||||||
return "\n".join(ova_list_output)
|
return "\n".join(ova_list_output)
|
||||||
|
|
||||||
|
|
||||||
def format_list_profile(profile_data):
|
def format_list_profile(config, profile_data):
|
||||||
if isinstance(profile_data, dict):
|
if isinstance(profile_data, dict):
|
||||||
profile_data = [profile_data]
|
profile_data = [profile_data]
|
||||||
|
|
||||||
@@ -1867,7 +1864,23 @@ def format_list_profile(profile_data):
|
|||||||
return "\n".join(profile_list_output)
|
return "\n".join(profile_list_output)
|
||||||
|
|
||||||
|
|
||||||
def format_list_task(task_data):
|
def format_list_task(config, task_data):
|
||||||
|
if not isinstance(task_data, list):
|
||||||
|
job_state = task_data["state"]
|
||||||
|
if job_state == "RUNNING":
|
||||||
|
retdata = "Job state: RUNNING\nStage: {}/{}\nStatus: {}".format(
|
||||||
|
task_data["current"], task_data["total"], task_data["status"]
|
||||||
|
)
|
||||||
|
elif job_state == "FAILED":
|
||||||
|
retdata = "Job state: FAILED\nStatus: {}".format(task_data["status"])
|
||||||
|
elif job_state == "COMPLETED":
|
||||||
|
retdata = "Job state: COMPLETED\nStatus: {}".format(task_data["status"])
|
||||||
|
else:
|
||||||
|
retdata = "Job state: {}\nStatus: {}".format(
|
||||||
|
task_data["state"], task_data["status"]
|
||||||
|
)
|
||||||
|
return retdata
|
||||||
|
|
||||||
task_list_output = []
|
task_list_output = []
|
||||||
|
|
||||||
# Determine optimal column widths
|
# Determine optimal column widths
|
||||||
|
|||||||
@@ -22,8 +22,8 @@
|
|||||||
import time
|
import time
|
||||||
import re
|
import re
|
||||||
|
|
||||||
import pvc.cli_lib.ansiprint as ansiprint
|
import pvc.lib.ansiprint as ansiprint
|
||||||
from pvc.cli_lib.common import call_api, format_bytes, format_metric
|
from pvc.lib.common import call_api, format_bytes, format_metric
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
@@ -286,20 +286,18 @@ def vm_tag_set(config, vm, action, tag, protected=False):
|
|||||||
return retstatus, response.json().get("message", "")
|
return retstatus, response.json().get("message", "")
|
||||||
|
|
||||||
|
|
||||||
def format_vm_tags(config, name, tags):
|
def format_vm_tags(config, data):
|
||||||
"""
|
"""
|
||||||
Format the output of a tags dictionary in a nice table
|
Format the output of a tags dictionary in a nice table
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
tags = data.get("tags", [])
|
||||||
|
|
||||||
if len(tags) < 1:
|
if len(tags) < 1:
|
||||||
return "No tags found."
|
return "No tags found."
|
||||||
|
|
||||||
output_list = []
|
output_list = []
|
||||||
|
|
||||||
name_length = 5
|
|
||||||
_name_length = len(name) + 1
|
|
||||||
if _name_length > name_length:
|
|
||||||
name_length = _name_length
|
|
||||||
|
|
||||||
tags_name_length = 4
|
tags_name_length = 4
|
||||||
tags_type_length = 5
|
tags_type_length = 5
|
||||||
tags_protected_length = 10
|
tags_protected_length = 10
|
||||||
@@ -495,44 +493,38 @@ def vm_vcpus_get(config, vm):
|
|||||||
except Exception:
|
except Exception:
|
||||||
return False, "ERROR: Failed to parse XML data."
|
return False, "ERROR: Failed to parse XML data."
|
||||||
|
|
||||||
vm_vcpus = int(parsed_xml.vcpu.text)
|
data = dict()
|
||||||
vm_sockets = parsed_xml.cpu.topology.attrib.get("sockets")
|
data["name"] = vm
|
||||||
vm_cores = parsed_xml.cpu.topology.attrib.get("cores")
|
data["vcpus"] = int(parsed_xml.vcpu.text)
|
||||||
vm_threads = parsed_xml.cpu.topology.attrib.get("threads")
|
data["sockets"] = parsed_xml.cpu.topology.attrib.get("sockets")
|
||||||
|
data["cores"] = parsed_xml.cpu.topology.attrib.get("cores")
|
||||||
|
data["threads"] = parsed_xml.cpu.topology.attrib.get("threads")
|
||||||
|
|
||||||
return True, (vm_vcpus, (vm_sockets, vm_cores, vm_threads))
|
return True, data
|
||||||
|
|
||||||
|
|
||||||
def format_vm_vcpus(config, name, vcpus):
|
def format_vm_vcpus(config, data):
|
||||||
"""
|
"""
|
||||||
Format the output of a vCPU value in a nice table
|
Format the output of a vCPU value in a nice table
|
||||||
"""
|
"""
|
||||||
output_list = []
|
output_list = []
|
||||||
|
|
||||||
name_length = 5
|
|
||||||
_name_length = len(name) + 1
|
|
||||||
if _name_length > name_length:
|
|
||||||
name_length = _name_length
|
|
||||||
|
|
||||||
vcpus_length = 6
|
vcpus_length = 6
|
||||||
sockets_length = 8
|
sockets_length = 8
|
||||||
cores_length = 6
|
cores_length = 6
|
||||||
threads_length = 8
|
threads_length = 8
|
||||||
|
|
||||||
output_list.append(
|
output_list.append(
|
||||||
"{bold}{name: <{name_length}} \
|
"{bold}{vcpus: <{vcpus_length}} \
|
||||||
{vcpus: <{vcpus_length}} \
|
|
||||||
{sockets: <{sockets_length}} \
|
{sockets: <{sockets_length}} \
|
||||||
{cores: <{cores_length}} \
|
{cores: <{cores_length}} \
|
||||||
{threads: <{threads_length}}{end_bold}".format(
|
{threads: <{threads_length}}{end_bold}".format(
|
||||||
name_length=name_length,
|
|
||||||
vcpus_length=vcpus_length,
|
vcpus_length=vcpus_length,
|
||||||
sockets_length=sockets_length,
|
sockets_length=sockets_length,
|
||||||
cores_length=cores_length,
|
cores_length=cores_length,
|
||||||
threads_length=threads_length,
|
threads_length=threads_length,
|
||||||
bold=ansiprint.bold(),
|
bold=ansiprint.bold(),
|
||||||
end_bold=ansiprint.end(),
|
end_bold=ansiprint.end(),
|
||||||
name="Name",
|
|
||||||
vcpus="vCPUs",
|
vcpus="vCPUs",
|
||||||
sockets="Sockets",
|
sockets="Sockets",
|
||||||
cores="Cores",
|
cores="Cores",
|
||||||
@@ -540,23 +532,20 @@ def format_vm_vcpus(config, name, vcpus):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
output_list.append(
|
output_list.append(
|
||||||
"{bold}{name: <{name_length}} \
|
"{bold}{vcpus: <{vcpus_length}} \
|
||||||
{vcpus: <{vcpus_length}} \
|
|
||||||
{sockets: <{sockets_length}} \
|
{sockets: <{sockets_length}} \
|
||||||
{cores: <{cores_length}} \
|
{cores: <{cores_length}} \
|
||||||
{threads: <{threads_length}}{end_bold}".format(
|
{threads: <{threads_length}}{end_bold}".format(
|
||||||
name_length=name_length,
|
|
||||||
vcpus_length=vcpus_length,
|
vcpus_length=vcpus_length,
|
||||||
sockets_length=sockets_length,
|
sockets_length=sockets_length,
|
||||||
cores_length=cores_length,
|
cores_length=cores_length,
|
||||||
threads_length=threads_length,
|
threads_length=threads_length,
|
||||||
bold="",
|
bold="",
|
||||||
end_bold="",
|
end_bold="",
|
||||||
name=name,
|
vcpus=data["vcpus"],
|
||||||
vcpus=vcpus[0],
|
sockets=data["sockets"],
|
||||||
sockets=vcpus[1][0],
|
cores=data["cores"],
|
||||||
cores=vcpus[1][1],
|
threads=data["threads"],
|
||||||
threads=vcpus[1][2],
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
return "\n".join(output_list)
|
return "\n".join(output_list)
|
||||||
@@ -619,44 +608,35 @@ def vm_memory_get(config, vm):
|
|||||||
except Exception:
|
except Exception:
|
||||||
return False, "ERROR: Failed to parse XML data."
|
return False, "ERROR: Failed to parse XML data."
|
||||||
|
|
||||||
vm_memory = int(parsed_xml.memory.text)
|
data = dict()
|
||||||
|
data["name"] = vm
|
||||||
|
data["memory"] = int(parsed_xml.memory.text)
|
||||||
|
|
||||||
return True, vm_memory
|
return True, data
|
||||||
|
|
||||||
|
|
||||||
def format_vm_memory(config, name, memory):
|
def format_vm_memory(config, data):
|
||||||
"""
|
"""
|
||||||
Format the output of a memory value in a nice table
|
Format the output of a memory value in a nice table
|
||||||
"""
|
"""
|
||||||
output_list = []
|
output_list = []
|
||||||
|
|
||||||
name_length = 5
|
|
||||||
_name_length = len(name) + 1
|
|
||||||
if _name_length > name_length:
|
|
||||||
name_length = _name_length
|
|
||||||
|
|
||||||
memory_length = 6
|
memory_length = 6
|
||||||
|
|
||||||
output_list.append(
|
output_list.append(
|
||||||
"{bold}{name: <{name_length}} \
|
"{bold}{memory: <{memory_length}}{end_bold}".format(
|
||||||
{memory: <{memory_length}}{end_bold}".format(
|
|
||||||
name_length=name_length,
|
|
||||||
memory_length=memory_length,
|
memory_length=memory_length,
|
||||||
bold=ansiprint.bold(),
|
bold=ansiprint.bold(),
|
||||||
end_bold=ansiprint.end(),
|
end_bold=ansiprint.end(),
|
||||||
name="Name",
|
|
||||||
memory="RAM (M)",
|
memory="RAM (M)",
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
output_list.append(
|
output_list.append(
|
||||||
"{bold}{name: <{name_length}} \
|
"{bold}{memory: <{memory_length}}{end_bold}".format(
|
||||||
{memory: <{memory_length}}{end_bold}".format(
|
|
||||||
name_length=name_length,
|
|
||||||
memory_length=memory_length,
|
memory_length=memory_length,
|
||||||
bold="",
|
bold="",
|
||||||
end_bold="",
|
end_bold="",
|
||||||
name=name,
|
memory=data["memory"],
|
||||||
memory=memory,
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
return "\n".join(output_list)
|
return "\n".join(output_list)
|
||||||
@@ -677,7 +657,7 @@ def vm_networks_add(
|
|||||||
from lxml.objectify import fromstring
|
from lxml.objectify import fromstring
|
||||||
from lxml.etree import tostring
|
from lxml.etree import tostring
|
||||||
from random import randint
|
from random import randint
|
||||||
import pvc.cli_lib.network as pvc_network
|
import pvc.lib.network as pvc_network
|
||||||
|
|
||||||
network_exists, _ = pvc_network.net_info(config, network)
|
network_exists, _ = pvc_network.net_info(config, network)
|
||||||
if not network_exists:
|
if not network_exists:
|
||||||
@@ -946,7 +926,9 @@ def vm_networks_get(config, vm):
|
|||||||
except Exception:
|
except Exception:
|
||||||
return False, "ERROR: Failed to parse XML data."
|
return False, "ERROR: Failed to parse XML data."
|
||||||
|
|
||||||
network_data = list()
|
data = dict()
|
||||||
|
data["name"] = vm
|
||||||
|
data["networks"] = list()
|
||||||
for interface in parsed_xml.devices.find("interface"):
|
for interface in parsed_xml.devices.find("interface"):
|
||||||
mac_address = interface.mac.attrib.get("address")
|
mac_address = interface.mac.attrib.get("address")
|
||||||
model = interface.model.attrib.get("type")
|
model = interface.model.attrib.get("type")
|
||||||
@@ -960,76 +942,65 @@ def vm_networks_get(config, vm):
|
|||||||
elif interface_type == "hostdev":
|
elif interface_type == "hostdev":
|
||||||
network = "hostdev:{}".format(interface.source.attrib.get("dev"))
|
network = "hostdev:{}".format(interface.source.attrib.get("dev"))
|
||||||
|
|
||||||
network_data.append((network, mac_address, model))
|
data["networks"].append(
|
||||||
|
{"network": network, "mac_address": mac_address, "model": model}
|
||||||
|
)
|
||||||
|
|
||||||
return True, network_data
|
return True, data
|
||||||
|
|
||||||
|
|
||||||
def format_vm_networks(config, name, networks):
|
def format_vm_networks(config, data):
|
||||||
"""
|
"""
|
||||||
Format the output of a network list in a nice table
|
Format the output of a network list in a nice table
|
||||||
"""
|
"""
|
||||||
output_list = []
|
output_list = []
|
||||||
|
|
||||||
name_length = 5
|
network_length = 8
|
||||||
vni_length = 8
|
|
||||||
macaddr_length = 12
|
macaddr_length = 12
|
||||||
model_length = 6
|
model_length = 6
|
||||||
|
|
||||||
_name_length = len(name) + 1
|
for network in data["networks"]:
|
||||||
if _name_length > name_length:
|
_network_length = len(network["network"]) + 1
|
||||||
name_length = _name_length
|
if _network_length > network_length:
|
||||||
|
network_length = _network_length
|
||||||
|
|
||||||
for network in networks:
|
_macaddr_length = len(network["mac_address"]) + 1
|
||||||
_vni_length = len(network[0]) + 1
|
|
||||||
if _vni_length > vni_length:
|
|
||||||
vni_length = _vni_length
|
|
||||||
|
|
||||||
_macaddr_length = len(network[1]) + 1
|
|
||||||
if _macaddr_length > macaddr_length:
|
if _macaddr_length > macaddr_length:
|
||||||
macaddr_length = _macaddr_length
|
macaddr_length = _macaddr_length
|
||||||
|
|
||||||
_model_length = len(network[2]) + 1
|
_model_length = len(network["model"]) + 1
|
||||||
if _model_length > model_length:
|
if _model_length > model_length:
|
||||||
model_length = _model_length
|
model_length = _model_length
|
||||||
|
|
||||||
output_list.append(
|
output_list.append(
|
||||||
"{bold}{name: <{name_length}} \
|
"{bold}{network: <{network_length}} \
|
||||||
{vni: <{vni_length}} \
|
|
||||||
{macaddr: <{macaddr_length}} \
|
{macaddr: <{macaddr_length}} \
|
||||||
{model: <{model_length}}{end_bold}".format(
|
{model: <{model_length}}{end_bold}".format(
|
||||||
name_length=name_length,
|
network_length=network_length,
|
||||||
vni_length=vni_length,
|
|
||||||
macaddr_length=macaddr_length,
|
macaddr_length=macaddr_length,
|
||||||
model_length=model_length,
|
model_length=model_length,
|
||||||
bold=ansiprint.bold(),
|
bold=ansiprint.bold(),
|
||||||
end_bold=ansiprint.end(),
|
end_bold=ansiprint.end(),
|
||||||
name="Name",
|
network="Network",
|
||||||
vni="Network",
|
|
||||||
macaddr="MAC Address",
|
macaddr="MAC Address",
|
||||||
model="Model",
|
model="Model",
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
count = 0
|
count = 0
|
||||||
for network in networks:
|
for network in data["networks"]:
|
||||||
if count > 0:
|
|
||||||
name = ""
|
|
||||||
count += 1
|
count += 1
|
||||||
output_list.append(
|
output_list.append(
|
||||||
"{bold}{name: <{name_length}} \
|
"{bold}{network: <{network_length}} \
|
||||||
{vni: <{vni_length}} \
|
|
||||||
{macaddr: <{macaddr_length}} \
|
{macaddr: <{macaddr_length}} \
|
||||||
{model: <{model_length}}{end_bold}".format(
|
{model: <{model_length}}{end_bold}".format(
|
||||||
name_length=name_length,
|
network_length=network_length,
|
||||||
vni_length=vni_length,
|
|
||||||
macaddr_length=macaddr_length,
|
macaddr_length=macaddr_length,
|
||||||
model_length=model_length,
|
model_length=model_length,
|
||||||
bold="",
|
bold="",
|
||||||
end_bold="",
|
end_bold="",
|
||||||
name=name,
|
network=network["network"],
|
||||||
vni=network[0],
|
macaddr=network["mac_address"],
|
||||||
macaddr=network[1],
|
model=network["model"],
|
||||||
model=network[2],
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
return "\n".join(output_list)
|
return "\n".join(output_list)
|
||||||
@@ -1046,7 +1017,7 @@ def vm_volumes_add(config, vm, volume, disk_id, bus, disk_type, live, restart):
|
|||||||
from lxml.objectify import fromstring
|
from lxml.objectify import fromstring
|
||||||
from lxml.etree import tostring
|
from lxml.etree import tostring
|
||||||
from copy import deepcopy
|
from copy import deepcopy
|
||||||
import pvc.cli_lib.ceph as pvc_ceph
|
import pvc.lib.ceph as pvc_ceph
|
||||||
|
|
||||||
if disk_type == "rbd":
|
if disk_type == "rbd":
|
||||||
# Verify that the provided volume is valid
|
# Verify that the provided volume is valid
|
||||||
@@ -1270,7 +1241,9 @@ def vm_volumes_get(config, vm):
|
|||||||
except Exception:
|
except Exception:
|
||||||
return False, "ERROR: Failed to parse XML data."
|
return False, "ERROR: Failed to parse XML data."
|
||||||
|
|
||||||
volume_data = list()
|
data = dict()
|
||||||
|
data["name"] = vm
|
||||||
|
data["volumes"] = list()
|
||||||
for disk in parsed_xml.devices.find("disk"):
|
for disk in parsed_xml.devices.find("disk"):
|
||||||
protocol = disk.attrib.get("type")
|
protocol = disk.attrib.get("type")
|
||||||
disk_id = disk.target.attrib.get("dev")
|
disk_id = disk.target.attrib.get("dev")
|
||||||
@@ -1285,58 +1258,52 @@ def vm_volumes_get(config, vm):
|
|||||||
protocol = "unknown"
|
protocol = "unknown"
|
||||||
source = "unknown"
|
source = "unknown"
|
||||||
|
|
||||||
volume_data.append((source, disk_id, protocol, bus))
|
data["volumes"].append(
|
||||||
|
{"volume": source, "disk_id": disk_id, "protocol": protocol, "bus": bus}
|
||||||
|
)
|
||||||
|
|
||||||
return True, volume_data
|
return True, data
|
||||||
|
|
||||||
|
|
||||||
def format_vm_volumes(config, name, volumes):
|
def format_vm_volumes(config, data):
|
||||||
"""
|
"""
|
||||||
Format the output of a volume value in a nice table
|
Format the output of a volume value in a nice table
|
||||||
"""
|
"""
|
||||||
output_list = []
|
output_list = []
|
||||||
|
|
||||||
name_length = 5
|
|
||||||
volume_length = 7
|
volume_length = 7
|
||||||
disk_id_length = 4
|
disk_id_length = 4
|
||||||
protocol_length = 5
|
protocol_length = 5
|
||||||
bus_length = 4
|
bus_length = 4
|
||||||
|
|
||||||
_name_length = len(name) + 1
|
for volume in data["volumes"]:
|
||||||
if _name_length > name_length:
|
_volume_length = len(volume["volume"]) + 1
|
||||||
name_length = _name_length
|
|
||||||
|
|
||||||
for volume in volumes:
|
|
||||||
_volume_length = len(volume[0]) + 1
|
|
||||||
if _volume_length > volume_length:
|
if _volume_length > volume_length:
|
||||||
volume_length = _volume_length
|
volume_length = _volume_length
|
||||||
|
|
||||||
_disk_id_length = len(volume[1]) + 1
|
_disk_id_length = len(volume["disk_id"]) + 1
|
||||||
if _disk_id_length > disk_id_length:
|
if _disk_id_length > disk_id_length:
|
||||||
disk_id_length = _disk_id_length
|
disk_id_length = _disk_id_length
|
||||||
|
|
||||||
_protocol_length = len(volume[2]) + 1
|
_protocol_length = len(volume["protocol"]) + 1
|
||||||
if _protocol_length > protocol_length:
|
if _protocol_length > protocol_length:
|
||||||
protocol_length = _protocol_length
|
protocol_length = _protocol_length
|
||||||
|
|
||||||
_bus_length = len(volume[3]) + 1
|
_bus_length = len(volume["bus"]) + 1
|
||||||
if _bus_length > bus_length:
|
if _bus_length > bus_length:
|
||||||
bus_length = _bus_length
|
bus_length = _bus_length
|
||||||
|
|
||||||
output_list.append(
|
output_list.append(
|
||||||
"{bold}{name: <{name_length}} \
|
"{bold}{volume: <{volume_length}} \
|
||||||
{volume: <{volume_length}} \
|
|
||||||
{disk_id: <{disk_id_length}} \
|
{disk_id: <{disk_id_length}} \
|
||||||
{protocol: <{protocol_length}} \
|
{protocol: <{protocol_length}} \
|
||||||
{bus: <{bus_length}}{end_bold}".format(
|
{bus: <{bus_length}}{end_bold}".format(
|
||||||
name_length=name_length,
|
|
||||||
volume_length=volume_length,
|
volume_length=volume_length,
|
||||||
disk_id_length=disk_id_length,
|
disk_id_length=disk_id_length,
|
||||||
protocol_length=protocol_length,
|
protocol_length=protocol_length,
|
||||||
bus_length=bus_length,
|
bus_length=bus_length,
|
||||||
bold=ansiprint.bold(),
|
bold=ansiprint.bold(),
|
||||||
end_bold=ansiprint.end(),
|
end_bold=ansiprint.end(),
|
||||||
name="Name",
|
|
||||||
volume="Volume",
|
volume="Volume",
|
||||||
disk_id="Dev",
|
disk_id="Dev",
|
||||||
protocol="Type",
|
protocol="Type",
|
||||||
@@ -1344,28 +1311,23 @@ def format_vm_volumes(config, name, volumes):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
count = 0
|
count = 0
|
||||||
for volume in volumes:
|
for volume in data["volumes"]:
|
||||||
if count > 0:
|
|
||||||
name = ""
|
|
||||||
count += 1
|
count += 1
|
||||||
output_list.append(
|
output_list.append(
|
||||||
"{bold}{name: <{name_length}} \
|
"{bold}{volume: <{volume_length}} \
|
||||||
{volume: <{volume_length}} \
|
|
||||||
{disk_id: <{disk_id_length}} \
|
{disk_id: <{disk_id_length}} \
|
||||||
{protocol: <{protocol_length}} \
|
{protocol: <{protocol_length}} \
|
||||||
{bus: <{bus_length}}{end_bold}".format(
|
{bus: <{bus_length}}{end_bold}".format(
|
||||||
name_length=name_length,
|
|
||||||
volume_length=volume_length,
|
volume_length=volume_length,
|
||||||
disk_id_length=disk_id_length,
|
disk_id_length=disk_id_length,
|
||||||
protocol_length=protocol_length,
|
protocol_length=protocol_length,
|
||||||
bus_length=bus_length,
|
bus_length=bus_length,
|
||||||
bold="",
|
bold="",
|
||||||
end_bold="",
|
end_bold="",
|
||||||
name=name,
|
volume=volume["volume"],
|
||||||
volume=volume[0],
|
disk_id=volume["disk_id"],
|
||||||
disk_id=volume[1],
|
protocol=volume["protocol"],
|
||||||
protocol=volume[2],
|
bus=volume["bus"],
|
||||||
bus=volume[3],
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
return "\n".join(output_list)
|
return "\n".join(output_list)
|
||||||
@@ -1869,7 +1831,7 @@ def format_info(config, domain_information, long_output):
|
|||||||
return "\n".join(ainformation)
|
return "\n".join(ainformation)
|
||||||
|
|
||||||
|
|
||||||
def format_list(config, vm_list, raw):
|
def format_list(config, vm_list):
|
||||||
# Function to strip the "br" off of nets and return a nicer list
|
# Function to strip the "br" off of nets and return a nicer list
|
||||||
def getNiceNetID(domain_information):
|
def getNiceNetID(domain_information):
|
||||||
# Network list
|
# Network list
|
||||||
@@ -1888,13 +1850,6 @@ def format_list(config, vm_list, raw):
|
|||||||
tag_list.append(tag["name"])
|
tag_list.append(tag["name"])
|
||||||
return tag_list
|
return tag_list
|
||||||
|
|
||||||
# Handle raw mode since it just lists the names
|
|
||||||
if raw:
|
|
||||||
ainformation = list()
|
|
||||||
for vm in sorted(item["name"] for item in vm_list):
|
|
||||||
ainformation.append(vm)
|
|
||||||
return "\n".join(ainformation)
|
|
||||||
|
|
||||||
vm_list_output = []
|
vm_list_output = []
|
||||||
|
|
||||||
# Determine optimal column widths
|
# Determine optimal column widths
|
||||||
|
|||||||
Reference in New Issue
Block a user