2021-06-23 05:26:50 -04:00
#!/usr/bin/env python3
2019-12-25 13:35:31 -05:00
# pvc.py - PVC client command-line interface
2018-06-06 01:47:53 -04:00
# Part of the Parallel Virtual Cluster (PVC) system
#
2022-10-06 11:55:27 -04:00
# Copyright (C) 2018-2022 Joshua M. Boniface <joshua@boniface.me>
2018-06-06 01:47:53 -04:00
#
# 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
2021-03-25 16:57:17 -04:00
# the Free Software Foundation, version 3.
2018-06-06 01:47:53 -04:00
#
# 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/>.
#
###############################################################################
2018-06-14 12:07:46 -04:00
import socket
import click
2018-09-25 02:32:08 -04:00
import os
import difflib
import re
2020-01-08 14:41:19 -05:00
import time
2018-09-25 02:32:08 -04:00
import colorama
2019-03-12 22:55:29 -04:00
import yaml
2019-12-30 13:27:40 -05:00
import json
2021-12-10 16:17:33 -05:00
import syslog
2019-12-27 09:52:16 -05:00
import lxml . etree as etree
2019-12-25 13:35:31 -05:00
2021-12-10 16:17:33 -05:00
from sys import argv
2019-12-30 13:27:40 -05:00
from distutils . util import strtobool
2020-06-05 14:49:53 -04:00
from functools import wraps
2021-06-23 04:08:02 -04:00
import pvc . cli_lib . ansiprint as ansiprint
import pvc . cli_lib . cluster as pvc_cluster
import pvc . cli_lib . node as pvc_node
import pvc . cli_lib . vm as pvc_vm
import pvc . cli_lib . network as pvc_network
import pvc . cli_lib . ceph as pvc_ceph
import pvc . cli_lib . provisioner as pvc_provisioner
2018-06-05 01:39:59 -04:00
2021-11-08 00:04:20 -05:00
2021-11-06 03:02:43 -04:00
myhostname = socket . gethostname ( ) . split ( " . " ) [ 0 ]
zk_host = " "
is_completion = True if os . environ . get ( " _PVC_COMPLETE " , " " ) == " complete " else False
2018-06-14 11:57:36 -04:00
2021-11-06 03:02:43 -04:00
default_store_data = { " cfgfile " : " /etc/pvc/pvcapid.yaml " }
2021-11-08 00:04:20 -05:00
config = dict ( )
2019-12-30 13:27:40 -05:00
2020-11-07 14:45:24 -05:00
2021-12-10 16:17:33 -05:00
#
# Audit function
#
def audit ( ) :
args = argv
args [ 0 ] = " pvc "
syslog . openlog ( facility = syslog . LOG_AUTH )
syslog . syslog (
' client audit: command " {} " by user " {} " ' . format (
" " . join ( args ) ,
os . environ . get ( " USER " , None ) ,
)
)
syslog . closelog ( )
2021-10-11 15:34:41 -04:00
#
# Version function
#
def print_version ( ctx , param , value ) :
if not value or ctx . resilient_parsing :
return
from pkg_resources import get_distribution
2021-11-06 03:02:43 -04:00
version = get_distribution ( " pvc " ) . version
2021-11-08 00:04:20 -05:00
echo ( f " Parallel Virtual Cluster version { version } " )
2021-10-11 15:34:41 -04:00
ctx . exit ( )
2019-12-30 13:27:40 -05:00
#
# Data store handling functions
#
def read_from_yaml ( cfgfile ) :
2021-11-06 03:02:43 -04:00
with open ( cfgfile , " r " ) as fh :
2019-12-30 13:27:40 -05:00
api_config = yaml . load ( fh , Loader = yaml . BaseLoader )
2021-11-06 03:02:43 -04:00
host = api_config [ " pvc " ] [ " api " ] [ " listen_address " ]
port = api_config [ " pvc " ] [ " api " ] [ " listen_port " ]
if strtobool ( api_config [ " pvc " ] [ " api " ] [ " ssl " ] [ " enabled " ] ) :
scheme = " https "
2019-12-30 13:27:40 -05:00
else :
2021-11-06 03:02:43 -04:00
scheme = " http "
if strtobool ( api_config [ " pvc " ] [ " api " ] [ " authentication " ] [ " enabled " ] ) :
2020-01-08 18:36:31 -05:00
# Always use the first token
2021-11-06 03:02:43 -04:00
api_key = api_config [ " pvc " ] [ " api " ] [ " authentication " ] [ " tokens " ] [ 0 ] [ " token " ]
2020-01-08 18:36:31 -05:00
else :
2021-11-06 03:02:43 -04:00
api_key = " N/A "
2021-04-08 12:09:51 -04:00
return cfgfile , host , port , scheme , api_key
2019-12-30 13:29:07 -05:00
2020-11-07 14:45:24 -05:00
2019-12-30 13:27:40 -05:00
def get_config ( store_data , cluster = None ) :
# This is generally static
2021-11-06 03:02:43 -04:00
prefix = " /api/v1 "
2019-12-30 13:27:40 -05:00
cluster_details = store_data . get ( cluster )
if not cluster_details :
cluster_details = default_store_data
2021-11-06 03:02:43 -04:00
cluster = " local "
2019-12-30 13:27:40 -05:00
2021-11-06 03:02:43 -04:00
if cluster_details . get ( " cfgfile " , None ) :
2019-12-30 13:27:40 -05:00
# This is a reference to an API configuration; grab the details from its listen address
2021-11-06 03:02:43 -04:00
cfgfile = cluster_details . get ( " cfgfile " )
2019-12-30 13:27:40 -05:00
if os . path . isfile ( cfgfile ) :
2021-04-08 12:09:51 -04:00
description , host , port , scheme , api_key = read_from_yaml ( cfgfile )
2019-12-30 13:27:40 -05:00
else :
2021-11-06 03:02:43 -04:00
return { " badcfg " : True }
2020-02-16 20:01:24 -05:00
# Handle an all-wildcard address
2021-11-06 03:02:43 -04:00
if host == " 0.0.0.0 " :
host = " 127.0.0.1 "
2019-12-30 13:27:40 -05:00
else :
# This is a static configuration, get the raw details
2021-11-06 03:02:43 -04:00
description = cluster_details [ " description " ]
host = cluster_details [ " host " ]
port = cluster_details [ " port " ]
scheme = cluster_details [ " scheme " ]
api_key = cluster_details [ " api_key " ]
2019-12-30 13:27:40 -05:00
config = dict ( )
2021-11-06 03:02:43 -04:00
config [ " debug " ] = False
config [ " cluster " ] = cluster
config [ " desctription " ] = description
config [ " api_host " ] = " {} : {} " . format ( host , port )
config [ " api_scheme " ] = scheme
config [ " api_key " ] = api_key
config [ " api_prefix " ] = prefix
if cluster == " local " :
config [ " verify_ssl " ] = False
2020-08-27 13:23:24 -04:00
else :
2021-11-06 03:02:43 -04:00
config [ " verify_ssl " ] = bool (
strtobool ( os . environ . get ( " PVC_CLIENT_VERIFY_SSL " , " True " ) )
)
2019-12-30 13:27:40 -05:00
return config
2020-11-07 14:45:24 -05:00
2019-12-30 13:27:40 -05:00
def get_store ( store_path ) :
2021-11-06 03:02:43 -04:00
store_file = " {} /pvc-cli.json " . format ( store_path )
with open ( store_file , " r " ) as fh :
2020-11-06 19:26:22 -05:00
store_data = json . loads ( fh . read ( ) )
2019-12-30 13:27:40 -05:00
return store_data
2020-11-07 14:45:24 -05:00
2019-12-30 13:27:40 -05:00
def update_store ( store_path , store_data ) :
2021-11-06 03:02:43 -04:00
store_file = " {} /pvc-cli.json " . format ( store_path )
2020-08-27 13:14:55 -04:00
if not os . path . exists ( store_file ) :
2021-11-06 03:02:43 -04:00
with open ( store_file , " w " ) as fh :
2020-08-27 13:14:55 -04:00
fh . write ( json . dumps ( store_data , sort_keys = True , indent = 4 ) )
# Ensure file has sensible permissions due to API key storage, but only when created!
2021-11-06 03:02:43 -04:00
os . chmod ( store_file , int ( os . environ . get ( " PVC_CLIENT_DB_PERMS " , " 600 " ) , 8 ) )
2020-08-27 13:14:55 -04:00
else :
2021-11-06 03:02:43 -04:00
with open ( store_file , " w " ) as fh :
2020-08-27 13:14:55 -04:00
fh . write ( json . dumps ( store_data , sort_keys = True , indent = 4 ) )
2019-12-30 13:27:40 -05:00
2020-11-07 13:17:49 -05:00
2021-06-23 05:26:50 -04:00
if not is_completion :
2021-11-06 03:02:43 -04:00
pvc_client_dir = os . environ . get ( " PVC_CLIENT_DIR " , None )
home_dir = os . environ . get ( " HOME " , None )
2021-06-23 05:26:50 -04:00
if pvc_client_dir :
2021-11-06 03:02:43 -04:00
store_path = " {} " . format ( pvc_client_dir )
2021-06-23 05:26:50 -04:00
elif home_dir :
2021-11-06 03:02:43 -04:00
store_path = " {} /.config/pvc " . format ( home_dir )
2021-06-23 05:26:50 -04:00
else :
2021-11-06 03:02:43 -04:00
print ( " WARNING: No client or home config dir found, using /tmp instead " )
store_path = " /tmp/pvc "
2021-06-23 05:26:50 -04:00
if not os . path . isdir ( store_path ) :
os . makedirs ( store_path )
2021-11-06 03:02:43 -04:00
if not os . path . isfile ( store_path + " /pvc-cli.json " ) :
2021-06-23 05:26:50 -04:00
update_store ( store_path , { " local " : default_store_data } )
2019-12-25 19:52:15 -05:00
2021-11-06 03:02:43 -04:00
CONTEXT_SETTINGS = dict ( help_option_names = [ " -h " , " --help " ] , max_content_width = 120 )
2018-06-11 01:35:50 -04:00
2020-11-07 14:45:24 -05:00
2021-11-08 00:04:20 -05:00
def echo ( msg , nl = True , err = False ) :
if config . get ( " colour " , False ) :
colour = True
else :
colour = None
click . echo ( message = msg , color = colour , nl = nl , err = err )
2019-12-25 19:52:15 -05:00
def cleanup ( retcode , retmsg ) :
2021-11-06 03:02:43 -04:00
if retmsg != " " :
2021-11-08 00:04:20 -05:00
echo ( retmsg )
2020-11-06 19:35:19 -05:00
if retcode is True :
2018-09-20 03:25:58 -04:00
exit ( 0 )
else :
exit ( 1 )
2020-11-07 14:45:24 -05:00
2019-12-30 13:27:40 -05:00
###############################################################################
# pvc cluster
###############################################################################
2021-11-06 03:02:43 -04:00
@click.group (
name = " cluster " ,
short_help = " Manage PVC cluster connections. " ,
context_settings = CONTEXT_SETTINGS ,
)
2019-12-30 13:27:40 -05:00
def cli_cluster ( ) :
"""
Manage the PVC clusters this CLI can connect to .
"""
pass
2020-11-07 14:45:24 -05:00
2019-12-30 13:27:40 -05:00
###############################################################################
# pvc cluster add
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " add " , short_help = " Add a new cluster to the client. " )
2021-04-08 12:09:51 -04:00
@click.option (
2021-11-06 03:02:43 -04:00
" -d " ,
" --description " ,
" description " ,
required = False ,
default = " N/A " ,
help = " A text description of the cluster. " ,
2021-04-08 12:09:51 -04:00
)
2019-12-30 13:27:40 -05:00
@click.option (
2021-11-06 03:02:43 -04:00
" -a " ,
" --address " ,
" address " ,
required = True ,
help = " The IP address or hostname of the cluster API client. " ,
2019-12-30 13:27:40 -05:00
)
@click.option (
2021-11-06 03:02:43 -04:00
" -p " ,
" --port " ,
" port " ,
required = False ,
default = 7370 ,
show_default = True ,
help = " The cluster API client port. " ,
2019-12-30 13:27:40 -05:00
)
@click.option (
2021-11-06 03:02:43 -04:00
" -s/-S " ,
" --ssl/--no-ssl " ,
" ssl " ,
is_flag = True ,
default = False ,
show_default = True ,
help = " Whether to use SSL or not. " ,
2019-12-30 13:27:40 -05:00
)
2020-01-08 18:36:31 -05:00
@click.option (
2021-11-06 03:02:43 -04:00
" -k " ,
" --api-key " ,
" api_key " ,
required = False ,
default = None ,
help = " An API key to authenticate against the cluster. " ,
2019-12-30 13:27:40 -05:00
)
2021-11-06 03:02:43 -04:00
@click.argument ( " name " )
2021-04-08 12:09:51 -04:00
def cluster_add ( description , address , port , ssl , name , api_key ) :
2019-12-30 13:27:40 -05:00
"""
Add a new PVC cluster NAME , via its API connection details , to the configuration of the local CLI client . Replaces any existing cluster with this name .
"""
if ssl :
2021-11-06 03:02:43 -04:00
scheme = " https "
2019-12-30 13:27:40 -05:00
else :
2021-11-06 03:02:43 -04:00
scheme = " http "
2019-12-30 13:27:40 -05:00
# Get the existing data
existing_config = get_store ( store_path )
# Append our new entry to the end
existing_config [ name ] = {
2021-11-06 03:02:43 -04:00
" description " : description ,
" host " : address ,
" port " : port ,
" scheme " : scheme ,
" api_key " : api_key ,
2019-12-30 13:27:40 -05:00
}
# Update the store
update_store ( store_path , existing_config )
2021-11-08 00:04:20 -05:00
echo ( ' Added new cluster " {} " at host " {} " to local database ' . format ( name , address ) )
2019-12-30 13:27:40 -05:00
2020-11-07 14:45:24 -05:00
2019-12-30 13:27:40 -05:00
###############################################################################
# pvc cluster remove
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " remove " , short_help = " Remove a cluster from the client. " )
@click.argument ( " name " )
2019-12-30 13:27:40 -05:00
def cluster_remove ( name ) :
"""
Remove a PVC cluster from the configuration of the local CLI client .
"""
# Get the existing data
existing_config = get_store ( store_path )
# Remove the entry matching the name
try :
existing_config . pop ( name )
except KeyError :
print ( ' No cluster with name " {} " found ' . format ( name ) )
# Update the store
update_store ( store_path , existing_config )
2021-11-08 00:04:20 -05:00
echo ( ' Removed cluster " {} " from local database ' . format ( name ) )
2019-12-30 13:27:40 -05:00
2020-11-07 14:45:24 -05:00
2019-12-30 13:27:40 -05:00
###############################################################################
# pvc cluster list
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " list " , short_help = " List all available clusters. " )
2021-07-09 10:53:20 -04:00
@click.option (
2021-11-06 03:02:43 -04:00
" -r " ,
" --raw " ,
" raw " ,
is_flag = True ,
default = False ,
help = " Display the raw list of cluster names only. " ,
2021-07-09 10:53:20 -04:00
)
def cluster_list ( raw ) :
2019-12-30 13:27:40 -05:00
"""
List all the available PVC clusters configured in this CLI instance .
"""
# Get the existing data
clusters = get_store ( store_path )
# Find the lengths of each column
name_length = 5
2021-04-08 12:09:51 -04:00
description_length = 12
2019-12-30 13:27:40 -05:00
address_length = 10
port_length = 5
2020-01-08 18:36:31 -05:00
scheme_length = 7
2021-04-08 12:09:51 -04:00
api_key_length = 32
2019-12-30 13:27:40 -05:00
for cluster in clusters :
cluster_details = clusters [ cluster ]
2021-11-06 03:02:43 -04:00
if cluster_details . get ( " cfgfile " , None ) :
2019-12-30 13:27:40 -05:00
# This is a reference to an API configuration; grab the details from its listen address
2021-11-06 03:02:43 -04:00
cfgfile = cluster_details . get ( " cfgfile " )
2019-12-30 13:27:40 -05:00
if os . path . isfile ( cfgfile ) :
2021-04-08 12:09:51 -04:00
description , address , port , scheme , api_key = read_from_yaml ( cfgfile )
2020-01-02 12:18:41 -05:00
else :
2021-11-06 03:02:43 -04:00
description , address , port , scheme , api_key = (
" N/A " ,
" N/A " ,
" N/A " ,
" N/A " ,
" N/A " ,
)
2019-12-30 13:27:40 -05:00
else :
2021-11-06 03:02:43 -04:00
description = cluster_details . get ( " description " , " " )
address = cluster_details . get ( " host " , " N/A " )
port = cluster_details . get ( " port " , " N/A " )
scheme = cluster_details . get ( " scheme " , " N/A " )
api_key = cluster_details . get ( " api_key " , " N/A " )
2020-01-08 18:36:31 -05:00
if not api_key :
2021-11-06 03:02:43 -04:00
api_key = " N/A "
2019-12-30 13:27:40 -05:00
_name_length = len ( cluster ) + 1
if _name_length > name_length :
name_length = _name_length
_address_length = len ( address ) + 1
2021-04-08 12:09:51 -04:00
_description_length = len ( description ) + 1
if _description_length > description_length :
description_length = _description_length
2019-12-30 13:27:40 -05:00
if _address_length > address_length :
address_length = _address_length
_port_length = len ( str ( port ) ) + 1
if _port_length > port_length :
port_length = _port_length
_scheme_length = len ( scheme ) + 1
if _scheme_length > scheme_length :
scheme_length = _scheme_length
2020-01-08 18:36:31 -05:00
_api_key_length = len ( api_key ) + 1
if _api_key_length > api_key_length :
api_key_length = _api_key_length
2019-12-30 13:27:40 -05:00
2021-07-09 10:53:20 -04:00
if not raw :
# Display the data nicely
2021-11-08 00:04:20 -05:00
echo ( " Available clusters: " )
2021-11-25 09:33:26 -05:00
echo ( " " )
2021-11-08 00:04:20 -05:00
echo (
2021-11-06 03:02:43 -04:00
" {bold} { name: < {name_length} } { description: < {description_length} } { address: < {address_length} } { port: < {port_length} } { scheme: < {scheme_length} } { api_key: < {api_key_length} } {end_bold} " . format (
2021-07-09 10:53:20 -04:00
bold = ansiprint . bold ( ) ,
end_bold = ansiprint . end ( ) ,
name = " Name " ,
name_length = name_length ,
description = " Description " ,
description_length = description_length ,
address = " Address " ,
address_length = address_length ,
port = " Port " ,
port_length = port_length ,
scheme = " Scheme " ,
scheme_length = scheme_length ,
api_key = " API Key " ,
2021-11-06 03:02:43 -04:00
api_key_length = api_key_length ,
2021-07-09 10:53:20 -04:00
)
2019-12-30 13:27:40 -05:00
)
for cluster in clusters :
cluster_details = clusters [ cluster ]
2021-11-06 03:02:43 -04:00
if cluster_details . get ( " cfgfile " , None ) :
2019-12-30 13:27:40 -05:00
# This is a reference to an API configuration; grab the details from its listen address
if os . path . isfile ( cfgfile ) :
2021-04-08 12:09:51 -04:00
description , address , port , scheme , api_key = read_from_yaml ( cfgfile )
2020-01-06 09:18:22 -05:00
else :
2021-04-13 10:01:49 -04:00
continue
2019-12-30 13:27:40 -05:00
else :
2021-11-06 03:02:43 -04:00
address = cluster_details . get ( " host " , " N/A " )
description = cluster_details . get ( " description " , " N/A " )
port = cluster_details . get ( " port " , " N/A " )
scheme = cluster_details . get ( " scheme " , " N/A " )
api_key = cluster_details . get ( " api_key " , " N/A " )
2020-01-08 18:36:31 -05:00
if not api_key :
2021-11-06 03:02:43 -04:00
api_key = " N/A "
2019-12-30 13:27:40 -05:00
2021-07-09 10:53:20 -04:00
if not raw :
2021-11-08 00:04:20 -05:00
echo (
2021-11-06 03:02:43 -04:00
" {bold} { name: < {name_length} } { description: < {description_length} } { address: < {address_length} } { port: < {port_length} } { scheme: < {scheme_length} } { api_key: < {api_key_length} } {end_bold} " . format (
bold = " " ,
end_bold = " " ,
2021-07-09 10:53:20 -04:00
name = cluster ,
name_length = name_length ,
description = description ,
description_length = description_length ,
address = address ,
address_length = address_length ,
port = port ,
port_length = port_length ,
scheme = scheme ,
scheme_length = scheme_length ,
api_key = api_key ,
2021-11-06 03:02:43 -04:00
api_key_length = api_key_length ,
2021-07-09 10:53:20 -04:00
)
2019-12-30 13:27:40 -05:00
)
2021-07-09 10:53:20 -04:00
else :
2021-11-08 00:04:20 -05:00
echo ( cluster )
2019-12-30 13:29:07 -05:00
2020-11-07 14:45:24 -05:00
2020-06-05 14:49:53 -04:00
# Validate that the cluster is set for a given command
def cluster_req ( function ) :
@wraps ( function )
def validate_cluster ( * args , * * kwargs ) :
2021-11-06 03:02:43 -04:00
if config . get ( " badcfg " , None ) :
2021-11-08 00:04:20 -05:00
echo (
2021-11-06 03:02:43 -04:00
' No cluster specified and no local pvcapid.yaml configuration found. Use " pvc cluster " to add a cluster API to connect to. '
)
2020-06-05 14:49:53 -04:00
exit ( 1 )
2020-06-05 15:50:43 -04:00
return function ( * args , * * kwargs )
2021-11-06 03:02:43 -04:00
2020-06-05 14:49:53 -04:00
return validate_cluster
2019-12-30 13:27:40 -05:00
2018-06-05 01:39:59 -04:00
###############################################################################
# pvc node
###############################################################################
2021-11-06 03:02:43 -04:00
@click.group (
name = " node " , short_help = " Manage a PVC node. " , context_settings = CONTEXT_SETTINGS
)
2018-09-20 03:25:58 -04:00
def cli_node ( ) :
2018-06-05 01:39:59 -04:00
"""
Manage the state of a node in the PVC cluster .
"""
2020-11-07 14:45:24 -05:00
pass
2018-06-05 01:39:59 -04:00
2018-10-14 02:01:35 -04:00
###############################################################################
# pvc node secondary
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " secondary " , short_help = " Set a node in secondary node status. " )
@click.argument ( " node " )
2020-02-19 14:33:31 -05:00
@click.option (
2021-11-06 03:02:43 -04:00
" -w " ,
" --wait " ,
" wait " ,
is_flag = True ,
default = False ,
help = " Wait for transition to complete before returning. " ,
2020-02-19 14:33:31 -05:00
)
2020-06-05 14:49:53 -04:00
@cluster_req
2020-02-19 14:33:31 -05:00
def node_secondary ( node , wait ) :
2018-10-14 02:01:35 -04:00
"""
2022-05-06 15:39:06 -04:00
Take NODE out of primary coordinator mode .
2018-10-14 02:01:35 -04:00
"""
2019-12-30 13:29:07 -05:00
2020-01-12 16:00:49 -05:00
task_retcode , task_retdata = pvc_provisioner . task_status ( config , None )
if len ( task_retdata ) > 0 :
2021-11-08 00:04:20 -05:00
echo (
2021-11-06 03:02:43 -04:00
" Note: There are currently {} active or queued provisioner jobs on the current primary node. " . format (
len ( task_retdata )
)
)
2021-11-08 00:04:20 -05:00
echo (
2021-11-06 03:02:43 -04:00
" These jobs will continue executing, but status will not be visible until the current "
)
2021-11-08 00:04:20 -05:00
echo ( " node returns to primary state. " )
2021-11-25 09:33:26 -05:00
echo ( " " )
2020-01-12 16:00:49 -05:00
2021-11-06 03:02:43 -04:00
retcode , retmsg = pvc_node . node_coordinator_state ( config , node , " secondary " )
2020-02-19 14:33:31 -05:00
if not retcode :
cleanup ( retcode , retmsg )
else :
2020-02-19 16:22:29 -05:00
if wait :
2021-11-08 00:04:20 -05:00
echo ( retmsg )
echo ( " Waiting for state transition... " , nl = False )
2020-02-19 16:22:29 -05:00
# Every half-second, check if the API is reachable and the node is in secondary state
while True :
try :
_retcode , _retmsg = pvc_node . node_info ( config , node )
2021-11-06 03:02:43 -04:00
if _retmsg [ " coordinator_state " ] == " secondary " :
2020-02-19 16:22:29 -05:00
retmsg = " done. "
break
else :
time . sleep ( 0.5 )
2020-11-06 18:55:10 -05:00
except Exception :
2020-02-19 14:33:31 -05:00
time . sleep ( 0.5 )
2020-02-19 16:22:29 -05:00
cleanup ( retcode , retmsg )
2018-10-14 02:01:35 -04:00
2020-11-07 14:45:24 -05:00
2018-10-14 02:01:35 -04:00
###############################################################################
# pvc node primary
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " primary " , short_help = " Set a node in primary status. " )
@click.argument ( " node " )
2020-02-19 14:33:31 -05:00
@click.option (
2021-11-06 03:02:43 -04:00
" -w " ,
" --wait " ,
" wait " ,
is_flag = True ,
default = False ,
help = " Wait for transition to complete before returning. " ,
2020-02-19 14:33:31 -05:00
)
2020-06-05 14:49:53 -04:00
@cluster_req
2020-02-19 14:33:31 -05:00
def node_primary ( node , wait ) :
2018-10-14 02:01:35 -04:00
"""
2022-05-06 15:39:06 -04:00
Put NODE into primary coordinator mode .
2018-10-14 02:01:35 -04:00
"""
2020-01-12 16:00:49 -05:00
task_retcode , task_retdata = pvc_provisioner . task_status ( config , None )
if len ( task_retdata ) > 0 :
2021-11-08 00:04:20 -05:00
echo (
2021-11-06 03:02:43 -04:00
" Note: There are currently {} active or queued provisioner jobs on the current primary node. " . format (
len ( task_retdata )
)
)
2021-11-08 00:04:20 -05:00
echo (
2021-11-06 03:02:43 -04:00
" These jobs will continue executing, but status will not be visible until the current "
)
2021-11-08 00:04:20 -05:00
echo ( " node returns to primary state. " )
2021-11-25 09:33:26 -05:00
echo ( " " )
2020-01-12 16:00:49 -05:00
2021-11-06 03:02:43 -04:00
retcode , retmsg = pvc_node . node_coordinator_state ( config , node , " primary " )
2020-02-19 14:33:31 -05:00
if not retcode :
cleanup ( retcode , retmsg )
else :
2020-02-19 16:22:29 -05:00
if wait :
2021-11-08 00:04:20 -05:00
echo ( retmsg )
echo ( " Waiting for state transition... " , nl = False )
2020-02-19 16:22:29 -05:00
# Every half-second, check if the API is reachable and the node is in secondary state
while True :
try :
_retcode , _retmsg = pvc_node . node_info ( config , node )
2021-11-06 03:02:43 -04:00
if _retmsg [ " coordinator_state " ] == " primary " :
2020-02-19 16:22:29 -05:00
retmsg = " done. "
break
else :
time . sleep ( 0.5 )
2020-11-06 18:55:10 -05:00
except Exception :
2020-02-19 14:33:31 -05:00
time . sleep ( 0.5 )
2020-02-19 16:22:29 -05:00
cleanup ( retcode , retmsg )
2018-06-05 01:39:59 -04:00
2020-11-07 14:45:24 -05:00
2018-06-05 01:39:59 -04:00
###############################################################################
# pvc node flush
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " flush " , short_help = " Take a node out of service. " )
2018-07-17 01:48:15 -04:00
@click.option (
2021-11-06 03:02:43 -04:00
" -w " ,
" --wait " ,
" wait " ,
is_flag = True ,
default = False ,
help = " Wait for migrations to complete before returning. " ,
2018-06-06 20:49:07 -04:00
)
2021-11-06 03:02:43 -04:00
@click.argument ( " node " , default = myhostname )
2020-06-05 14:49:53 -04:00
@cluster_req
2018-09-20 03:25:58 -04:00
def node_flush ( node , wait ) :
2018-06-05 01:39:59 -04:00
"""
2018-06-16 22:22:07 -04:00
Take NODE out of active service and migrate away all VMs . If unspecified , defaults to this host .
2018-06-05 01:39:59 -04:00
"""
2019-12-30 13:29:07 -05:00
2021-11-06 03:02:43 -04:00
retcode , retmsg = pvc_node . node_domain_state ( config , node , " flush " , wait )
2019-12-25 20:18:53 -05:00
cleanup ( retcode , retmsg )
2018-06-05 01:39:59 -04:00
2020-11-07 14:45:24 -05:00
2018-06-05 01:39:59 -04:00
###############################################################################
2018-06-26 23:46:03 -04:00
# pvc node ready/unflush
2018-06-05 01:39:59 -04:00
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " ready " , short_help = " Restore node to service. " )
@click.argument ( " node " , default = myhostname )
2019-05-11 00:16:38 -04:00
@click.option (
2021-11-06 03:02:43 -04:00
" -w " ,
" --wait " ,
" wait " ,
is_flag = True ,
default = False ,
help = " Wait for migrations to complete before returning. " ,
2019-05-11 00:16:38 -04:00
)
2020-06-05 14:49:53 -04:00
@cluster_req
2019-05-11 00:16:38 -04:00
def node_ready ( node , wait ) :
2018-07-18 22:58:41 -04:00
"""
Restore NODE to active service and migrate back all VMs . If unspecified , defaults to this host .
"""
2021-11-06 03:02:43 -04:00
retcode , retmsg = pvc_node . node_domain_state ( config , node , " ready " , wait )
2019-12-25 20:18:53 -05:00
cleanup ( retcode , retmsg )
2018-06-26 23:46:03 -04:00
2020-11-07 14:45:24 -05:00
2021-11-06 03:02:43 -04:00
@click.command ( name = " unflush " , short_help = " Restore node to service. " )
@click.argument ( " node " , default = myhostname )
2019-05-11 00:16:38 -04:00
@click.option (
2021-11-06 03:02:43 -04:00
" -w " ,
" --wait " ,
" wait " ,
is_flag = True ,
default = False ,
help = " Wait for migrations to complete before returning. " ,
2019-05-11 00:16:38 -04:00
)
def node_unflush ( node , wait ) :
2018-07-18 22:58:41 -04:00
"""
Restore NODE to active service and migrate back all VMs . If unspecified , defaults to this host .
"""
2021-11-06 03:02:43 -04:00
retcode , retmsg = pvc_node . node_domain_state ( config , node , " ready " , wait )
2019-12-25 20:18:53 -05:00
cleanup ( retcode , retmsg )
2018-06-05 01:39:59 -04:00
2020-11-07 14:45:24 -05:00
2021-07-18 17:37:49 -04:00
###############################################################################
# pvc node log
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " log " , short_help = " Show logs of a node. " )
@click.argument ( " node " )
2021-07-18 17:37:49 -04:00
@click.option (
2021-11-06 03:02:43 -04:00
" -l " ,
" --lines " ,
" lines " ,
default = None ,
show_default = False ,
help = " Display this many log lines from the end of the log buffer. [default: 1000; with follow: 10] " ,
2021-07-18 17:37:49 -04:00
)
@click.option (
2021-11-06 03:02:43 -04:00
" -f " ,
" --follow " ,
" follow " ,
is_flag = True ,
default = False ,
help = " Follow the log buffer; output may be delayed by a few seconds relative to the live system. The --lines value defaults to 10 for the initial output. " ,
2021-07-18 17:37:49 -04:00
)
@cluster_req
def node_log ( node , lines , follow ) :
"""
Show node logs of virtual machine DOMAIN on its current node in a pager or continuously . DOMAIN may be a UUID or name . Note that migrating a VM to a different node will cause the log buffer to be overwritten by entries from the new node .
"""
# Set the default here so we can handle it
if lines is None :
if follow :
lines = 10
else :
lines = 1000
if follow :
retcode , retmsg = pvc_node . follow_node_log ( config , node , lines )
else :
retcode , retmsg = pvc_node . view_node_log ( config , node , lines )
click . echo_via_pager ( retmsg )
2021-11-06 03:02:43 -04:00
retmsg = " "
2021-07-18 17:37:49 -04:00
cleanup ( retcode , retmsg )
2018-06-11 02:49:47 -04:00
###############################################################################
# pvc node info
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " info " , short_help = " Show details of a node object. " )
@click.argument ( " node " , default = myhostname )
2018-06-11 02:49:47 -04:00
@click.option (
2021-11-06 03:02:43 -04:00
" -l " ,
" --long " ,
" long_output " ,
is_flag = True ,
default = False ,
help = " Display more detailed information. " ,
2018-06-11 02:49:47 -04:00
)
2020-06-05 14:49:53 -04:00
@cluster_req
2018-06-16 22:22:07 -04:00
def node_info ( node , long_output ) :
2018-06-11 02:49:47 -04:00
"""
2018-06-16 22:22:07 -04:00
Show information about node NODE . If unspecified , defaults to this host .
2018-06-11 02:49:47 -04:00
"""
2019-12-26 11:20:57 -05:00
retcode , retdata = pvc_node . node_info ( config , node )
2019-05-10 23:25:06 -04:00
if retcode :
2020-01-05 12:35:00 -05:00
retdata = pvc_node . format_info ( retdata , long_output )
2019-12-26 11:20:57 -05:00
cleanup ( retcode , retdata )
2018-06-11 02:49:47 -04:00
2020-11-07 14:45:24 -05:00
2018-06-11 02:49:47 -04:00
###############################################################################
# pvc node list
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " list " , short_help = " List all node objects. " )
@click.argument ( " limit " , default = None , required = False )
2020-06-25 11:38:30 -04:00
@click.option (
2021-11-06 03:02:43 -04:00
" -ds " ,
" --daemon-state " ,
" target_daemon_state " ,
default = None ,
help = " Limit list to nodes in the specified daemon state. " ,
2020-06-25 11:38:30 -04:00
)
@click.option (
2021-11-06 03:02:43 -04:00
" -cs " ,
" --coordinator-state " ,
" target_coordinator_state " ,
default = None ,
help = " Limit list to nodes in the specified coordinator state. " ,
2020-06-25 11:38:30 -04:00
)
@click.option (
2021-11-06 03:02:43 -04:00
" -vs " ,
" --domain-state " ,
" target_domain_state " ,
default = None ,
help = " Limit list to nodes in the specified domain state. " ,
2020-06-25 11:38:30 -04:00
)
@click.option (
2021-11-06 03:02:43 -04:00
" -r " ,
" --raw " ,
" raw " ,
is_flag = True ,
default = False ,
help = " Display the raw list of node names only. " ,
2020-06-25 11:38:30 -04:00
)
2020-06-05 14:49:53 -04:00
@cluster_req
2021-11-06 03:02:43 -04:00
def node_list (
limit , target_daemon_state , target_coordinator_state , target_domain_state , raw
) :
2018-06-11 02:49:47 -04:00
"""
2020-01-04 14:06:36 -05:00
List all nodes ; optionally only match names matching regex LIMIT .
2018-06-11 02:49:47 -04:00
"""
2021-11-06 03:02:43 -04:00
retcode , retdata = pvc_node . node_list (
config ,
limit ,
target_daemon_state ,
target_coordinator_state ,
target_domain_state ,
)
2019-05-10 23:25:06 -04:00
if retcode :
2020-06-25 11:38:30 -04:00
retdata = pvc_node . format_list ( retdata , raw )
2020-07-11 11:38:13 -04:00
else :
if raw :
retdata = " "
2019-12-26 17:52:57 -05:00
cleanup ( retcode , retdata )
2018-06-11 02:49:47 -04:00
2020-11-07 14:45:24 -05:00
2018-06-05 01:39:59 -04:00
###############################################################################
# pvc vm
###############################################################################
2021-11-06 03:02:43 -04:00
@click.group (
name = " vm " ,
short_help = " Manage a PVC virtual machine. " ,
context_settings = CONTEXT_SETTINGS ,
)
2018-09-20 03:25:58 -04:00
def cli_vm ( ) :
2018-06-05 01:39:59 -04:00
"""
Manage the state of a virtual machine in the PVC cluster .
"""
2020-11-07 14:45:24 -05:00
pass
2018-06-05 01:39:59 -04:00
###############################################################################
# pvc vm define
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command (
name = " define " , short_help = " Define a new virtual machine from a Libvirt XML file. "
2018-07-18 12:15:39 -04:00
)
@click.option (
2021-11-06 03:02:43 -04:00
" -t " ,
" --target " ,
" target_node " ,
help = " Home node for this domain; autoselect if unspecified. " ,
2019-10-12 01:17:39 -04:00
)
@click.option (
2021-11-06 03:02:43 -04:00
" -l " ,
" --limit " ,
" node_limit " ,
default = None ,
show_default = False ,
help = " Comma-separated list of nodes to limit VM operation to; saved with VM. " ,
2019-10-12 01:17:39 -04:00
)
@click.option (
2021-11-06 03:02:43 -04:00
" -s " ,
2022-06-10 02:14:15 -04:00
" --node-selector " ,
2021-11-06 03:02:43 -04:00
" node_selector " ,
2022-06-10 02:03:12 -04:00
default = " none " ,
2021-11-06 03:02:43 -04:00
show_default = True ,
2022-06-10 02:03:12 -04:00
type = click . Choice ( [ " mem " , " memfree " , " load " , " vcpus " , " vms " , " none " ] ) ,
2021-11-06 03:02:43 -04:00
help = ' Method to determine optimal target node during autoselect; " none " will use the default for the cluster. ' ,
2018-06-05 01:39:59 -04:00
)
2020-10-29 11:31:32 -04:00
@click.option (
2021-11-06 03:02:43 -04:00
" -a/-A " ,
" --autostart/--no-autostart " ,
" node_autostart " ,
is_flag = True ,
default = False ,
help = " Start VM automatically on next unflush/ready state of home node; unset by daemon once used. " ,
2020-10-29 11:31:32 -04:00
)
2021-07-13 19:04:56 -04:00
@click.option (
2021-11-06 03:02:43 -04:00
" -m " ,
" --method " ,
" migration_method " ,
default = " none " ,
show_default = True ,
type = click . Choice ( [ " none " , " live " , " shutdown " ] ) ,
help = " The preferred migration method of the VM between nodes; saved with VM. " ,
2021-07-13 19:04:56 -04:00
)
@click.option (
2021-11-06 03:02:43 -04:00
" -g " ,
" --tag " ,
" user_tags " ,
default = [ ] ,
multiple = True ,
help = " User tag for the VM; can be specified multiple times, once per tag. " ,
2021-07-13 19:04:56 -04:00
)
2021-11-06 03:02:43 -04:00
@click.option (
" -G " ,
" --protected-tag " ,
" protected_tags " ,
default = [ ] ,
multiple = True ,
help = " Protected user tag for the VM; can be specified multiple times, once per tag. " ,
2018-06-16 22:22:07 -04:00
)
2021-11-06 03:02:43 -04:00
@click.argument ( " vmconfig " , type = click . File ( ) )
2020-06-05 14:49:53 -04:00
@cluster_req
2021-11-06 03:02:43 -04:00
def vm_define (
vmconfig ,
target_node ,
node_limit ,
node_selector ,
node_autostart ,
migration_method ,
user_tags ,
protected_tags ,
) :
2018-06-05 01:39:59 -04:00
"""
2020-01-23 11:33:09 -05:00
Define a new virtual machine from Libvirt XML configuration file VMCONFIG .
2022-06-10 02:14:15 -04:00
The target node selector ( " --node-selector " / " -s " ) can be " none " to use the cluster default , or one of the following values :
* " mem " : choose the node with the least provisioned VM memory
* " memfree " : choose the node with the most ( real ) free memory
* " vcpus " : choose the node with the least allocated VM vCPUs
* " load " : choose the node with the lowest current load average
* " vms " : choose the node with the least number of provisioned VMs
For most clusters , " mem " should be sufficient , but others may be used based on the cluster workload and available resources . The following caveats should be considered :
* " mem " looks at the provisioned memory , not the allocated memory ; thus , stopped or disabled VMs are counted towards a node ' s memory for this selector, even though their memory is not actively in use.
* " memfree " looks at the free memory of the node in general , ignoring the amount provisioned to VMs ; if any VM ' s internal memory usage changes, this value would be affected. This might be preferable to " mem " on clusters with very high memory utilization versus total capacity or if many VMs are stopped/disabled.
* " load " looks at the system load of the node in general , ignoring load in any particular VMs ; if any VM ' s CPU usage changes, this value would be affected. This might be preferable on clusters with some very CPU intensive VMs.
2018-06-05 01:39:59 -04:00
"""
2018-06-06 12:00:52 -04:00
# Open the XML file
2020-01-23 11:33:09 -05:00
vmconfig_data = vmconfig . read ( )
vmconfig . close ( )
2018-06-06 12:00:52 -04:00
2020-01-24 13:17:48 -05:00
# Verify our XML is sensible
try :
xml_data = etree . fromstring ( vmconfig_data )
2021-11-06 03:02:43 -04:00
new_cfg = etree . tostring ( xml_data , pretty_print = True ) . decode ( " utf8 " )
2020-11-06 18:55:10 -05:00
except Exception :
2021-11-06 03:02:43 -04:00
cleanup ( False , " Error: XML is malformed or invalid " )
retcode , retmsg = pvc_vm . vm_define (
config ,
new_cfg ,
target_node ,
node_limit ,
node_selector ,
node_autostart ,
migration_method ,
user_tags ,
protected_tags ,
)
2019-12-27 09:52:16 -05:00
cleanup ( retcode , retmsg )
2019-10-12 01:17:39 -04:00
2020-11-07 14:45:24 -05:00
2019-10-12 01:17:39 -04:00
###############################################################################
# pvc vm meta
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " meta " , short_help = " Modify PVC metadata of an existing VM. " )
2019-10-12 01:17:39 -04:00
@click.option (
2021-11-06 03:02:43 -04:00
" -l " ,
" --limit " ,
" node_limit " ,
default = None ,
show_default = False ,
help = " Comma-separated list of nodes to limit VM operation to; set to an empty string to remove. " ,
2019-10-12 01:17:39 -04:00
)
@click.option (
2021-11-06 03:02:43 -04:00
" -s " ,
2022-06-10 02:14:15 -04:00
" --node-selector " ,
2021-11-06 03:02:43 -04:00
" node_selector " ,
default = None ,
show_default = False ,
2022-06-10 02:03:12 -04:00
type = click . Choice ( [ " mem " , " memfree " , " load " , " vcpus " , " vms " , " none " ] ) ,
2021-11-06 03:02:43 -04:00
help = ' Method to determine optimal target node during autoselect; " none " will use the default for the cluster. ' ,
2019-10-12 01:17:39 -04:00
)
@click.option (
2021-11-06 03:02:43 -04:00
" -a/-A " ,
" --autostart/--no-autostart " ,
" node_autostart " ,
is_flag = True ,
default = None ,
help = " Start VM automatically on next unflush/ready state of home node; unset by daemon once used. " ,
2019-10-12 01:17:39 -04:00
)
2020-10-29 11:31:32 -04:00
@click.option (
2021-11-06 03:02:43 -04:00
" -m " ,
" --method " ,
" migration_method " ,
default = " none " ,
show_default = True ,
type = click . Choice ( [ " none " , " live " , " shutdown " ] ) ,
help = " The preferred migration method of the VM between nodes. " ,
2020-10-29 11:31:32 -04:00
)
2020-01-30 11:45:46 -05:00
@click.option (
2021-11-06 03:02:43 -04:00
" -p " ,
" --profile " ,
" provisioner_profile " ,
default = None ,
show_default = False ,
help = " PVC provisioner profile name for VM. " ,
2019-10-12 01:17:39 -04:00
)
2021-11-06 03:02:43 -04:00
@click.argument ( " domain " )
2020-06-05 14:49:53 -04:00
@cluster_req
2021-11-06 03:02:43 -04:00
def vm_meta (
domain ,
node_limit ,
node_selector ,
node_autostart ,
migration_method ,
provisioner_profile ,
) :
2019-10-12 01:17:39 -04:00
"""
Modify the PVC metadata of existing virtual machine DOMAIN . At least one option to update must be specified . DOMAIN may be a UUID or name .
2022-06-10 02:14:15 -04:00
For details on the " --node-selector " / " -s " values , please see help for the command " pvc vm define " .
2019-10-12 01:17:39 -04:00
"""
2021-11-06 03:02:43 -04:00
if (
node_limit is None
and node_selector is None
and node_autostart is None
and migration_method is None
and provisioner_profile is None
) :
cleanup ( False , " At least one metadata option must be specified to update. " )
retcode , retmsg = pvc_vm . vm_metadata (
config ,
domain ,
node_limit ,
node_selector ,
node_autostart ,
migration_method ,
provisioner_profile ,
)
2019-12-27 09:52:16 -05:00
cleanup ( retcode , retmsg )
2018-06-06 12:00:52 -04:00
2020-11-07 14:45:24 -05:00
2018-07-20 00:38:31 -04:00
###############################################################################
# pvc vm modify
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " modify " , short_help = " Modify an existing VM configuration. " )
2018-07-20 00:38:31 -04:00
@click.option (
2021-11-06 03:02:43 -04:00
" -e " ,
" --editor " ,
" editor " ,
is_flag = True ,
help = " Use local editor to modify existing config. " ,
2018-07-20 00:38:31 -04:00
)
@click.option (
2021-11-06 03:02:43 -04:00
" -r " ,
" --restart " ,
" restart " ,
is_flag = True ,
help = " Immediately restart VM to apply new config. " ,
2018-07-20 00:38:31 -04:00
)
2021-04-08 12:57:40 -04:00
@click.option (
2021-11-06 03:02:43 -04:00
" -d " ,
" --confirm-diff " ,
" confirm_diff_flag " ,
is_flag = True ,
default = False ,
help = " Confirm the diff. " ,
2021-07-19 00:25:43 -04:00
)
@click.option (
2021-11-06 03:02:43 -04:00
" -c " ,
" --confirm-restart " ,
" confirm_restart_flag " ,
is_flag = True ,
default = False ,
help = " Confirm the restart. " ,
2021-07-19 00:25:43 -04:00
)
@click.option (
2021-11-06 03:02:43 -04:00
" -y " ,
" --yes " ,
" confirm_all_flag " ,
is_flag = True ,
default = False ,
help = " Confirm the diff and the restart. " ,
)
@click.argument ( " domain " )
@click.argument ( " cfgfile " , type = click . File ( ) , default = None , required = False )
2022-08-02 10:02:26 -04:00
@cluster_req
2021-11-06 03:02:43 -04:00
def vm_modify (
domain ,
cfgfile ,
editor ,
restart ,
confirm_diff_flag ,
confirm_restart_flag ,
confirm_all_flag ,
) :
2018-07-20 00:38:31 -04:00
"""
Modify existing virtual machine DOMAIN , either in - editor or with replacement CONFIG . DOMAIN may be a UUID or name .
"""
2020-11-06 19:36:36 -05:00
if editor is False and cfgfile is None :
2021-11-06 03:02:43 -04:00
cleanup (
False ,
' Either an XML config file or the " --editor " option must be specified. ' ,
)
2018-07-20 00:38:31 -04:00
2019-12-27 09:52:16 -05:00
retcode , vm_information = pvc_vm . vm_info ( config , domain )
2021-11-06 03:02:43 -04:00
if not retcode or not vm_information . get ( " name " , None ) :
2020-01-04 14:06:36 -05:00
cleanup ( False , ' ERROR: Could not find VM " {} " ! ' . format ( domain ) )
2019-12-27 09:52:16 -05:00
2021-11-06 03:02:43 -04:00
dom_name = vm_information . get ( " name " )
2018-09-20 03:25:58 -04:00
2021-07-19 00:02:19 -04:00
# Grab the current config
2021-11-06 03:02:43 -04:00
current_vm_cfg_raw = vm_information . get ( " xml " )
2021-07-19 00:02:19 -04:00
xml_data = etree . fromstring ( current_vm_cfg_raw )
2021-11-06 03:02:43 -04:00
current_vm_cfgfile = (
etree . tostring ( xml_data , pretty_print = True ) . decode ( " utf8 " ) . strip ( )
)
2018-07-20 00:38:31 -04:00
2021-07-19 00:02:19 -04:00
if editor is True :
2021-11-06 03:02:43 -04:00
new_vm_cfgfile = click . edit (
text = current_vm_cfgfile , require_save = True , extension = " .xml "
)
2020-01-08 09:33:01 -05:00
if new_vm_cfgfile is None :
2021-11-08 00:04:20 -05:00
echo ( " Aborting with no modifications. " )
2018-07-20 00:38:31 -04:00
exit ( 0 )
2020-01-08 09:33:01 -05:00
else :
new_vm_cfgfile = new_vm_cfgfile . strip ( )
2018-07-20 00:38:31 -04:00
# We're operating in replace mode
else :
# Open the XML file
2019-12-27 09:52:16 -05:00
new_vm_cfgfile = cfgfile . read ( )
cfgfile . close ( )
2018-07-20 00:38:31 -04:00
2021-11-08 00:04:20 -05:00
echo (
2021-11-06 03:02:43 -04:00
' Replacing configuration of VM " {} " with file " {} " . ' . format (
dom_name , cfgfile . name
)
)
2021-04-13 10:15:40 -04:00
# Show a diff and confirm
2021-11-08 00:04:20 -05:00
echo ( " Pending modifications: " )
echo ( " " )
2021-11-06 03:02:43 -04:00
diff = list (
difflib . unified_diff (
current_vm_cfgfile . split ( " \n " ) ,
new_vm_cfgfile . split ( " \n " ) ,
fromfile = " current " ,
tofile = " modified " ,
fromfiledate = " " ,
tofiledate = " " ,
n = 3 ,
lineterm = " " ,
)
)
2021-04-13 10:15:40 -04:00
for line in diff :
2021-11-06 03:02:43 -04:00
if re . match ( r " ^ \ + " , line ) is not None :
2021-11-08 00:04:20 -05:00
echo ( colorama . Fore . GREEN + line + colorama . Fore . RESET )
2021-11-06 03:02:43 -04:00
elif re . match ( r " ^ \ - " , line ) is not None :
2021-11-08 00:04:20 -05:00
echo ( colorama . Fore . RED + line + colorama . Fore . RESET )
2021-11-06 03:02:43 -04:00
elif re . match ( r " ^ \ ^ " , line ) is not None :
2021-11-08 00:04:20 -05:00
echo ( colorama . Fore . BLUE + line + colorama . Fore . RESET )
2018-09-25 02:36:37 -04:00
else :
2021-11-08 00:04:20 -05:00
echo ( line )
echo ( " " )
2018-07-20 00:38:31 -04:00
2020-01-24 13:17:48 -05:00
# Verify our XML is sensible
try :
xml_data = etree . fromstring ( new_vm_cfgfile )
2021-11-06 03:02:43 -04:00
new_cfg = etree . tostring ( xml_data , pretty_print = True ) . decode ( " utf8 " )
2020-01-24 13:17:48 -05:00
except Exception as e :
2021-11-06 03:02:43 -04:00
cleanup ( False , " Error: XML is malformed or invalid: {} " . format ( e ) )
2020-01-24 13:17:48 -05:00
2021-11-06 03:02:43 -04:00
if not confirm_diff_flag and not confirm_all_flag and not config [ " unsafe " ] :
click . confirm ( " Write modifications to cluster? " , abort = True )
2021-04-13 10:15:40 -04:00
2021-11-06 03:02:43 -04:00
if (
restart
and not confirm_restart_flag
and not confirm_all_flag
and not config [ " unsafe " ]
) :
2021-04-13 10:15:40 -04:00
try :
2021-11-06 03:02:43 -04:00
click . confirm (
" Restart VM {} " . format ( domain ) , prompt_suffix = " ? " , abort = True
)
2021-04-13 10:15:40 -04:00
except Exception :
restart = False
2020-01-24 13:17:48 -05:00
retcode , retmsg = pvc_vm . vm_modify ( config , domain , new_cfg , restart )
2021-04-08 12:57:40 -04:00
if retcode and not restart :
retmsg = retmsg + " Changes will be applied on next VM start/restart. "
2019-12-27 09:52:16 -05:00
cleanup ( retcode , retmsg )
2018-07-20 00:38:31 -04:00
2020-11-07 14:45:24 -05:00
2021-05-23 16:41:42 -04:00
###############################################################################
# pvc vm rename
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " rename " , short_help = " Rename a virtual machine. " )
@click.argument ( " domain " )
@click.argument ( " new_name " )
2021-05-23 16:41:42 -04:00
@click.option (
2021-11-06 03:02:43 -04:00
" -y " ,
" --yes " ,
" confirm_flag " ,
is_flag = True ,
default = False ,
help = " Confirm the rename " ,
2021-05-23 16:41:42 -04:00
)
@cluster_req
def vm_rename ( domain , new_name , confirm_flag ) :
"""
Rename virtual machine DOMAIN , and all its connected disk volumes , to NEW_NAME . DOMAIN may be a UUID or name .
"""
2021-11-06 03:02:43 -04:00
if not confirm_flag and not config [ " unsafe " ] :
2021-05-23 16:41:42 -04:00
try :
2021-11-06 03:02:43 -04:00
click . confirm (
" Rename VM {} to {} " . format ( domain , new_name ) ,
prompt_suffix = " ? " ,
abort = True ,
)
2021-05-23 16:41:42 -04:00
except Exception :
exit ( 0 )
retcode , retmsg = pvc_vm . vm_rename ( config , domain , new_name )
cleanup ( retcode , retmsg )
2018-06-06 12:00:52 -04:00
###############################################################################
# pvc vm undefine
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " undefine " , short_help = " Undefine a virtual machine. " )
@click.argument ( " domain " )
2020-01-08 10:34:27 -05:00
@click.option (
2021-11-06 03:02:43 -04:00
" -y " ,
" --yes " ,
" confirm_flag " ,
is_flag = True ,
default = False ,
help = " Confirm the removal " ,
2020-01-08 10:34:27 -05:00
)
2020-06-05 14:49:53 -04:00
@cluster_req
2020-01-08 10:34:27 -05:00
def vm_undefine ( domain , confirm_flag ) :
2018-06-06 12:00:52 -04:00
"""
2020-01-04 14:06:36 -05:00
Stop virtual machine DOMAIN and remove it database , preserving disks . DOMAIN may be a UUID or name .
2018-06-06 12:00:52 -04:00
"""
2021-11-06 03:02:43 -04:00
if not confirm_flag and not config [ " unsafe " ] :
2020-01-08 10:34:27 -05:00
try :
2021-11-06 03:02:43 -04:00
click . confirm (
" Undefine VM {} " . format ( domain ) , prompt_suffix = " ? " , abort = True
)
2020-11-06 18:55:10 -05:00
except Exception :
2020-01-08 10:34:27 -05:00
exit ( 0 )
2018-06-06 12:00:52 -04:00
2019-12-27 09:52:16 -05:00
retcode , retmsg = pvc_vm . vm_remove ( config , domain , delete_disks = False )
cleanup ( retcode , retmsg )
2018-06-05 01:39:59 -04:00
2020-11-07 14:45:24 -05:00
2019-06-27 11:19:48 -04:00
###############################################################################
# pvc vm remove
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " remove " , short_help = " Remove a virtual machine. " )
@click.argument ( " domain " )
2020-01-08 10:34:27 -05:00
@click.option (
2021-11-06 03:02:43 -04:00
" -y " ,
" --yes " ,
" confirm_flag " ,
is_flag = True ,
default = False ,
help = " Confirm the removal " ,
2020-01-08 10:34:27 -05:00
)
2020-06-05 14:49:53 -04:00
@cluster_req
2020-01-08 10:34:27 -05:00
def vm_remove ( domain , confirm_flag ) :
2019-06-27 11:19:48 -04:00
"""
2020-01-04 14:06:36 -05:00
Stop virtual machine DOMAIN and remove it , along with all disks , . DOMAIN may be a UUID or name .
2019-06-27 11:19:48 -04:00
"""
2021-11-06 03:02:43 -04:00
if not confirm_flag and not config [ " unsafe " ] :
2020-01-08 10:34:27 -05:00
try :
2021-11-06 03:02:43 -04:00
click . confirm (
" Undefine VM {} and remove all disks " . format ( domain ) ,
prompt_suffix = " ? " ,
abort = True ,
)
2020-11-06 18:55:10 -05:00
except Exception :
2020-01-08 10:34:27 -05:00
exit ( 0 )
2019-06-27 11:19:48 -04:00
2019-12-27 09:52:16 -05:00
retcode , retmsg = pvc_vm . vm_remove ( config , domain , delete_disks = True )
cleanup ( retcode , retmsg )
2019-03-12 21:09:54 -04:00
2020-11-07 14:45:24 -05:00
2018-06-05 01:39:59 -04:00
###############################################################################
# pvc vm start
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " start " , short_help = " Start up a defined virtual machine. " )
@click.argument ( " domain " )
2020-06-05 14:49:53 -04:00
@cluster_req
2018-09-20 03:25:58 -04:00
def vm_start ( domain ) :
2018-06-05 01:39:59 -04:00
"""
2018-10-14 02:01:35 -04:00
Start virtual machine DOMAIN on its configured node . DOMAIN may be a UUID or name .
2018-06-05 01:39:59 -04:00
"""
2021-11-06 03:02:43 -04:00
retcode , retmsg = pvc_vm . vm_state ( config , domain , " start " )
2019-12-27 09:52:16 -05:00
cleanup ( retcode , retmsg )
2018-06-05 01:39:59 -04:00
2020-11-07 14:45:24 -05:00
2018-06-13 12:49:51 -04:00
###############################################################################
# pvc vm restart
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " restart " , short_help = " Restart a running virtual machine. " )
@click.argument ( " domain " )
2020-02-19 09:57:31 -05:00
@click.option (
2021-11-06 03:02:43 -04:00
" -w " ,
" --wait " ,
" wait " ,
is_flag = True ,
default = False ,
help = " Wait for restart to complete before returning. " ,
2020-02-19 09:57:31 -05:00
)
2021-04-08 12:57:40 -04:00
@click.option (
2021-11-06 03:02:43 -04:00
" -y " ,
" --yes " ,
" confirm_flag " ,
is_flag = True ,
default = False ,
help = " Confirm the restart " ,
2021-04-08 12:57:40 -04:00
)
2020-06-05 14:49:53 -04:00
@cluster_req
2021-04-08 12:57:40 -04:00
def vm_restart ( domain , wait , confirm_flag ) :
2018-06-13 12:49:51 -04:00
"""
2018-06-17 02:24:06 -04:00
Restart running virtual machine DOMAIN . DOMAIN may be a UUID or name .
2018-06-13 12:49:51 -04:00
"""
2021-11-06 03:02:43 -04:00
if not confirm_flag and not config [ " unsafe " ] :
2021-04-08 12:57:40 -04:00
try :
2021-11-06 03:02:43 -04:00
click . confirm (
" Restart VM {} " . format ( domain ) , prompt_suffix = " ? " , abort = True
)
2021-04-08 12:57:40 -04:00
except Exception :
exit ( 0 )
2018-06-13 12:49:51 -04:00
2021-11-06 03:02:43 -04:00
retcode , retmsg = pvc_vm . vm_state ( config , domain , " restart " , wait = wait )
2019-12-27 09:52:16 -05:00
cleanup ( retcode , retmsg )
2018-06-13 12:49:51 -04:00
2020-11-07 14:45:24 -05:00
2018-06-05 01:39:59 -04:00
###############################################################################
# pvc vm shutdown
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command (
name = " shutdown " , short_help = " Gracefully shut down a running virtual machine. "
2018-06-05 01:39:59 -04:00
)
2021-11-06 03:02:43 -04:00
@click.argument ( " domain " )
2020-02-19 09:57:31 -05:00
@click.option (
2021-11-06 03:02:43 -04:00
" -w " ,
" --wait " ,
" wait " ,
is_flag = True ,
default = False ,
help = " Wait for shutdown to complete before returning. " ,
2020-02-19 09:57:31 -05:00
)
2021-04-08 12:57:40 -04:00
@click.option (
2021-11-06 03:02:43 -04:00
" -y " ,
" --yes " ,
" confirm_flag " ,
is_flag = True ,
default = False ,
help = " Confirm the shutdown " ,
2021-04-08 12:57:40 -04:00
)
2020-06-05 14:49:53 -04:00
@cluster_req
2021-04-08 12:57:40 -04:00
def vm_shutdown ( domain , wait , confirm_flag ) :
2018-06-05 01:39:59 -04:00
"""
2018-06-16 22:22:07 -04:00
Gracefully shut down virtual machine DOMAIN . DOMAIN may be a UUID or name .
2018-06-05 01:39:59 -04:00
"""
2021-11-06 03:02:43 -04:00
if not confirm_flag and not config [ " unsafe " ] :
2021-04-08 12:57:40 -04:00
try :
2021-11-06 03:02:43 -04:00
click . confirm (
" Shut down VM {} " . format ( domain ) , prompt_suffix = " ? " , abort = True
)
2021-04-08 12:57:40 -04:00
except Exception :
exit ( 0 )
2018-06-05 01:39:59 -04:00
2021-11-06 03:02:43 -04:00
retcode , retmsg = pvc_vm . vm_state ( config , domain , " shutdown " , wait = wait )
2019-12-27 09:52:16 -05:00
cleanup ( retcode , retmsg )
2018-06-05 01:39:59 -04:00
2020-11-07 14:45:24 -05:00
2018-06-05 01:39:59 -04:00
###############################################################################
# pvc vm stop
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " stop " , short_help = " Forcibly halt a running virtual machine. " )
@click.argument ( " domain " )
2021-04-08 12:57:40 -04:00
@click.option (
2021-11-06 03:02:43 -04:00
" -y " , " --yes " , " confirm_flag " , is_flag = True , default = False , help = " Confirm the stop "
2021-04-08 12:57:40 -04:00
)
2020-06-05 14:49:53 -04:00
@cluster_req
2021-04-08 12:57:40 -04:00
def vm_stop ( domain , confirm_flag ) :
2018-06-05 01:39:59 -04:00
"""
2018-06-16 22:22:07 -04:00
Forcibly halt ( destroy ) running virtual machine DOMAIN . DOMAIN may be a UUID or name .
2018-06-05 01:39:59 -04:00
"""
2021-11-06 03:02:43 -04:00
if not confirm_flag and not config [ " unsafe " ] :
2021-04-08 12:57:40 -04:00
try :
2021-11-06 03:02:43 -04:00
click . confirm (
" Forcibly stop VM {} " . format ( domain ) , prompt_suffix = " ? " , abort = True
)
2021-04-08 12:57:40 -04:00
except Exception :
exit ( 0 )
2018-06-05 01:39:59 -04:00
2021-11-06 03:02:43 -04:00
retcode , retmsg = pvc_vm . vm_state ( config , domain , " stop " )
2019-12-27 09:52:16 -05:00
cleanup ( retcode , retmsg )
2018-06-05 01:39:59 -04:00
2020-11-07 14:45:24 -05:00
2019-10-23 23:37:42 -04:00
###############################################################################
# pvc vm disable
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " disable " , short_help = " Mark a virtual machine as disabled. " )
@click.argument ( " domain " )
2021-11-06 04:02:09 -04:00
@click.option (
" --force " ,
2022-08-18 11:37:57 -04:00
" force_flag " ,
2021-11-06 04:02:09 -04:00
is_flag = True ,
default = False ,
help = " Forcibly stop the VM instead of waiting for shutdown. " ,
)
2022-07-21 16:43:37 -04:00
@click.option (
" -y " ,
" --yes " ,
" confirm_flag " ,
is_flag = True ,
default = False ,
help = " Confirm the disable " ,
)
2020-06-05 14:49:53 -04:00
@cluster_req
2022-07-21 16:43:37 -04:00
def vm_disable ( domain , force_flag , confirm_flag ) :
2019-10-23 23:37:42 -04:00
"""
2021-11-06 04:02:09 -04:00
Shut down virtual machine DOMAIN and mark it as disabled . DOMAIN may be a UUID or name .
2019-10-23 23:37:42 -04:00
2021-11-06 04:02:09 -04:00
Disabled VMs will not be counted towards a degraded cluster health status , unlike stopped VMs . Use this option for a VM that will remain off for an extended period .
2019-10-23 23:37:42 -04:00
"""
2022-07-21 16:43:37 -04:00
if not confirm_flag and not config [ " unsafe " ] :
try :
click . confirm (
" Disable VM {} " . format ( domain ) , prompt_suffix = " ? " , abort = True
)
except Exception :
exit ( 0 )
retcode , retmsg = pvc_vm . vm_state ( config , domain , " disable " , force = force_flag )
2019-12-27 09:52:16 -05:00
cleanup ( retcode , retmsg )
2019-10-23 23:37:42 -04:00
2020-11-07 14:45:24 -05:00
2018-06-10 21:03:41 -04:00
###############################################################################
# pvc vm move
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command (
name = " move " , short_help = " Permanently move a virtual machine to another node. "
2018-06-10 21:03:41 -04:00
)
2021-11-06 03:02:43 -04:00
@click.argument ( " domain " )
2018-06-10 21:03:41 -04:00
@click.option (
2021-11-06 03:02:43 -04:00
" -t " ,
" --target " ,
" target_node " ,
default = None ,
help = " Target node to migrate to; autodetect if unspecified. " ,
2018-06-10 21:03:41 -04:00
)
2020-02-19 09:57:31 -05:00
@click.option (
2021-11-06 03:02:43 -04:00
" -w " ,
" --wait " ,
" wait " ,
is_flag = True ,
default = False ,
help = " Wait for migration to complete before returning. " ,
2020-02-19 09:57:31 -05:00
)
2020-06-06 11:49:21 -04:00
@click.option (
2021-11-06 03:02:43 -04:00
" --force-live " ,
" force_live " ,
is_flag = True ,
default = False ,
help = " Do not fall back to shutdown-based migration if live migration fails. " ,
2020-06-06 11:49:21 -04:00
)
2020-06-05 14:49:53 -04:00
@cluster_req
2020-06-06 11:49:21 -04:00
def vm_move ( domain , target_node , wait , force_live ) :
2018-06-10 21:03:41 -04:00
"""
2018-10-14 02:01:35 -04:00
Permanently move virtual machine DOMAIN , via live migration if running and possible , to another node . DOMAIN may be a UUID or name .
2018-06-10 21:03:41 -04:00
"""
2021-11-06 03:02:43 -04:00
retcode , retmsg = pvc_vm . vm_node (
config ,
domain ,
target_node ,
" move " ,
force = False ,
wait = wait ,
force_live = force_live ,
)
2019-12-27 09:52:16 -05:00
cleanup ( retcode , retmsg )
2018-06-10 21:03:41 -04:00
2020-11-07 14:45:24 -05:00
2018-06-05 22:06:08 -04:00
###############################################################################
# pvc vm migrate
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command (
name = " migrate " , short_help = " Temporarily migrate a virtual machine to another node. "
2018-06-05 22:06:08 -04:00
)
2021-11-06 03:02:43 -04:00
@click.argument ( " domain " )
2018-06-05 22:06:08 -04:00
@click.option (
2021-11-06 03:02:43 -04:00
" -t " ,
" --target " ,
" target_node " ,
default = None ,
help = " Target node to migrate to; autodetect if unspecified. " ,
2018-06-05 22:06:08 -04:00
)
@click.option (
2021-11-06 03:02:43 -04:00
" -f " ,
" --force " ,
" force_migrate " ,
is_flag = True ,
default = False ,
help = " Force migrate an already migrated VM; does not replace an existing previous node value. " ,
2018-06-05 22:06:08 -04:00
)
2020-02-19 09:57:31 -05:00
@click.option (
2021-11-06 03:02:43 -04:00
" -w " ,
" --wait " ,
" wait " ,
is_flag = True ,
default = False ,
help = " Wait for migration to complete before returning. " ,
2020-02-19 09:57:31 -05:00
)
2020-06-06 11:49:21 -04:00
@click.option (
2021-11-06 03:02:43 -04:00
" --force-live " ,
" force_live " ,
is_flag = True ,
default = False ,
help = " Do not fall back to shutdown-based migration if live migration fails. " ,
2020-06-06 11:49:21 -04:00
)
2020-06-05 14:49:53 -04:00
@cluster_req
2020-06-06 11:49:21 -04:00
def vm_migrate ( domain , target_node , force_migrate , wait , force_live ) :
2018-06-05 01:39:59 -04:00
"""
2018-10-14 02:01:35 -04:00
Temporarily migrate running virtual machine DOMAIN , via live migration if possible , to another node . DOMAIN may be a UUID or name . If DOMAIN is not running , it will be started on the target node .
2018-06-05 01:39:59 -04:00
"""
2021-11-06 03:02:43 -04:00
retcode , retmsg = pvc_vm . vm_node (
config ,
domain ,
target_node ,
" migrate " ,
force = force_migrate ,
wait = wait ,
force_live = force_live ,
)
2019-12-27 09:52:16 -05:00
cleanup ( retcode , retmsg )
2018-06-05 22:06:08 -04:00
2020-11-07 14:45:24 -05:00
2018-06-05 22:06:08 -04:00
###############################################################################
# pvc vm unmigrate
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command (
name = " unmigrate " ,
short_help = " Restore a migrated virtual machine to its original node. " ,
2018-06-05 22:06:08 -04:00
)
2021-11-06 03:02:43 -04:00
@click.argument ( " domain " )
2020-02-19 09:57:31 -05:00
@click.option (
2021-11-06 03:02:43 -04:00
" -w " ,
" --wait " ,
" wait " ,
is_flag = True ,
default = False ,
help = " Wait for migration to complete before returning. " ,
2020-02-19 09:57:31 -05:00
)
2020-06-06 11:49:21 -04:00
@click.option (
2021-11-06 03:02:43 -04:00
" --force-live " ,
" force_live " ,
is_flag = True ,
default = False ,
help = " Do not fall back to shutdown-based migration if live migration fails. " ,
2020-06-06 11:49:21 -04:00
)
2020-06-05 14:49:53 -04:00
@cluster_req
2020-06-06 11:49:21 -04:00
def vm_unmigrate ( domain , wait , force_live ) :
2018-06-05 01:39:59 -04:00
"""
2018-10-14 02:01:35 -04:00
Restore previously migrated virtual machine DOMAIN , via live migration if possible , to its original node . DOMAIN may be a UUID or name . If DOMAIN is not running , it will be started on the target node .
2018-06-05 01:39:59 -04:00
"""
2021-11-06 03:02:43 -04:00
retcode , retmsg = pvc_vm . vm_node (
config , domain , None , " unmigrate " , force = False , wait = wait , force_live = force_live
)
2019-12-27 09:52:16 -05:00
cleanup ( retcode , retmsg )
2018-06-05 22:06:08 -04:00
2020-11-07 14:45:24 -05:00
2019-08-07 13:42:01 -04:00
###############################################################################
2019-08-07 17:50:25 -04:00
# pvc vm flush-locks
2019-08-07 13:42:01 -04:00
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command (
name = " flush-locks " , short_help = " Flush stale RBD locks for a virtual machine. "
2019-08-07 13:42:01 -04:00
)
2021-11-06 03:02:43 -04:00
@click.argument ( " domain " )
2020-06-05 14:49:53 -04:00
@cluster_req
2019-08-07 13:42:01 -04:00
def vm_flush_locks ( domain ) :
"""
Flush stale RBD locks for virtual machine DOMAIN . DOMAIN may be a UUID or name . DOMAIN must be in a stopped state before flushing locks .
"""
2019-12-27 09:52:16 -05:00
retcode , retmsg = pvc_vm . vm_locks ( config , domain )
cleanup ( retcode , retmsg )
2020-11-07 14:45:24 -05:00
2021-07-13 19:04:56 -04:00
###############################################################################
# pvc vm tag
###############################################################################
2021-11-06 03:02:43 -04:00
@click.group (
name = " tag " ,
short_help = " Manage tags of a virtual machine. " ,
context_settings = CONTEXT_SETTINGS ,
)
2021-07-13 19:04:56 -04:00
def vm_tags ( ) :
"""
Manage the tags of a virtual machine in the PVC cluster . "
"""
pass
###############################################################################
# pvc vm tag get
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " get " , short_help = " Get the current tags of a virtual machine. " )
@click.argument ( " domain " )
2021-07-13 19:04:56 -04:00
@click.option (
2021-11-06 03:02:43 -04:00
" -r " ,
" --raw " ,
" raw " ,
is_flag = True ,
default = False ,
help = " Display the raw value only without formatting. " ,
2021-07-13 19:04:56 -04:00
)
@cluster_req
def vm_tags_get ( domain , raw ) :
"""
Get the current tags of the virtual machine DOMAIN .
"""
retcode , retdata = pvc_vm . vm_tags_get ( config , domain )
if retcode :
if not raw :
2021-11-06 03:02:43 -04:00
retdata = pvc_vm . format_vm_tags ( config , domain , retdata [ " tags " ] )
2021-07-13 19:04:56 -04:00
else :
2021-11-06 03:02:43 -04:00
if len ( retdata [ " tags " ] ) > 0 :
retdata = " \n " . join ( [ tag [ " name " ] for tag in retdata [ " tags " ] ] )
2021-07-13 19:04:56 -04:00
else :
2021-11-06 03:02:43 -04:00
retdata = " No tags found. "
2021-07-13 19:04:56 -04:00
cleanup ( retcode , retdata )
###############################################################################
# pvc vm tag add
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " add " , short_help = " Add new tags to a virtual machine. " )
@click.argument ( " domain " )
@click.argument ( " tag " )
2021-07-13 19:04:56 -04:00
@click.option (
2021-11-06 03:02:43 -04:00
" -p " ,
" --protected " ,
" protected " ,
is_flag = True ,
required = False ,
default = False ,
help = " Set this tag as protected; protected tags cannot be removed. " ,
2021-07-13 19:04:56 -04:00
)
@cluster_req
def vm_tags_add ( domain , tag , protected ) :
"""
Add TAG to the virtual machine DOMAIN .
"""
2021-11-06 03:02:43 -04:00
retcode , retmsg = pvc_vm . vm_tag_set ( config , domain , " add " , tag , protected )
2021-07-13 19:04:56 -04:00
cleanup ( retcode , retmsg )
###############################################################################
# pvc vm tag remove
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " remove " , short_help = " Remove tags from a virtual machine. " )
@click.argument ( " domain " )
@click.argument ( " tag " )
2021-07-13 19:04:56 -04:00
@cluster_req
def vm_tags_remove ( domain , tag ) :
"""
Remove TAG from the virtual machine DOMAIN .
"""
2021-11-06 03:02:43 -04:00
retcode , retmsg = pvc_vm . vm_tag_set ( config , domain , " remove " , tag )
2021-07-13 19:04:56 -04:00
cleanup ( retcode , retmsg )
2020-11-07 16:02:56 -05:00
###############################################################################
# pvc vm vcpu
###############################################################################
2021-11-06 03:02:43 -04:00
@click.group (
name = " vcpu " ,
short_help = " Manage vCPU counts of a virtual machine. " ,
context_settings = CONTEXT_SETTINGS ,
)
2020-11-07 16:02:56 -05:00
def vm_vcpu ( ) :
"""
Manage the vCPU counts of a virtual machine in the PVC cluster . "
"""
pass
2020-11-07 17:35:45 -05:00
###############################################################################
# pvc vm vcpu get
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command (
name = " get " , short_help = " Get the current vCPU count of a virtual machine. "
2020-11-07 17:35:45 -05:00
)
2021-11-06 03:02:43 -04:00
@click.argument ( " domain " )
2020-11-07 17:35:45 -05:00
@click.option (
2021-11-06 03:02:43 -04:00
" -r " ,
" --raw " ,
" raw " ,
is_flag = True ,
default = False ,
help = " Display the raw value only without formatting. " ,
2020-11-07 17:35:45 -05:00
)
@cluster_req
def vm_vcpu_get ( domain , raw ) :
"""
Get the current vCPU count of the virtual machine DOMAIN .
"""
retcode , retmsg = pvc_vm . vm_vcpus_get ( config , domain )
if not raw :
retmsg = pvc_vm . format_vm_vcpus ( config , domain , retmsg )
else :
retmsg = retmsg [ 0 ] # Get only the first part of the tuple (vm_vcpus)
cleanup ( retcode , retmsg )
###############################################################################
# pvc vm vcpu set
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " set " , short_help = " Set the vCPU count of a virtual machine. " )
@click.argument ( " domain " )
@click.argument ( " vcpus " )
2020-11-07 17:35:45 -05:00
@click.option (
2021-11-06 03:02:43 -04:00
" -t " ,
" --topology " ,
" topology " ,
default = None ,
help = " Use an alternative topology for the vCPUs in the CSV form <sockets>,<cores>,<threads>. SxCxT must equal VCPUS. " ,
2020-11-07 17:35:45 -05:00
)
@click.option (
2021-11-06 03:02:43 -04:00
" -r " ,
" --restart " ,
" restart " ,
is_flag = True ,
default = False ,
help = " Immediately restart VM to apply new config. " ,
2020-11-07 17:35:45 -05:00
)
2021-04-08 12:57:40 -04:00
@click.option (
2021-11-06 03:02:43 -04:00
" -y " ,
" --yes " ,
" confirm_flag " ,
is_flag = True ,
default = False ,
help = " Confirm the restart " ,
2021-04-08 12:57:40 -04:00
)
2020-11-07 17:35:45 -05:00
@cluster_req
2021-04-08 12:57:40 -04:00
def vm_vcpu_set ( domain , vcpus , topology , restart , confirm_flag ) :
2020-11-07 17:35:45 -05:00
"""
Set the vCPU count of the virtual machine DOMAIN to VCPUS .
By default , the topology of the vCPus is 1 socket , VCPUS cores per socket , 1 thread per core .
"""
if topology is not None :
try :
2021-11-06 03:02:43 -04:00
sockets , cores , threads = topology . split ( " , " )
2020-11-07 17:35:45 -05:00
if sockets * cores * threads != vcpus :
raise
except Exception :
2021-04-13 10:15:40 -04:00
cleanup ( False , " The specified topology is not valid. " )
2020-11-07 17:35:45 -05:00
topology = ( sockets , cores , threads )
else :
topology = ( 1 , vcpus , 1 )
2021-11-06 03:02:43 -04:00
if restart and not confirm_flag and not config [ " unsafe " ] :
2021-04-13 10:15:40 -04:00
try :
2021-11-06 03:02:43 -04:00
click . confirm (
" Restart VM {} " . format ( domain ) , prompt_suffix = " ? " , abort = True
)
2021-04-13 10:15:40 -04:00
except Exception :
restart = False
2020-11-07 17:35:45 -05:00
retcode , retmsg = pvc_vm . vm_vcpus_set ( config , domain , vcpus , topology , restart )
2021-04-08 12:57:40 -04:00
if retcode and not restart :
retmsg = retmsg + " Changes will be applied on next VM start/restart. "
2020-11-07 17:35:45 -05:00
cleanup ( retcode , retmsg )
2020-11-07 16:02:56 -05:00
###############################################################################
# pvc vm memory
###############################################################################
2021-11-06 03:02:43 -04:00
@click.group (
name = " memory " ,
short_help = " Manage provisioned memory of a virtual machine. " ,
context_settings = CONTEXT_SETTINGS ,
)
2020-11-07 16:02:56 -05:00
def vm_memory ( ) :
"""
Manage the provisioned memory of a virtual machine in the PVC cluster . "
"""
pass
2020-11-07 18:01:43 -05:00
###############################################################################
# pvc vm memory get
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command (
name = " get " , short_help = " Get the current provisioned memory of a virtual machine. "
2020-11-07 18:01:43 -05:00
)
2021-11-06 03:02:43 -04:00
@click.argument ( " domain " )
2020-11-07 18:01:43 -05:00
@click.option (
2021-11-06 03:02:43 -04:00
" -r " ,
" --raw " ,
" raw " ,
is_flag = True ,
default = False ,
help = " Display the raw value only without formatting. " ,
2020-11-07 18:01:43 -05:00
)
@cluster_req
def vm_memory_get ( domain , raw ) :
"""
Get the current provisioned memory of the virtual machine DOMAIN .
"""
retcode , retmsg = pvc_vm . vm_memory_get ( config , domain )
if not raw :
retmsg = pvc_vm . format_vm_memory ( config , domain , retmsg )
cleanup ( retcode , retmsg )
###############################################################################
# pvc vm memory set
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command (
name = " set " , short_help = " Set the provisioned memory of a virtual machine. "
2020-11-07 18:01:43 -05:00
)
2021-11-06 03:02:43 -04:00
@click.argument ( " domain " )
@click.argument ( " memory " )
2020-11-07 18:01:43 -05:00
@click.option (
2021-11-06 03:02:43 -04:00
" -r " ,
" --restart " ,
" restart " ,
is_flag = True ,
default = False ,
help = " Immediately restart VM to apply new config. " ,
2020-11-07 18:01:43 -05:00
)
2021-04-08 12:57:40 -04:00
@click.option (
2021-11-06 03:02:43 -04:00
" -y " ,
" --yes " ,
" confirm_flag " ,
is_flag = True ,
default = False ,
help = " Confirm the restart " ,
2021-04-08 12:57:40 -04:00
)
2020-11-07 18:01:43 -05:00
@cluster_req
2021-04-08 12:57:40 -04:00
def vm_memory_set ( domain , memory , restart , confirm_flag ) :
2020-11-07 18:01:43 -05:00
"""
Set the provisioned memory of the virtual machine DOMAIN to MEMORY ; MEMORY must be an integer in MB .
"""
2021-11-06 03:02:43 -04:00
if restart and not confirm_flag and not config [ " unsafe " ] :
2021-04-08 12:57:40 -04:00
try :
2021-11-06 03:02:43 -04:00
click . confirm (
" Restart VM {} " . format ( domain ) , prompt_suffix = " ? " , abort = True
)
2021-04-08 12:57:40 -04:00
except Exception :
2021-04-13 10:15:40 -04:00
restart = False
2020-11-07 18:01:43 -05:00
retcode , retmsg = pvc_vm . vm_memory_set ( config , domain , memory , restart )
2021-04-08 12:57:40 -04:00
if retcode and not restart :
retmsg = retmsg + " Changes will be applied on next VM start/restart. "
2020-11-07 18:01:43 -05:00
cleanup ( retcode , retmsg )
2020-11-07 16:02:56 -05:00
###############################################################################
# pvc vm network
###############################################################################
2021-11-06 03:02:43 -04:00
@click.group (
name = " network " ,
short_help = " Manage attached networks of a virtual machine. " ,
context_settings = CONTEXT_SETTINGS ,
)
2020-11-07 16:02:56 -05:00
def vm_network ( ) :
"""
2020-11-07 22:52:12 -05:00
Manage the attached networks of a virtual machine in the PVC cluster .
2020-11-08 00:48:50 -05:00
Network details cannot be modified here . To modify a network , first remove it , then readd it with the correct settings . Unless the ' -r ' / ' --reboot ' flag is provided , this will not affect the running VM until it is restarted .
2020-11-07 16:02:56 -05:00
"""
pass
2020-11-07 22:52:12 -05:00
###############################################################################
# pvc vm network get
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " get " , short_help = " Get the networks of a virtual machine. " )
@click.argument ( " domain " )
2020-11-07 22:52:12 -05:00
@click.option (
2021-11-06 03:02:43 -04:00
" -r " ,
" --raw " ,
" raw " ,
is_flag = True ,
default = False ,
help = " Display the raw values only without formatting. " ,
2020-11-07 22:52:12 -05:00
)
@cluster_req
def vm_network_get ( domain , raw ) :
"""
Get the networks of the virtual machine DOMAIN .
"""
retcode , retdata = pvc_vm . vm_networks_get ( config , domain )
if not raw :
retmsg = pvc_vm . format_vm_networks ( config , domain , retdata )
else :
network_vnis = list ( )
for network in retdata :
network_vnis . append ( network [ 0 ] )
2021-11-06 03:02:43 -04:00
retmsg = " , " . join ( network_vnis )
2020-11-07 22:52:12 -05:00
cleanup ( retcode , retmsg )
###############################################################################
# pvc vm network add
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " add " , short_help = " Add network to a virtual machine. " )
@click.argument ( " domain " )
@click.argument ( " net " )
2020-11-07 22:52:12 -05:00
@click.option (
2021-11-06 03:02:43 -04:00
" -a " ,
" --macaddr " ,
" macaddr " ,
default = None ,
help = " Use this MAC address instead of random generation; must be a valid MAC address in colon-delimited format. " ,
2020-11-07 22:52:12 -05:00
)
@click.option (
2021-11-06 03:02:43 -04:00
" -m " ,
" --model " ,
" model " ,
default = " virtio " ,
show_default = True ,
help = ' The model for the interface; must be a valid libvirt model. Not used for " netdev " SR-IOV NETs. ' ,
2021-06-21 22:21:54 -04:00
)
@click.option (
2021-11-06 03:02:43 -04:00
" -s " ,
" --sriov " ,
" sriov_flag " ,
is_flag = True ,
default = False ,
help = " Identify that NET is an SR-IOV device name and not a VNI. Required for adding SR-IOV NETs. " ,
2021-06-21 22:21:54 -04:00
)
@click.option (
2021-11-06 03:02:43 -04:00
" -d " ,
" --sriov-mode " ,
" sriov_mode " ,
default = " macvtap " ,
show_default = True ,
type = click . Choice ( [ " hostdev " , " macvtap " ] ) ,
help = " For SR-IOV NETs, the SR-IOV network device mode. " ,
2020-11-07 22:52:12 -05:00
)
@click.option (
2021-11-06 03:02:43 -04:00
" -l/-L " ,
" --live/--no-live " ,
" live_flag " ,
is_flag = True ,
default = True ,
help = " Immediately live-attach device to VM [default] or disable this behaviour. " ,
2021-09-12 15:41:05 -04:00
)
@click.option (
2021-11-06 03:02:43 -04:00
" -r " ,
" --restart " ,
" restart_flag " ,
is_flag = True ,
default = False ,
help = ' Immediately restart VM to apply new config; implies " --no-live " . ' ,
2020-11-07 22:52:12 -05:00
)
2021-04-08 12:57:40 -04:00
@click.option (
2021-11-06 03:02:43 -04:00
" -y " ,
" --yes " ,
" confirm_flag " ,
is_flag = True ,
default = False ,
help = " Confirm the VM restart. " ,
2021-04-08 12:57:40 -04:00
)
2020-11-07 22:52:12 -05:00
@cluster_req
2021-11-06 03:02:43 -04:00
def vm_network_add (
domain ,
net ,
macaddr ,
model ,
sriov_flag ,
sriov_mode ,
live_flag ,
restart_flag ,
confirm_flag ,
) :
2020-11-07 22:52:12 -05:00
"""
2021-06-21 22:21:54 -04:00
Add the network NET to the virtual machine DOMAIN . Networks are always addded to the end of the current list of networks in the virtual machine .
NET may be a PVC network VNI , which is added as a bridged device , or a SR - IOV VF device connected in the given mode .
NOTE : Adding a SR - IOV network device in the " hostdev " mode has the following caveats :
1. The VM will not be able to be live migrated ; it must be shut down to migrate between nodes . The VM metadata will be updated to force this .
2. If an identical SR - IOV VF device is not present on the target node , post - migration startup will fail . It may be prudent to use a node limit here .
2020-11-07 22:52:12 -05:00
"""
2021-09-12 15:41:05 -04:00
if restart_flag and live_flag :
2021-10-27 13:23:39 -04:00
live_flag = False
2021-09-12 15:41:05 -04:00
2021-11-06 03:02:43 -04:00
if restart_flag and not confirm_flag and not config [ " unsafe " ] :
2021-04-08 12:57:40 -04:00
try :
2021-11-06 03:02:43 -04:00
click . confirm (
" Restart VM {} " . format ( domain ) , prompt_suffix = " ? " , abort = True
)
2021-04-08 12:57:40 -04:00
except Exception :
2021-09-12 15:41:05 -04:00
restart_flag = False
2020-11-07 22:52:12 -05:00
2021-11-06 03:02:43 -04:00
retcode , retmsg = pvc_vm . vm_networks_add (
config ,
domain ,
net ,
macaddr ,
model ,
sriov_flag ,
sriov_mode ,
live_flag ,
restart_flag ,
)
2020-11-07 22:52:12 -05:00
cleanup ( retcode , retmsg )
###############################################################################
# pvc vm network remove
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " remove " , short_help = " Remove network from a virtual machine. " )
@click.argument ( " domain " )
@click.argument ( " net " , required = False , default = None )
2021-10-27 13:17:35 -04:00
@click.option (
2021-11-06 03:02:43 -04:00
" -m " ,
" --mac-address " ,
" macaddr " ,
default = None ,
help = " Remove an interface with this MAC address; required if NET is unspecified. " ,
2021-06-21 22:21:54 -04:00
)
@click.option (
2021-11-06 03:02:43 -04:00
" -s " ,
" --sriov " ,
" sriov_flag " ,
is_flag = True ,
default = False ,
help = " Identify that NET is an SR-IOV device name and not a VNI. Required for removing SR-IOV NETs. " ,
2020-11-07 22:52:12 -05:00
)
@click.option (
2021-11-06 03:02:43 -04:00
" -l/-L " ,
" --live/--no-live " ,
" live_flag " ,
is_flag = True ,
default = True ,
help = " Immediately live-detach device to VM [default] or disable this behaviour. " ,
2021-09-12 15:41:05 -04:00
)
@click.option (
2021-11-06 03:02:43 -04:00
" -r " ,
" --restart " ,
" restart_flag " ,
is_flag = True ,
default = False ,
help = ' Immediately restart VM to apply new config; implies " --no-live " . ' ,
2020-11-07 22:52:12 -05:00
)
2021-04-08 12:57:40 -04:00
@click.option (
2021-11-06 03:02:43 -04:00
" -y " ,
" --yes " ,
" confirm_flag " ,
is_flag = True ,
default = False ,
help = " Confirm the restart. " ,
2021-04-08 12:57:40 -04:00
)
2020-11-07 22:52:12 -05:00
@cluster_req
2021-11-06 03:02:43 -04:00
def vm_network_remove (
domain , net , macaddr , sriov_flag , live_flag , restart_flag , confirm_flag
) :
2020-11-07 22:52:12 -05:00
"""
2021-06-21 22:21:54 -04:00
Remove the network NET from the virtual machine DOMAIN .
NET may be a PVC network VNI , which is added as a bridged device , or a SR - IOV VF device connected in the given mode .
2021-10-27 13:17:35 -04:00
NET is optional if the ' -m ' / ' --mac-address ' option is specified . If it is , then the specific device with that MAC address is removed instead .
If multiple interfaces are present on the VM in network NET , and ' -m ' / ' --mac-address ' is not specified , then all interfaces in that network will be removed .
2020-11-07 22:52:12 -05:00
"""
2021-09-12 15:41:05 -04:00
if restart_flag and live_flag :
2021-10-27 13:23:39 -04:00
live_flag = False
2021-09-12 15:41:05 -04:00
2021-11-06 03:02:43 -04:00
if restart_flag and not confirm_flag and not config [ " unsafe " ] :
2021-04-08 12:57:40 -04:00
try :
2021-11-06 03:02:43 -04:00
click . confirm (
" Restart VM {} " . format ( domain ) , prompt_suffix = " ? " , abort = True
)
2021-04-08 12:57:40 -04:00
except Exception :
2021-09-12 15:41:05 -04:00
restart_flag = False
2020-11-07 22:52:12 -05:00
2021-11-06 03:02:43 -04:00
retcode , retmsg = pvc_vm . vm_networks_remove (
config , domain , net , macaddr , sriov_flag , live_flag , restart_flag
)
2020-11-07 22:52:12 -05:00
cleanup ( retcode , retmsg )
2020-11-07 16:02:56 -05:00
###############################################################################
# pvc vm volume
###############################################################################
2021-11-06 03:02:43 -04:00
@click.group (
name = " volume " ,
short_help = " Manage attached volumes of a virtual machine. " ,
context_settings = CONTEXT_SETTINGS ,
)
2020-11-07 16:02:56 -05:00
def vm_volume ( ) :
"""
2020-11-08 00:48:50 -05:00
Manage the attached volumes of a virtual machine in the PVC cluster .
Volume details cannot be modified here . To modify a volume , first remove it , then readd it with the correct settings . Unless the ' -r ' / ' --reboot ' flag is provided , this will not affect the running VM until it is restarted .
2020-11-07 16:02:56 -05:00
"""
pass
2020-11-08 00:48:50 -05:00
###############################################################################
# pvc vm volume get
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " get " , short_help = " Get the volumes of a virtual machine. " )
@click.argument ( " domain " )
2020-11-08 00:48:50 -05:00
@click.option (
2021-11-06 03:02:43 -04:00
" -r " ,
" --raw " ,
" raw " ,
is_flag = True ,
default = False ,
help = " Display the raw values only without formatting. " ,
2020-11-08 00:48:50 -05:00
)
@cluster_req
def vm_volume_get ( domain , raw ) :
"""
Get the volumes of the virtual machine DOMAIN .
"""
retcode , retdata = pvc_vm . vm_volumes_get ( config , domain )
if not raw :
retmsg = pvc_vm . format_vm_volumes ( config , domain , retdata )
else :
volume_paths = list ( )
for volume in retdata :
volume_paths . append ( " {} : {} " . format ( volume [ 2 ] , volume [ 0 ] ) )
2021-11-06 03:02:43 -04:00
retmsg = " , " . join ( volume_paths )
2020-11-08 00:48:50 -05:00
cleanup ( retcode , retmsg )
###############################################################################
# pvc vm volume add
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " add " , short_help = " Add volume to a virtual machine. " )
@click.argument ( " domain " )
@click.argument ( " volume " )
2020-11-08 00:48:50 -05:00
@click.option (
2021-11-06 03:02:43 -04:00
" -d " ,
" --disk-id " ,
" disk_id " ,
default = None ,
help = " The disk ID in sdX/vdX/hdX format; if not specified, the next available will be used. " ,
2020-11-08 00:48:50 -05:00
)
@click.option (
2021-11-06 03:02:43 -04:00
" -b " ,
" --bus " ,
" bus " ,
default = " scsi " ,
show_default = True ,
type = click . Choice ( [ " scsi " , " ide " , " usb " , " virtio " ] ) ,
help = " The bus to attach the disk to; must be present in the VM. " ,
2020-11-08 00:48:50 -05:00
)
@click.option (
2021-11-06 03:02:43 -04:00
" -t " ,
" --type " ,
" disk_type " ,
default = " rbd " ,
show_default = True ,
type = click . Choice ( [ " rbd " , " file " ] ) ,
help = " The type of volume to add. " ,
2020-11-08 00:48:50 -05:00
)
@click.option (
2021-11-06 03:02:43 -04:00
" -l/-L " ,
" --live/--no-live " ,
" live_flag " ,
is_flag = True ,
default = True ,
help = " Immediately live-attach device to VM [default] or disable this behaviour. " ,
2021-09-12 15:41:05 -04:00
)
@click.option (
2021-11-06 03:02:43 -04:00
" -r " ,
" --restart " ,
" restart_flag " ,
is_flag = True ,
default = False ,
help = ' Immediately restart VM to apply new config; implies " --no-live " . ' ,
2020-11-08 00:48:50 -05:00
)
2021-04-08 12:57:40 -04:00
@click.option (
2021-11-06 03:02:43 -04:00
" -y " ,
" --yes " ,
" confirm_flag " ,
is_flag = True ,
default = False ,
help = " Confirm the restart " ,
2021-04-08 12:57:40 -04:00
)
2020-11-08 00:48:50 -05:00
@cluster_req
2021-11-06 03:02:43 -04:00
def vm_volume_add (
domain , volume , disk_id , bus , disk_type , live_flag , restart_flag , confirm_flag
) :
2020-11-08 00:48:50 -05:00
"""
Add the volume VOLUME to the virtual machine DOMAIN .
VOLUME may be either an absolute file path ( for type ' file ' ) or an RBD volume in the form " pool/volume " ( for type ' rbd ' ) . RBD volumes are verified against the cluster before adding and must exist .
"""
2021-09-12 15:41:05 -04:00
if restart_flag and live_flag :
2021-10-27 13:23:39 -04:00
live_flag = False
2021-09-12 15:41:05 -04:00
2021-11-06 03:02:43 -04:00
if restart_flag and not confirm_flag and not config [ " unsafe " ] :
2021-04-08 12:57:40 -04:00
try :
2021-11-06 03:02:43 -04:00
click . confirm (
" Restart VM {} " . format ( domain ) , prompt_suffix = " ? " , abort = True
)
2021-04-08 12:57:40 -04:00
except Exception :
2021-09-12 15:41:05 -04:00
restart_flag = False
2020-11-08 00:48:50 -05:00
2021-11-06 03:02:43 -04:00
retcode , retmsg = pvc_vm . vm_volumes_add (
config , domain , volume , disk_id , bus , disk_type , live_flag , restart_flag
)
2020-11-08 00:48:50 -05:00
cleanup ( retcode , retmsg )
###############################################################################
# pvc vm volume remove
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " remove " , short_help = " Remove volume from a virtual machine. " )
@click.argument ( " domain " )
@click.argument ( " volume " )
2020-11-08 00:48:50 -05:00
@click.option (
2021-11-06 03:02:43 -04:00
" -l/-L " ,
" --live/--no-live " ,
" live_flag " ,
is_flag = True ,
default = True ,
help = " Immediately live-detach device to VM [default] or disable this behaviour. " ,
2021-09-12 15:41:05 -04:00
)
@click.option (
2021-11-06 03:02:43 -04:00
" -r " ,
" --restart " ,
" restart_flag " ,
is_flag = True ,
default = False ,
help = ' Immediately restart VM to apply new config; implies " --no-live " . ' ,
2020-11-08 00:48:50 -05:00
)
2021-04-08 12:57:40 -04:00
@click.option (
2021-11-06 03:02:43 -04:00
" -y " ,
" --yes " ,
" confirm_flag " ,
is_flag = True ,
default = False ,
help = " Confirm the restart " ,
2021-04-08 12:57:40 -04:00
)
2020-11-08 00:48:50 -05:00
@cluster_req
2021-09-12 15:41:05 -04:00
def vm_volume_remove ( domain , volume , live_flag , restart_flag , confirm_flag ) :
2020-11-08 00:48:50 -05:00
"""
2021-06-22 04:31:02 -04:00
Remove VOLUME from the virtual machine DOMAIN ; VOLUME must be a file path or RBD path in ' pool/volume ' format .
2020-11-08 00:48:50 -05:00
"""
2021-09-12 15:41:05 -04:00
if restart_flag and live_flag :
2021-10-27 13:23:39 -04:00
live_flag = False
2021-09-12 15:41:05 -04:00
2021-11-06 03:02:43 -04:00
if restart_flag and not confirm_flag and not config [ " unsafe " ] :
2021-04-08 12:57:40 -04:00
try :
2021-11-06 03:02:43 -04:00
click . confirm (
" Restart VM {} " . format ( domain ) , prompt_suffix = " ? " , abort = True
)
2021-04-08 12:57:40 -04:00
except Exception :
2021-09-12 15:41:05 -04:00
restart_flag = False
2020-11-08 00:48:50 -05:00
2021-11-06 03:02:43 -04:00
retcode , retmsg = pvc_vm . vm_volumes_remove (
config , domain , volume , live_flag , restart_flag
)
2020-11-08 00:48:50 -05:00
cleanup ( retcode , retmsg )
2019-12-27 09:52:16 -05:00
###############################################################################
# pvc vm log
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " log " , short_help = " Show console logs of a VM object. " )
@click.argument ( " domain " )
2019-12-27 09:52:16 -05:00
@click.option (
2021-11-06 03:02:43 -04:00
" -l " ,
" --lines " ,
" lines " ,
default = None ,
show_default = False ,
help = " Display this many log lines from the end of the log buffer. [default: 1000; with follow: 10] " ,
2019-12-27 09:52:16 -05:00
)
@click.option (
2021-11-06 03:02:43 -04:00
" -f " ,
" --follow " ,
" follow " ,
is_flag = True ,
default = False ,
help = " Follow the log buffer; output may be delayed by a few seconds relative to the live system. The --lines value defaults to 10 for the initial output. " ,
2019-12-27 09:52:16 -05:00
)
2020-06-05 14:49:53 -04:00
@cluster_req
2019-12-27 09:52:16 -05:00
def vm_log ( domain , lines , follow ) :
"""
2020-01-08 10:34:27 -05:00
Show console logs of virtual machine DOMAIN on its current node in a pager or continuously . DOMAIN may be a UUID or name . Note that migrating a VM to a different node will cause the log buffer to be overwritten by entries from the new node .
2019-12-27 09:52:16 -05:00
"""
2020-11-03 11:14:49 -05:00
# Set the default here so we can handle it
if lines is None :
if follow :
lines = 10
else :
lines = 1000
2019-12-27 09:52:16 -05:00
if follow :
retcode , retmsg = pvc_vm . follow_console_log ( config , domain , lines )
else :
retcode , retmsg = pvc_vm . view_console_log ( config , domain , lines )
2020-01-08 10:06:34 -05:00
click . echo_via_pager ( retmsg )
2021-11-06 03:02:43 -04:00
retmsg = " "
2019-12-27 09:52:16 -05:00
cleanup ( retcode , retmsg )
2019-08-07 13:42:01 -04:00
2020-11-07 14:45:24 -05:00
2018-06-05 22:06:08 -04:00
###############################################################################
2018-06-11 01:24:14 -04:00
# pvc vm info
2018-06-05 22:06:08 -04:00
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " info " , short_help = " Show details of a VM object. " )
@click.argument ( " domain " )
2018-06-05 18:45:54 -04:00
@click.option (
2021-11-06 03:02:43 -04:00
" -l " ,
" --long " ,
" long_output " ,
is_flag = True ,
default = False ,
help = " Display more detailed information. " ,
2018-06-05 18:45:54 -04:00
)
2020-06-05 14:49:53 -04:00
@cluster_req
2018-06-16 22:22:07 -04:00
def vm_info ( domain , long_output ) :
2018-06-05 01:39:59 -04:00
"""
2020-01-08 10:34:27 -05:00
Show information about virtual machine DOMAIN . DOMAIN may be a UUID or name .
2018-06-05 01:39:59 -04:00
"""
2018-06-05 22:06:08 -04:00
2019-12-27 09:52:16 -05:00
retcode , retdata = pvc_vm . vm_info ( config , domain )
2019-05-20 22:15:28 -04:00
if retcode :
2020-01-05 12:35:00 -05:00
retdata = pvc_vm . format_info ( config , retdata , long_output )
2019-12-27 09:52:16 -05:00
cleanup ( retcode , retdata )
2018-06-05 01:39:59 -04:00
2020-11-07 14:45:24 -05:00
2019-04-11 19:06:06 -04:00
###############################################################################
2019-12-27 09:52:16 -05:00
# pvc vm dump
2019-04-11 19:06:06 -04:00
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " dump " , short_help = " Dump a virtual machine XML to stdout. " )
2021-06-13 22:32:54 -04:00
@click.option (
2021-11-06 03:02:43 -04:00
" -f " ,
" --file " ,
" filename " ,
default = None ,
type = click . File ( mode = " w " ) ,
help = " Write VM XML to this file. " ,
2019-04-11 19:06:06 -04:00
)
2021-11-06 03:02:43 -04:00
@click.argument ( " domain " )
2020-06-05 14:49:53 -04:00
@cluster_req
2021-06-13 22:32:54 -04:00
def vm_dump ( filename , domain ) :
2019-04-11 19:06:06 -04:00
"""
2019-12-27 09:52:16 -05:00
Dump the Libvirt XML definition of virtual machine DOMAIN to stdout . DOMAIN may be a UUID or name .
2019-04-11 19:06:06 -04:00
"""
2021-06-13 22:32:54 -04:00
retcode , retdata = pvc_vm . vm_info ( config , domain )
2021-11-06 03:02:43 -04:00
if not retcode or not retdata . get ( " name " , None ) :
2020-01-04 14:06:36 -05:00
cleanup ( False , ' ERROR: Could not find VM " {} " ! ' . format ( domain ) )
2019-12-27 09:52:16 -05:00
2021-11-06 03:02:43 -04:00
current_vm_cfg_raw = retdata . get ( " xml " )
2019-12-27 09:52:16 -05:00
xml_data = etree . fromstring ( current_vm_cfg_raw )
2021-11-06 03:02:43 -04:00
current_vm_cfgfile = etree . tostring ( xml_data , pretty_print = True ) . decode ( " utf8 " )
2021-06-13 22:32:54 -04:00
xml = current_vm_cfgfile . strip ( )
if filename is not None :
filename . write ( xml )
cleanup ( retcode , ' VM XML written to " {} " . ' . format ( filename . name ) )
else :
cleanup ( retcode , xml )
2019-04-11 19:06:06 -04:00
2020-11-07 14:45:24 -05:00
2018-06-10 20:21:00 -04:00
###############################################################################
2018-06-11 01:24:14 -04:00
# pvc vm list
2018-06-10 20:21:00 -04:00
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " list " , short_help = " List all VM objects. " )
@click.argument ( " limit " , default = None , required = False )
2018-06-11 01:24:14 -04:00
@click.option (
2021-11-06 03:02:43 -04:00
" -t " ,
" --target " ,
" target_node " ,
default = None ,
help = " Limit list to VMs on the specified node. " ,
2019-03-20 11:31:54 -04:00
)
@click.option (
2021-11-06 03:02:43 -04:00
" -s " ,
" --state " ,
" target_state " ,
default = None ,
help = " Limit list to VMs in the specified state. " ,
2018-06-11 01:24:14 -04:00
)
2021-07-14 00:51:48 -04:00
@click.option (
2021-11-06 03:02:43 -04:00
" -g " ,
" --tag " ,
" target_tag " ,
default = None ,
help = " Limit list to VMs with the specified tag. " ,
2021-07-14 00:51:48 -04:00
)
2019-03-12 21:30:01 -04:00
@click.option (
2021-11-06 03:02:43 -04:00
" -r " ,
" --raw " ,
" raw " ,
is_flag = True ,
default = False ,
help = " Display the raw list of VM names only. " ,
2019-03-12 21:30:01 -04:00
)
2021-10-07 11:13:30 -04:00
@click.option (
2021-11-06 03:02:43 -04:00
" -n " ,
" --negate " ,
" negate " ,
is_flag = True ,
default = False ,
help = " Negate the specified node, state, or tag limit(s). " ,
2021-10-07 11:13:30 -04:00
)
2020-06-05 14:49:53 -04:00
@cluster_req
2021-10-07 11:13:30 -04:00
def vm_list ( target_node , target_state , target_tag , limit , raw , negate ) :
2018-07-18 22:58:41 -04:00
"""
2021-07-09 11:51:20 -04:00
List all virtual machines ; optionally only match names or full UUIDs matching regex LIMIT .
2018-10-20 15:27:07 -04:00
NOTE : Red - coloured network lists indicate one or more configured networks are missing / invalid .
2018-07-18 22:58:41 -04:00
"""
2021-11-06 03:02:43 -04:00
retcode , retdata = pvc_vm . vm_list (
config , limit , target_node , target_state , target_tag , negate
)
2019-05-20 22:15:28 -04:00
if retcode :
2020-01-05 12:35:00 -05:00
retdata = pvc_vm . format_list ( config , retdata , raw )
2020-07-11 11:38:13 -04:00
else :
if raw :
retdata = " "
2019-12-27 09:52:16 -05:00
cleanup ( retcode , retdata )
2018-06-10 20:21:00 -04:00
2020-11-07 14:45:24 -05:00
2018-09-21 23:43:30 -04:00
###############################################################################
# pvc network
###############################################################################
2021-11-06 03:02:43 -04:00
@click.group (
name = " network " ,
short_help = " Manage a PVC virtual network. " ,
context_settings = CONTEXT_SETTINGS ,
)
2018-09-21 23:43:30 -04:00
def cli_network ( ) :
"""
Manage the state of a VXLAN network in the PVC cluster .
"""
2020-11-07 14:45:24 -05:00
pass
2018-09-21 23:43:30 -04:00
###############################################################################
# pvc network add
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " add " , short_help = " Add a new virtual network. " )
2018-09-21 23:43:30 -04:00
@click.option (
2021-11-06 03:02:43 -04:00
" -d " ,
" --description " ,
" description " ,
2018-10-17 00:23:27 -04:00
required = True ,
2021-11-06 03:02:43 -04:00
help = " Description of the network; must be unique and not contain whitespace. " ,
2018-09-28 20:42:24 -04:00
)
@click.option (
2021-11-06 03:02:43 -04:00
" -p " ,
" --type " ,
" nettype " ,
2018-09-28 20:42:24 -04:00
required = True ,
2021-11-06 03:02:43 -04:00
type = click . Choice ( [ " managed " , " bridged " ] ) ,
help = " Network type; managed networks control IP addressing; bridged networks are simple vLAN bridges. All subsequent options are unused for bridged networks. " ,
2019-03-15 11:28:49 -04:00
)
2021-11-06 03:02:43 -04:00
@click.option ( " -m " , " --mtu " , " mtu " , default = " " , help = " MTU of the network interfaces. " )
2021-10-09 18:05:26 -04:00
@click.option (
2021-11-06 03:02:43 -04:00
" -n " , " --domain " , " domain " , default = None , help = " Domain name of the network. "
2018-09-21 23:43:30 -04:00
)
2019-12-08 23:32:03 -05:00
@click.option (
2021-11-06 03:02:43 -04:00
" --dns-server " ,
" name_servers " ,
2019-12-08 23:32:03 -05:00
multiple = True ,
2021-11-06 03:02:43 -04:00
help = " DNS nameserver for network; multiple entries may be specified. " ,
2019-12-08 23:32:03 -05:00
)
2018-09-21 23:43:30 -04:00
@click.option (
2021-11-06 03:02:43 -04:00
" -i " ,
" --ipnet " ,
" ip_network " ,
2018-11-13 01:22:15 -05:00
default = None ,
2021-11-06 03:02:43 -04:00
help = " CIDR-format IPv4 network address for subnet. " ,
2018-11-13 01:22:15 -05:00
)
@click.option (
2021-11-06 03:02:43 -04:00
" -i6 " ,
" --ipnet6 " ,
" ip6_network " ,
2018-11-13 01:22:15 -05:00
default = None ,
2021-11-06 03:02:43 -04:00
help = ' CIDR-format IPv6 network address for subnet; should be /64 or larger ending " ::/YY " . ' ,
2018-09-21 23:43:30 -04:00
)
@click.option (
2021-11-06 03:02:43 -04:00
" -g " ,
" --gateway " ,
" ip_gateway " ,
2018-11-13 01:22:15 -05:00
default = None ,
2021-11-06 03:02:43 -04:00
help = " Default IPv4 gateway address for subnet. " ,
2018-11-13 01:22:15 -05:00
)
@click.option (
2021-11-06 03:02:43 -04:00
" -g6 " ,
" --gateway6 " ,
" ip6_gateway " ,
2018-11-13 01:22:15 -05:00
default = None ,
2021-11-06 03:02:43 -04:00
help = ' Default IPv6 gateway address for subnet. [default: " X::1 " ] ' ,
2018-09-21 23:43:30 -04:00
)
@click.option (
2021-11-06 03:02:43 -04:00
" --dhcp/--no-dhcp " ,
" dhcp_flag " ,
2018-09-21 23:43:30 -04:00
is_flag = True ,
2019-03-15 11:28:49 -04:00
default = False ,
2021-11-06 03:02:43 -04:00
help = " Enable/disable IPv4 DHCP for clients on subnet. " ,
2018-09-21 23:43:30 -04:00
)
2018-09-29 02:54:48 -04:00
@click.option (
2021-11-06 03:02:43 -04:00
" --dhcp-start " , " dhcp_start " , default = None , help = " IPv4 DHCP range start address. "
2018-09-29 02:54:48 -04:00
)
@click.option (
2021-11-06 03:02:43 -04:00
" --dhcp-end " , " dhcp_end " , default = None , help = " IPv4 DHCP range end address. "
2018-09-21 23:43:30 -04:00
)
2021-11-06 03:02:43 -04:00
@click.argument ( " vni " )
2020-06-05 14:49:53 -04:00
@cluster_req
2021-11-06 03:02:43 -04:00
def net_add (
vni ,
description ,
nettype ,
mtu ,
domain ,
ip_network ,
ip_gateway ,
ip6_network ,
ip6_gateway ,
dhcp_flag ,
dhcp_start ,
dhcp_end ,
name_servers ,
) :
2018-09-21 23:43:30 -04:00
"""
2020-01-04 14:06:36 -05:00
Add a new virtual network with VXLAN identifier VNI .
2018-09-21 23:43:30 -04:00
2021-10-09 18:05:26 -04:00
NOTE : The MTU must be equal to , or less than , the underlying device MTU ( either the node ' bridge_mtu ' for bridged networks , or the node ' cluster_mtu ' minus 50 for managed networks ) . Is only required if the device MTU should be lower than the underlying physical device MTU for compatibility . If unset , defaults to the underlying device MTU which will be set explcitly when the network is added to the nodes .
2019-03-15 11:28:49 -04:00
Examples :
2020-08-05 10:35:41 -04:00
pvc network add 101 - - description my - bridged - net - - type bridged
2019-03-15 11:28:49 -04:00
> Creates vLAN 101 and a simple bridge on the VNI dev interface .
2019-12-30 13:29:07 -05:00
2020-08-05 10:35:41 -04:00
pvc network add 1001 - - description my - managed - net - - type managed - - domain test . local - - ipnet 10.1 .1 .0 / 24 - - gateway 10.1 .1 .1
2019-03-15 11:28:49 -04:00
> Creates a VXLAN with ID 1001 on the VNI dev interface , with IPv4 managed networking .
2018-11-13 01:22:15 -05:00
IPv6 is fully supported with - - ipnet6 and - - gateway6 in addition to or instead of IPv4 . PVC will configure DHCPv6 in a semi - managed configuration for the network if set .
2018-09-21 23:43:30 -04:00
"""
2021-11-06 03:02:43 -04:00
retcode , retmsg = pvc_network . net_add (
config ,
vni ,
description ,
nettype ,
mtu ,
domain ,
name_servers ,
ip_network ,
ip_gateway ,
ip6_network ,
ip6_gateway ,
dhcp_flag ,
dhcp_start ,
dhcp_end ,
)
2019-12-29 16:13:32 -05:00
cleanup ( retcode , retmsg )
2018-09-21 23:43:30 -04:00
2020-11-07 14:45:24 -05:00
2018-09-23 15:26:20 -04:00
###############################################################################
# pvc network modify
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " modify " , short_help = " Modify an existing virtual network. " )
2021-10-09 18:05:26 -04:00
@click.option (
2021-11-06 03:02:43 -04:00
" -d " ,
" --description " ,
" description " ,
2021-10-09 18:05:26 -04:00
default = None ,
2021-11-06 03:02:43 -04:00
help = " Description of the network; must be unique and not contain whitespace. " ,
2021-10-09 18:05:26 -04:00
)
2021-11-06 03:02:43 -04:00
@click.option ( " -m " , " --mtu " , " mtu " , default = None , help = " MTU of the network interfaces. " )
2018-10-03 20:22:42 -04:00
@click.option (
2021-11-06 03:02:43 -04:00
" -n " , " --domain " , " domain " , default = None , help = " Domain name of the network. "
2018-10-03 20:22:42 -04:00
)
2019-12-08 23:32:03 -05:00
@click.option (
2021-11-06 03:02:43 -04:00
" --dns-server " ,
" name_servers " ,
2019-12-08 23:32:03 -05:00
multiple = True ,
2021-11-06 03:02:43 -04:00
help = " DNS nameserver for network; multiple entries may be specified (will overwrite all previous entries). " ,
2019-12-08 23:32:03 -05:00
)
2018-09-23 15:26:20 -04:00
@click.option (
2021-11-06 03:02:43 -04:00
" -i " ,
" --ipnet " ,
" ip4_network " ,
2018-09-23 15:26:20 -04:00
default = None ,
2021-11-06 03:02:43 -04:00
help = ' CIDR-format IPv4 network address for subnet; disable with " " . ' ,
2018-11-13 01:22:15 -05:00
)
@click.option (
2021-11-06 03:02:43 -04:00
" -i6 " ,
" --ipnet6 " ,
" ip6_network " ,
2018-11-13 01:22:15 -05:00
default = None ,
2021-11-06 03:02:43 -04:00
help = ' CIDR-format IPv6 network address for subnet; disable with " " . ' ,
2018-09-23 15:26:20 -04:00
)
@click.option (
2021-11-06 03:02:43 -04:00
" -g " ,
" --gateway " ,
" ip4_gateway " ,
2018-09-23 15:26:20 -04:00
default = None ,
2021-11-06 03:02:43 -04:00
help = ' Default IPv4 gateway address for subnet; disable with " " . ' ,
2018-11-13 01:22:15 -05:00
)
@click.option (
2021-11-06 03:02:43 -04:00
" -g6 " ,
" --gateway6 " ,
" ip6_gateway " ,
2018-11-13 01:22:15 -05:00
default = None ,
2021-11-06 03:02:43 -04:00
help = ' Default IPv6 gateway address for subnet; disable with " " . ' ,
2018-09-23 15:26:20 -04:00
)
@click.option (
2021-11-06 03:02:43 -04:00
" --dhcp/--no-dhcp " ,
" dhcp_flag " ,
2018-09-23 15:26:20 -04:00
is_flag = True ,
2018-10-17 00:23:27 -04:00
default = None ,
2021-11-06 03:02:43 -04:00
help = " Enable/disable DHCPv4 for clients on subnet (DHCPv6 is always enabled if DHCPv6 network is set). " ,
2018-10-03 20:22:42 -04:00
)
@click.option (
2021-11-06 03:02:43 -04:00
" --dhcp-start " , " dhcp_start " , default = None , help = " DHCPvr range start address. "
2018-09-23 15:26:20 -04:00
)
2021-11-06 03:02:43 -04:00
@click.option ( " --dhcp-end " , " dhcp_end " , default = None , help = " DHCPv4 range end address. " )
@click.argument ( " vni " )
2020-06-05 14:49:53 -04:00
@cluster_req
2021-11-06 03:02:43 -04:00
def net_modify (
vni ,
description ,
mtu ,
domain ,
name_servers ,
ip6_network ,
ip6_gateway ,
ip4_network ,
ip4_gateway ,
dhcp_flag ,
dhcp_start ,
dhcp_end ,
) :
2018-09-23 15:26:20 -04:00
"""
Modify details of virtual network VNI . All fields optional ; only specified fields will be updated .
2021-10-09 18:05:26 -04:00
NOTE : The MTU must be equal to , or less than , the underlying device MTU ( either the node ' bridge_mtu ' for bridged networks , or the node ' cluster_mtu ' minus 50 for managed networks ) . Is only required if the device MTU should be lower than the underlying physical device MTU for compatibility . To reset an explicit MTU to the default underlying device MTU , specify ' --mtu ' with a quoted empty string argument .
2018-09-23 15:26:20 -04:00
Example :
2021-04-12 15:55:59 -04:00
2018-10-03 20:22:42 -04:00
pvc network modify 1001 - - gateway 10.1 .1 .1 - - dhcp
2018-09-23 15:26:20 -04:00
"""
2021-11-06 03:02:43 -04:00
retcode , retmsg = pvc_network . net_modify (
config ,
vni ,
description ,
mtu ,
domain ,
name_servers ,
ip4_network ,
ip4_gateway ,
ip6_network ,
ip6_gateway ,
dhcp_flag ,
dhcp_start ,
dhcp_end ,
)
2019-12-29 16:13:32 -05:00
cleanup ( retcode , retmsg )
2018-09-23 15:26:20 -04:00
2020-11-07 14:45:24 -05:00
2018-09-21 23:43:30 -04:00
###############################################################################
# pvc network remove
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " remove " , short_help = " Remove a virtual network. " )
@click.argument ( " net " )
2020-01-08 10:34:27 -05:00
@click.option (
2021-11-06 03:02:43 -04:00
" -y " ,
" --yes " ,
" confirm_flag " ,
is_flag = True ,
default = False ,
help = " Confirm the removal " ,
2020-01-08 10:34:27 -05:00
)
2020-06-05 14:49:53 -04:00
@cluster_req
2020-01-08 10:34:27 -05:00
def net_remove ( net , confirm_flag ) :
2018-09-21 23:43:30 -04:00
"""
2020-01-04 14:06:36 -05:00
Remove an existing virtual network NET ; NET must be a VNI .
2018-09-21 23:43:30 -04:00
WARNING : PVC does not verify whether clients are still present in this network . Before removing , ensure
that all client VMs have been removed from the network or undefined behaviour may occur .
"""
2021-11-06 03:02:43 -04:00
if not confirm_flag and not config [ " unsafe " ] :
2020-01-08 10:34:27 -05:00
try :
2021-11-06 03:02:43 -04:00
click . confirm (
" Remove network {} " . format ( net ) , prompt_suffix = " ? " , abort = True
)
2020-11-06 18:55:10 -05:00
except Exception :
2020-01-08 10:34:27 -05:00
exit ( 0 )
2018-09-21 23:43:30 -04:00
2019-12-29 16:13:32 -05:00
retcode , retmsg = pvc_network . net_remove ( config , net )
cleanup ( retcode , retmsg )
2018-09-21 23:43:30 -04:00
2020-11-07 14:45:24 -05:00
2018-09-21 23:43:30 -04:00
###############################################################################
# pvc network info
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " info " , short_help = " Show details of a network. " )
@click.argument ( " vni " )
2018-09-25 01:32:03 -04:00
@click.option (
2021-11-06 03:02:43 -04:00
" -l " ,
" --long " ,
" long_output " ,
is_flag = True ,
default = False ,
help = " Display more detailed information. " ,
2018-09-25 01:32:03 -04:00
)
2020-06-05 14:49:53 -04:00
@cluster_req
2018-09-25 01:32:03 -04:00
def net_info ( vni , long_output ) :
2018-09-21 23:43:30 -04:00
"""
2020-01-08 10:34:27 -05:00
Show information about virtual network VNI .
2018-09-21 23:43:30 -04:00
"""
2019-12-29 16:13:32 -05:00
retcode , retdata = pvc_network . net_info ( config , vni )
2019-07-04 23:01:22 -04:00
if retcode :
2020-01-05 12:35:00 -05:00
retdata = pvc_network . format_info ( config , retdata , long_output )
2019-12-29 16:13:32 -05:00
cleanup ( retcode , retdata )
2018-09-21 23:43:30 -04:00
2020-11-07 14:45:24 -05:00
2018-09-21 23:43:30 -04:00
###############################################################################
# pvc network list
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " list " , short_help = " List all VM objects. " )
@click.argument ( " limit " , default = None , required = False )
2020-06-05 14:49:53 -04:00
@cluster_req
2018-09-21 23:43:30 -04:00
def net_list ( limit ) :
"""
2020-01-04 14:06:36 -05:00
List all virtual networks ; optionally only match VNIs or Descriptions matching regex LIMIT .
2018-09-21 23:43:30 -04:00
"""
2019-12-29 16:13:32 -05:00
retcode , retdata = pvc_network . net_list ( config , limit )
2019-07-04 23:01:22 -04:00
if retcode :
2020-01-05 12:35:00 -05:00
retdata = pvc_network . format_list ( config , retdata )
2019-12-29 16:13:32 -05:00
cleanup ( retcode , retdata )
2018-09-21 23:43:30 -04:00
2020-11-07 14:45:24 -05:00
2018-09-28 20:31:56 -04:00
###############################################################################
# pvc network dhcp
###############################################################################
2021-11-06 03:02:43 -04:00
@click.group (
name = " dhcp " ,
short_help = " Manage IPv4 DHCP leases in a PVC virtual network. " ,
context_settings = CONTEXT_SETTINGS ,
)
2018-09-28 20:31:56 -04:00
def net_dhcp ( ) :
"""
2018-11-13 01:22:15 -05:00
Manage host IPv4 DHCP leases of a VXLAN network in the PVC cluster .
2018-09-28 20:31:56 -04:00
"""
2020-11-07 14:45:24 -05:00
pass
2018-09-28 20:31:56 -04:00
2018-10-03 19:23:46 -04:00
###############################################################################
2019-12-29 16:13:32 -05:00
# pvc network dhcp add
2018-10-03 19:23:46 -04:00
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " add " , short_help = " Add a DHCP static reservation. " )
@click.argument ( " net " )
@click.argument ( " ipaddr " )
@click.argument ( " hostname " )
@click.argument ( " macaddr " )
2020-06-05 14:49:53 -04:00
@cluster_req
2019-12-29 16:13:32 -05:00
def net_dhcp_add ( net , ipaddr , macaddr , hostname ) :
2018-09-28 20:31:56 -04:00
"""
2019-12-29 16:13:32 -05:00
Add a new DHCP static reservation of IP address IPADDR with hostname HOSTNAME for MAC address MACADDR to virtual network NET ; NET must be a VNI .
2018-09-28 20:31:56 -04:00
"""
2019-12-29 16:13:32 -05:00
retcode , retmsg = pvc_network . net_dhcp_add ( config , net , ipaddr , macaddr , hostname )
cleanup ( retcode , retmsg )
2018-09-28 20:31:56 -04:00
2020-11-07 14:45:24 -05:00
2018-09-28 20:31:56 -04:00
###############################################################################
2019-12-29 16:13:32 -05:00
# pvc network dhcp remove
2018-09-28 20:31:56 -04:00
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " remove " , short_help = " Remove a DHCP static reservation. " )
@click.argument ( " net " )
@click.argument ( " macaddr " )
2020-01-08 10:34:27 -05:00
@click.option (
2021-11-06 03:02:43 -04:00
" -y " ,
" --yes " ,
" confirm_flag " ,
is_flag = True ,
default = False ,
help = " Confirm the removal " ,
2020-01-08 10:34:27 -05:00
)
2020-06-05 14:49:53 -04:00
@cluster_req
2020-01-08 10:34:27 -05:00
def net_dhcp_remove ( net , macaddr , confirm_flag ) :
2018-09-28 20:31:56 -04:00
"""
2020-01-08 10:34:27 -05:00
Remove a DHCP lease for MACADDR from virtual network NET ; NET must be a VNI .
2018-09-28 20:31:56 -04:00
"""
2021-11-06 03:02:43 -04:00
if not confirm_flag and not config [ " unsafe " ] :
2020-01-08 10:34:27 -05:00
try :
2021-11-06 03:02:43 -04:00
click . confirm (
" Remove DHCP lease for {} in network {} " . format ( macaddr , net ) ,
prompt_suffix = " ? " ,
abort = True ,
)
2020-11-06 18:55:10 -05:00
except Exception :
2020-01-08 10:34:27 -05:00
exit ( 0 )
2018-09-28 20:31:56 -04:00
2020-01-05 00:49:50 -05:00
retcode , retmsg = pvc_network . net_dhcp_remove ( config , net , macaddr )
2019-12-29 16:13:32 -05:00
cleanup ( retcode , retmsg )
2018-09-28 20:31:56 -04:00
2020-11-07 14:45:24 -05:00
2018-09-28 20:31:56 -04:00
###############################################################################
2019-12-29 16:13:32 -05:00
# pvc network dhcp list
2018-09-28 20:31:56 -04:00
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " list " , short_help = " List active DHCP leases. " )
@click.argument ( " net " )
@click.argument ( " limit " , default = None , required = False )
2019-12-29 16:13:32 -05:00
@click.option (
2021-11-06 03:02:43 -04:00
" -s " ,
" --static " ,
" only_static " ,
is_flag = True ,
default = False ,
help = " Show only static leases. " ,
2019-12-29 16:13:32 -05:00
)
2020-06-05 14:49:53 -04:00
@cluster_req
2019-12-29 16:13:32 -05:00
def net_dhcp_list ( net , limit , only_static ) :
2018-09-28 20:31:56 -04:00
"""
2019-12-29 16:13:32 -05:00
List all DHCP leases in virtual network NET ; optionally only match elements matching regex LIMIT ; NET must be a VNI .
2018-09-28 20:31:56 -04:00
"""
2019-12-29 16:13:32 -05:00
retcode , retdata = pvc_network . net_dhcp_list ( config , net , limit , only_static )
2019-07-04 23:01:22 -04:00
if retcode :
2020-01-05 12:35:00 -05:00
retdata = pvc_network . format_list_dhcp ( retdata )
2019-12-29 16:13:32 -05:00
cleanup ( retcode , retdata )
2018-09-28 20:31:56 -04:00
2020-11-07 14:45:24 -05:00
2018-09-28 20:31:56 -04:00
###############################################################################
# pvc network acl
###############################################################################
2021-11-06 03:02:43 -04:00
@click.group (
name = " acl " ,
short_help = " Manage a PVC virtual network firewall ACL rule. " ,
context_settings = CONTEXT_SETTINGS ,
)
2018-09-28 20:31:56 -04:00
def net_acl ( ) :
"""
Manage firewall ACLs of a VXLAN network in the PVC cluster .
"""
2020-11-07 14:45:24 -05:00
pass
2018-09-21 23:43:30 -04:00
2018-10-17 00:23:27 -04:00
###############################################################################
# pvc network acl add
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " add " , short_help = " Add firewall ACL. " )
2018-10-17 00:23:27 -04:00
@click.option (
2021-11-06 03:02:43 -04:00
" --in/--out " ,
" direction " ,
2018-10-17 00:23:27 -04:00
is_flag = True ,
2020-11-07 13:11:03 -05:00
default = True , # inbound
2021-11-06 03:02:43 -04:00
help = " Inbound or outbound ruleset. " ,
2018-10-17 00:23:27 -04:00
)
@click.option (
2021-11-06 03:02:43 -04:00
" -d " ,
" --description " ,
" description " ,
2018-10-17 00:23:27 -04:00
required = True ,
2021-11-06 03:02:43 -04:00
help = " Description of the ACL; must be unique and not contain whitespace. " ,
2018-10-17 00:23:27 -04:00
)
2021-11-06 03:02:43 -04:00
@click.option ( " -r " , " --rule " , " rule " , required = True , help = " NFT firewall rule. " )
2018-10-17 00:23:27 -04:00
@click.option (
2021-11-06 03:02:43 -04:00
" -o " ,
" --order " ,
" order " ,
2018-10-17 00:23:27 -04:00
default = None ,
2021-11-06 03:02:43 -04:00
help = ' Order of rule in the chain (see " list " ); defaults to last. ' ,
2018-10-17 00:23:27 -04:00
)
2021-11-06 03:02:43 -04:00
@click.argument ( " net " )
2020-06-05 14:49:53 -04:00
@cluster_req
2018-10-17 00:23:27 -04:00
def net_acl_add ( net , direction , description , rule , order ) :
"""
2019-12-29 16:13:32 -05:00
Add a new NFT firewall rule to network NET ; the rule is a literal NFT rule belonging to the forward table for the client network ; NET must be a VNI .
2018-10-17 00:23:27 -04:00
NOTE : All client networks are default - allow in both directions ; deny rules MUST be added here at the end of the sequence for a default - deny setup .
NOTE : Ordering places the rule at the specified ID , not before it ; the old rule of that ID and all subsequent rules will be moved down .
2019-12-29 16:13:32 -05:00
NOTE : Descriptions are used as names , and must be unique within a network ( both directions ) .
2018-10-17 00:23:27 -04:00
Example :
pvc network acl add 1001 - - in - - rule " tcp dport 22 ct state new accept " - - description " ssh-in " - - order 3
"""
2019-12-29 16:13:32 -05:00
if direction :
2021-11-06 03:02:43 -04:00
direction = " in "
2019-12-29 16:13:32 -05:00
else :
2021-11-06 03:02:43 -04:00
direction = " out "
2018-10-17 00:23:27 -04:00
2021-11-06 03:02:43 -04:00
retcode , retmsg = pvc_network . net_acl_add (
config , net , direction , description , rule , order
)
2019-12-29 16:13:32 -05:00
cleanup ( retcode , retmsg )
2018-10-17 00:23:27 -04:00
2020-11-07 14:45:24 -05:00
2018-10-17 00:23:27 -04:00
###############################################################################
# pvc network acl remove
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " remove " , short_help = " Remove firewall ACL. " )
@click.argument ( " net " )
2018-10-17 00:23:27 -04:00
@click.argument (
2021-11-06 03:02:43 -04:00
" rule " ,
2018-10-17 00:23:27 -04:00
)
2020-01-08 10:34:27 -05:00
@click.option (
2021-11-06 03:02:43 -04:00
" -y " ,
" --yes " ,
" confirm_flag " ,
is_flag = True ,
default = False ,
help = " Confirm the removal " ,
2020-01-08 10:34:27 -05:00
)
2020-06-05 14:49:53 -04:00
@cluster_req
2020-01-08 10:34:27 -05:00
def net_acl_remove ( net , rule , confirm_flag ) :
2018-10-17 00:23:27 -04:00
"""
2019-12-29 16:13:32 -05:00
Remove an NFT firewall rule RULE from network NET ; RULE must be a description ; NET must be a VNI .
2018-10-17 00:23:27 -04:00
"""
2021-11-06 03:02:43 -04:00
if not confirm_flag and not config [ " unsafe " ] :
2020-01-08 10:34:27 -05:00
try :
2021-11-06 03:02:43 -04:00
click . confirm (
" Remove ACL {} in network {} " . format ( rule , net ) ,
prompt_suffix = " ? " ,
abort = True ,
)
2020-11-06 18:55:10 -05:00
except Exception :
2020-01-08 10:34:27 -05:00
exit ( 0 )
2018-10-17 00:23:27 -04:00
2019-12-29 16:13:32 -05:00
retcode , retmsg = pvc_network . net_acl_remove ( config , net , rule )
cleanup ( retcode , retmsg )
2018-10-17 00:23:27 -04:00
###############################################################################
# pvc network acl list
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " list " , short_help = " List firewall ACLs. " )
2018-10-17 00:23:27 -04:00
@click.option (
2021-11-06 03:02:43 -04:00
" --in/--out " ,
" direction " ,
2018-10-17 00:23:27 -04:00
is_flag = True ,
2018-10-17 20:05:22 -04:00
required = False ,
2018-10-17 00:23:27 -04:00
default = None ,
2021-11-06 03:02:43 -04:00
help = " Inbound or outbound rule set only. " ,
2018-10-17 00:23:27 -04:00
)
2021-11-06 03:02:43 -04:00
@click.argument ( " net " )
@click.argument ( " limit " , default = None , required = False )
2020-06-05 14:49:53 -04:00
@cluster_req
2018-10-17 00:23:27 -04:00
def net_acl_list ( net , limit , direction ) :
"""
List all NFT firewall rules in network NET ; optionally only match elements matching description regex LIMIT ; NET can be either a VNI or description .
"""
2019-12-29 16:13:32 -05:00
if direction is not None :
if direction :
2021-11-06 03:02:43 -04:00
direction = " in "
2019-12-29 16:13:32 -05:00
else :
2021-11-06 03:02:43 -04:00
direction = " out "
2018-09-21 23:43:30 -04:00
2019-12-29 16:13:32 -05:00
retcode , retdata = pvc_network . net_acl_list ( config , net , limit , direction )
2019-07-04 23:01:22 -04:00
if retcode :
2020-01-05 12:35:00 -05:00
retdata = pvc_network . format_list_acl ( retdata )
2019-12-29 16:13:32 -05:00
cleanup ( retcode , retdata )
2018-09-21 23:43:30 -04:00
2020-11-07 14:45:24 -05:00
2021-06-21 17:12:53 -04:00
###############################################################################
# pvc network sriov
###############################################################################
2021-11-06 03:02:43 -04:00
@click.group (
name = " sriov " ,
short_help = " Manage SR-IOV network resources. " ,
context_settings = CONTEXT_SETTINGS ,
)
2021-06-21 17:12:53 -04:00
def net_sriov ( ) :
"""
Manage SR - IOV network resources on nodes ( PFs and VFs ) .
"""
pass
###############################################################################
# pvc network sriov pf
###############################################################################
2021-11-06 03:02:43 -04:00
@click.group (
name = " pf " , short_help = " Manage PF devices. " , context_settings = CONTEXT_SETTINGS
)
2021-06-21 17:12:53 -04:00
def net_sriov_pf ( ) :
"""
Manage SR - IOV PF devices on nodes .
"""
pass
###############################################################################
# pvc network sriov pf list
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " list " , short_help = " List PF devices. " )
@click.argument ( " node " )
2021-06-21 17:12:53 -04:00
@cluster_req
def net_sriov_pf_list ( node ) :
"""
List all SR - IOV PFs on NODE .
"""
retcode , retdata = pvc_network . net_sriov_pf_list ( config , node )
if retcode :
retdata = pvc_network . format_list_sriov_pf ( retdata )
cleanup ( retcode , retdata )
###############################################################################
# pvc network sriov vf
###############################################################################
2021-11-06 03:02:43 -04:00
@click.group (
name = " vf " , short_help = " Manage VF devices. " , context_settings = CONTEXT_SETTINGS
)
2021-06-21 17:12:53 -04:00
def net_sriov_vf ( ) :
"""
Manage SR - IOV VF devices on nodes .
"""
pass
###############################################################################
# pvc network sriov vf set
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " set " , short_help = " Set VF device properties. " )
2021-06-21 18:40:11 -04:00
@click.option (
2021-11-06 03:02:43 -04:00
" --vlan-id " ,
" vlan_id " ,
default = None ,
show_default = False ,
help = " The vLAN ID for vLAN tagging. " ,
2021-06-21 18:40:11 -04:00
)
@click.option (
2021-11-06 03:02:43 -04:00
" --qos-prio " ,
" vlan_qos " ,
default = None ,
show_default = False ,
help = " The vLAN QOS priority. " ,
2021-06-21 18:40:11 -04:00
)
@click.option (
2021-11-06 03:02:43 -04:00
" --tx-min " ,
" tx_rate_min " ,
default = None ,
show_default = False ,
help = " The minimum TX rate. " ,
2021-06-21 18:40:11 -04:00
)
@click.option (
2021-11-06 03:02:43 -04:00
" --tx-max " ,
" tx_rate_max " ,
default = None ,
show_default = False ,
help = " The maximum TX rate. " ,
2021-06-21 18:40:11 -04:00
)
@click.option (
2021-11-06 03:02:43 -04:00
" --link-state " ,
" link_state " ,
default = None ,
show_default = False ,
type = click . Choice ( [ " auto " , " enable " , " disable " ] ) ,
help = " The administrative link state. " ,
2021-06-21 18:40:11 -04:00
)
@click.option (
2021-11-06 03:02:43 -04:00
" --spoof-check/--no-spoof-check " ,
" spoof_check " ,
is_flag = True ,
default = None ,
show_default = False ,
help = " Enable or disable spoof checking. " ,
2021-06-21 18:40:11 -04:00
)
@click.option (
2021-11-06 03:02:43 -04:00
" --trust/--no-trust " ,
" trust " ,
is_flag = True ,
default = None ,
show_default = False ,
help = " Enable or disable VF user trust. " ,
2021-06-21 18:40:11 -04:00
)
@click.option (
2021-11-06 03:02:43 -04:00
" --query-rss/--no-query-rss " ,
" query_rss " ,
is_flag = True ,
default = None ,
show_default = False ,
help = " Enable or disable query RSS support. " ,
2021-06-21 17:12:53 -04:00
)
2021-11-06 03:02:43 -04:00
@click.argument ( " node " )
@click.argument ( " vf " )
2021-06-21 17:12:53 -04:00
@cluster_req
2021-11-06 03:02:43 -04:00
def net_sriov_vf_set (
node ,
vf ,
vlan_id ,
vlan_qos ,
tx_rate_min ,
tx_rate_max ,
link_state ,
spoof_check ,
trust ,
query_rss ,
) :
2021-06-21 17:12:53 -04:00
"""
Set a property of SR - IOV VF on NODE .
"""
2021-11-06 03:02:43 -04:00
if (
vlan_id is None
and vlan_qos is None
and tx_rate_min is None
and tx_rate_max is None
and link_state is None
and spoof_check is None
and trust is None
and query_rss is None
) :
cleanup (
False , " At least one configuration property must be specified to update. "
)
2021-06-21 18:40:11 -04:00
2021-11-06 03:02:43 -04:00
retcode , retmsg = pvc_network . net_sriov_vf_set (
config ,
node ,
vf ,
vlan_id ,
vlan_qos ,
tx_rate_min ,
tx_rate_max ,
link_state ,
spoof_check ,
trust ,
query_rss ,
)
2021-06-21 18:40:11 -04:00
cleanup ( retcode , retmsg )
2021-06-21 17:12:53 -04:00
###############################################################################
# pvc network sriov vf list
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " list " , short_help = " List VF devices. " )
@click.argument ( " node " )
@click.argument ( " pf " , default = None , required = False )
2021-06-21 17:12:53 -04:00
@cluster_req
def net_sriov_vf_list ( node , pf ) :
"""
List all SR - IOV VFs on NODE , optionally limited to device PF .
"""
retcode , retdata = pvc_network . net_sriov_vf_list ( config , node , pf )
if retcode :
retdata = pvc_network . format_list_sriov_vf ( retdata )
cleanup ( retcode , retdata )
###############################################################################
# pvc network sriov vf info
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " info " , short_help = " List VF devices. " )
@click.argument ( " node " )
@click.argument ( " vf " )
2021-06-21 17:12:53 -04:00
@cluster_req
def net_sriov_vf_info ( node , vf ) :
"""
Show details of the SR - IOV VF on NODE .
"""
retcode , retdata = pvc_network . net_sriov_vf_info ( config , node , vf )
if retcode :
retdata = pvc_network . format_info_sriov_vf ( config , retdata , node )
cleanup ( retcode , retdata )
2018-10-27 18:11:58 -04:00
###############################################################################
2019-07-10 15:14:17 -04:00
# pvc storage
###############################################################################
# Note: The prefix `storage` allows future potential storage subsystems.
# Since Ceph is the only section not abstracted by PVC directly
# (i.e. it references Ceph-specific concepts), this makes more
# sense in the long-term.
###############################################################################
2021-11-06 03:02:43 -04:00
@click.group (
name = " storage " ,
short_help = " Manage the PVC storage cluster. " ,
context_settings = CONTEXT_SETTINGS ,
)
2019-07-10 15:14:17 -04:00
def cli_storage ( ) :
"""
Manage the storage of the PVC cluster .
"""
2020-11-07 14:45:24 -05:00
pass
2019-07-10 15:14:17 -04:00
###############################################################################
2020-01-11 16:02:53 -05:00
# pvc storage status
2018-10-27 18:11:58 -04:00
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " status " , short_help = " Show storage cluster status. " )
2020-06-05 14:49:53 -04:00
@cluster_req
2018-10-27 18:11:58 -04:00
def ceph_status ( ) :
"""
Show detailed status of the storage cluster .
"""
2019-12-29 20:33:51 -05:00
retcode , retdata = pvc_ceph . ceph_status ( config )
2019-07-05 00:44:40 -04:00
if retcode :
2020-01-05 12:35:00 -05:00
retdata = pvc_ceph . format_raw_output ( retdata )
2019-12-29 20:33:51 -05:00
cleanup ( retcode , retdata )
2019-07-08 10:56:33 -04:00
2020-11-07 14:45:24 -05:00
2019-07-08 10:56:33 -04:00
###############################################################################
2020-01-11 16:02:53 -05:00
# pvc storage util
2019-07-08 10:56:33 -04:00
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " util " , short_help = " Show storage cluster utilization. " )
2020-06-05 14:49:53 -04:00
@cluster_req
2019-12-29 20:33:51 -05:00
def ceph_util ( ) :
2019-07-08 10:56:33 -04:00
"""
Show utilization of the storage cluster .
"""
2019-12-29 20:33:51 -05:00
retcode , retdata = pvc_ceph . ceph_util ( config )
2019-07-08 10:56:33 -04:00
if retcode :
2020-01-05 12:35:00 -05:00
retdata = pvc_ceph . format_raw_output ( retdata )
2019-12-29 20:33:51 -05:00
cleanup ( retcode , retdata )
2018-10-27 18:11:58 -04:00
2020-11-07 14:45:24 -05:00
2020-08-24 14:57:52 -04:00
###############################################################################
# pvc storage benchmark
###############################################################################
2021-11-06 03:02:43 -04:00
@click.group ( name = " benchmark " , short_help = " Run or view cluster storage benchmarks. " )
2020-08-24 14:57:52 -04:00
@cluster_req
def ceph_benchmark ( ) :
"""
Run or view benchmarks of the storage cluster .
"""
2020-11-07 14:45:24 -05:00
pass
2020-08-24 14:57:52 -04:00
###############################################################################
# pvc storage benchmark run
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " run " , short_help = " Run a storage benchmark. " )
2021-12-23 21:00:42 -05:00
@click.option (
" -y " ,
" --yes " ,
" confirm_flag " ,
is_flag = True ,
default = False ,
help = " Confirm the run " ,
)
2021-11-06 03:02:43 -04:00
@click.argument ( " pool " )
2020-08-24 14:57:52 -04:00
@cluster_req
2021-12-23 21:00:42 -05:00
def ceph_benchmark_run ( confirm_flag , pool ) :
2020-08-24 14:57:52 -04:00
"""
Run a storage benchmark on POOL in the background .
"""
2021-12-23 21:00:42 -05:00
if not confirm_flag and not config [ " unsafe " ] :
try :
click . confirm (
" NOTE: Storage benchmarks take approximately 10 minutes to run and generate significant load on the cluster; they should be run sparingly. Continue " ,
prompt_suffix = " ? " ,
abort = True ,
)
except Exception :
exit ( 0 )
2020-08-25 12:16:23 -04:00
2020-08-24 14:57:52 -04:00
retcode , retmsg = pvc_ceph . ceph_benchmark_run ( config , pool )
cleanup ( retcode , retmsg )
2020-11-07 14:45:24 -05:00
2020-08-25 12:16:23 -04:00
###############################################################################
# pvc storage benchmark info
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " info " , short_help = " Show detailed storage benchmark results. " )
@click.argument ( " job " , required = True )
2021-10-02 01:13:50 -04:00
@click.option (
2021-11-06 03:02:43 -04:00
" -f " ,
" --format " ,
" oformat " ,
default = " summary " ,
show_default = True ,
type = click . Choice ( [ " summary " , " json " , " json-pretty " ] ) ,
help = " Output format of benchmark information. " ,
2021-10-02 01:13:50 -04:00
)
2020-08-25 12:16:23 -04:00
@cluster_req
2021-10-02 01:13:50 -04:00
def ceph_benchmark_info ( job , oformat ) :
2020-08-25 12:16:23 -04:00
"""
Show full details of storage benchmark JOB .
"""
retcode , retdata = pvc_ceph . ceph_benchmark_list ( config , job )
if retcode :
2021-10-02 01:13:50 -04:00
retdata = pvc_ceph . format_info_benchmark ( config , oformat , retdata )
2020-08-25 12:16:23 -04:00
cleanup ( retcode , retdata )
2020-11-07 14:45:24 -05:00
2020-08-24 14:57:52 -04:00
###############################################################################
# pvc storage benchmark list
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " list " , short_help = " List storage benchmark results. " )
@click.argument ( " job " , default = None , required = False )
2020-08-24 14:57:52 -04:00
@cluster_req
def ceph_benchmark_list ( job ) :
"""
List all Ceph storage benchmarks ; optionally only match JOB .
"""
retcode , retdata = pvc_ceph . ceph_benchmark_list ( config , job )
if retcode :
2020-08-25 12:16:23 -04:00
retdata = pvc_ceph . format_list_benchmark ( config , retdata )
2020-08-24 14:57:52 -04:00
cleanup ( retcode , retdata )
2020-11-07 14:45:24 -05:00
2018-10-27 18:11:58 -04:00
###############################################################################
2020-01-11 16:02:53 -05:00
# pvc storage osd
2018-10-27 18:11:58 -04:00
###############################################################################
2021-11-06 03:02:43 -04:00
@click.group (
name = " osd " ,
short_help = " Manage OSDs in the PVC storage cluster. " ,
context_settings = CONTEXT_SETTINGS ,
)
2018-10-27 18:11:58 -04:00
def ceph_osd ( ) :
"""
Manage the Ceph OSDs of the PVC cluster .
"""
2020-11-07 14:45:24 -05:00
pass
2018-10-27 18:11:58 -04:00
2021-09-23 13:59:49 -04:00
###############################################################################
# pvc storage osd create-db-vg
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " create-db-vg " , short_help = " Create new OSD database volume group. " )
@click.argument ( " node " )
@click.argument ( " device " )
2021-09-23 13:59:49 -04:00
@click.option (
2021-11-06 03:02:43 -04:00
" -y " ,
" --yes " ,
" confirm_flag " ,
is_flag = True ,
default = False ,
help = " Confirm the creation. " ,
2021-09-23 13:59:49 -04:00
)
@cluster_req
def ceph_osd_create_db_vg ( node , device , confirm_flag ) :
"""
2021-12-24 15:18:38 -05:00
Create a new Ceph OSD database volume group on node NODE with block device DEVICE . DEVICE must be a valid raw block device ( e . g . ' /dev/nvme0n1 ' , ' /dev/disk/by-path/... ' ) or a " detect " string . Using partitions is not supported .
A " detect " string is a string in the form " detect:<NAME>:<HUMAN-SIZE>:<ID> " . Detect strings allow for automatic determination of Linux block device paths from known basic information about disks by leveraging " lsscsi " on the target host . The " NAME " should be some descriptive identifier , for instance the manufacturer ( e . g . " INTEL " ) , the " HUMAN-SIZE " should be the labeled human - readable size of the device ( e . g . " 480GB " , " 1.92TB " ) , and " ID " specifies the Nth 0 - indexed device which matches the " NAME " and " HUMAN-SIZE " values ( e . g . " 2 " would match the third device with the corresponding " NAME " and " HUMAN-SIZE " ) . When matching against sizes , there is + / - 3 % flexibility to account for base - 1000 vs . base - 1024 differences and rounding errors . The " NAME " may contain whitespace but if so the entire detect string should be quoted , and is case - insensitive . More information about detect strings can be found in the pvcbootstrapd manual .
2021-09-23 13:59:49 -04:00
2021-09-26 01:14:00 -04:00
This volume group will be used for Ceph OSD database and WAL functionality if the ' --ext-db ' flag is passed to newly - created OSDs during ' pvc storage osd add ' . DEVICE should be an extremely fast SSD device ( NVMe , Intel Optane , etc . ) which is significantly faster than the normal OSD disks and with very high write endurance . Only one OSD database volume group on a single physical device is supported per node , so it must be fast and large enough to act as an effective OSD database device for all OSDs on the node . Attempting to add additional database volume groups after the first will fail .
2021-09-23 13:59:49 -04:00
"""
2021-11-06 03:02:43 -04:00
if not confirm_flag and not config [ " unsafe " ] :
2021-09-23 13:59:49 -04:00
try :
2021-11-06 03:02:43 -04:00
click . confirm (
" Destroy all data and create a new OSD database volume group on {} : {} " . format (
node , device
) ,
prompt_suffix = " ? " ,
abort = True ,
)
2021-09-23 13:59:49 -04:00
except Exception :
exit ( 0 )
retcode , retmsg = pvc_ceph . ceph_osd_db_vg_add ( config , node , device )
cleanup ( retcode , retmsg )
2018-10-28 22:15:25 -04:00
###############################################################################
2020-01-11 16:02:53 -05:00
# pvc storage osd add
2018-10-28 22:15:25 -04:00
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " add " , short_help = " Add new OSD. " )
@click.argument ( " node " )
@click.argument ( " device " )
2018-11-01 23:03:27 -04:00
@click.option (
2021-11-06 03:02:43 -04:00
" -w " ,
" --weight " ,
" weight " ,
default = 1.0 ,
show_default = True ,
help = " Weight of the OSD within the CRUSH map. " ,
2018-11-01 23:03:27 -04:00
)
2021-09-23 13:59:49 -04:00
@click.option (
2021-11-06 03:02:43 -04:00
" -d " ,
" --ext-db " ,
" ext_db_flag " ,
is_flag = True ,
default = False ,
help = " Use an external database logical volume for this OSD. " ,
2021-09-23 13:59:49 -04:00
)
2021-09-23 23:31:58 -04:00
@click.option (
2021-11-06 03:02:43 -04:00
" -r " ,
" --ext-db-ratio " ,
" ext_db_ratio " ,
default = 0.05 ,
show_default = True ,
type = float ,
help = " Decimal ratio of the external database logical volume to the OSD size. " ,
2021-09-23 23:31:58 -04:00
)
2019-06-21 15:52:28 -04:00
@click.option (
2021-11-06 03:02:43 -04:00
" -y " ,
" --yes " ,
" confirm_flag " ,
is_flag = True ,
default = False ,
help = " Confirm the creation. " ,
2019-06-21 15:52:28 -04:00
)
2020-06-05 14:49:53 -04:00
@cluster_req
2021-09-23 23:31:58 -04:00
def ceph_osd_add ( node , device , weight , ext_db_flag , ext_db_ratio , confirm_flag ) :
2018-10-28 22:15:25 -04:00
"""
2021-12-24 15:18:38 -05:00
Add a new Ceph OSD on node NODE with block device DEVICE . DEVICE must be a valid raw block device ( e . g . ' /dev/sda ' , ' /dev/nvme0n1 ' , ' /dev/disk/by-path/... ' , ' /dev/disk/by-id/... ' ) or a " detect " string . Using partitions is not supported .
A " detect " string is a string in the form " detect:<NAME>:<HUMAN-SIZE>:<ID> " . Detect strings allow for automatic determination of Linux block device paths from known basic information about disks by leveraging " lsscsi " on the target host . The " NAME " should be some descriptive identifier , for instance the manufacturer ( e . g . " INTEL " ) , the " HUMAN-SIZE " should be the labeled human - readable size of the device ( e . g . " 480GB " , " 1.92TB " ) , and " ID " specifies the Nth 0 - indexed device which matches the " NAME " and " HUMAN-SIZE " values ( e . g . " 2 " would match the third device with the corresponding " NAME " and " HUMAN-SIZE " ) . When matching against sizes , there is + / - 3 % flexibility to account for base - 1000 vs . base - 1024 differences and rounding errors . The " NAME " may contain whitespace but if so the entire detect string should be quoted , and is case - insensitive . More information about detect strings can be found in the pvcbootstrapd manual .
2021-09-23 13:59:49 -04:00
2021-09-26 01:14:00 -04:00
The weight of an OSD should reflect the ratio of the OSD to other OSDs in the storage cluster . For example , if all OSDs are the same size as recommended for PVC , 1 ( the default ) is a valid weight so that all are treated identically . If a new OSD is added later which is 4 x the size of the existing OSDs , the new OSD ' s weight should then be 4 to tell the cluster that 4x the data can be stored on the OSD. Weights can also be tweaked for performance reasons, since OSDs with more data will incur more I/O load. For more information about CRUSH weights, please see the Ceph documentation.
If ' --ext-db ' is specified , the OSD database and WAL will be placed on a new logical volume in NODE ' s OSD database volume group; it must exist or OSD creation will fail. See the ' pvc storage osd create - db - vg ' command for more details.
2021-09-23 23:31:58 -04:00
The default ' --ext-db-ratio ' of 0.05 ( 5 % ) is sufficient for most RBD workloads and OSD sizes , though this can be adjusted based on the sizes of the OSD ( s ) and the underlying database device . Ceph documentation recommends at least 0.02 ( 2 % ) for RBD use - cases , and higher values may improve WAL performance under write - heavy workloads with fewer OSDs per node .
2018-10-28 22:15:25 -04:00
"""
2021-11-06 03:02:43 -04:00
if not confirm_flag and not config [ " unsafe " ] :
2020-01-08 10:34:27 -05:00
try :
2021-11-06 03:02:43 -04:00
click . confirm (
" Destroy all data and create a new OSD on {} : {} " . format ( node , device ) ,
prompt_suffix = " ? " ,
abort = True ,
)
2020-11-06 18:55:10 -05:00
except Exception :
2019-06-21 15:52:28 -04:00
exit ( 0 )
2021-11-06 03:02:43 -04:00
retcode , retmsg = pvc_ceph . ceph_osd_add (
config , node , device , weight , ext_db_flag , ext_db_ratio
)
2019-12-29 20:33:51 -05:00
cleanup ( retcode , retmsg )
2018-10-28 22:15:25 -04:00
2020-11-07 14:45:24 -05:00
2022-05-06 15:31:58 -04:00
###############################################################################
# pvc storage osd replace
###############################################################################
@click.command ( name = " replace " , short_help = " Replace OSD block device. " )
@click.argument ( " osdid " )
@click.argument ( " device " )
@click.option (
" -w " ,
" --weight " ,
" weight " ,
default = 1.0 ,
show_default = True ,
help = " New weight of the OSD within the CRUSH map. " ,
)
@click.option (
" -y " ,
" --yes " ,
" confirm_flag " ,
is_flag = True ,
default = False ,
help = " Confirm the removal " ,
)
@cluster_req
def ceph_osd_replace ( osdid , device , weight , confirm_flag ) :
"""
Replace the block device of an existing OSD with ID OSDID with DEVICE . Use this command to replace a failed or smaller OSD block device with a new one .
DEVICE must be a valid raw block device ( e . g . ' /dev/sda ' , ' /dev/nvme0n1 ' , ' /dev/disk/by-path/... ' , ' /dev/disk/by-id/... ' ) or a " detect " string . Using partitions is not supported . A " detect " string is a string in the form " detect:<NAME>:<HUMAN-SIZE>:<ID> " . For details , see ' pvc storage osd add --help ' .
The weight of an OSD should reflect the ratio of the OSD to other OSDs in the storage cluster . For details , see ' pvc storage osd add --help ' . Note that the current weight must be explicitly specified if it differs from the default .
Existing IDs , external DB devices , etc . of the OSD will be preserved ; data will be lost and rebuilt from the remaining healthy OSDs .
"""
if not confirm_flag and not config [ " unsafe " ] :
try :
click . confirm (
" Replace OSD {} with block device {} " . format ( osdid , device ) ,
prompt_suffix = " ? " ,
abort = True ,
)
except Exception :
exit ( 0 )
retcode , retmsg = pvc_ceph . ceph_osd_replace ( config , osdid , device , weight )
cleanup ( retcode , retmsg )
###############################################################################
# pvc storage osd refresh
###############################################################################
@click.command ( name = " refresh " , short_help = " Refresh (reimport) OSD device. " )
@click.argument ( " osdid " )
@click.argument ( " device " )
@cluster_req
def ceph_osd_refresh ( osdid , device ) :
"""
Refresh ( reimport ) the block DEVICE of an existing OSD with ID OSDID . Use this command to reimport a working OSD into a rebuilt / replaced node .
DEVICE must be a valid raw block device ( e . g . ' /dev/sda ' , ' /dev/nvme0n1 ' , ' /dev/disk/by-path/... ' , ' /dev/disk/by-id/... ' ) or a " detect " string . Using partitions is not supported . A " detect " string is a string in the form " detect:<NAME>:<HUMAN-SIZE>:<ID> " . For details , see ' pvc storage osd add --help ' .
Existing data , IDs , weights , etc . of the OSD will be preserved .
NOTE : If a device had an external DB device , this is not automatically handled at this time . It is best to remove and re - add the OSD instead .
"""
retcode , retmsg = pvc_ceph . ceph_osd_refresh ( config , osdid , device )
cleanup ( retcode , retmsg )
2018-10-28 22:15:25 -04:00
###############################################################################
2020-01-11 16:02:53 -05:00
# pvc storage osd remove
2018-10-28 22:15:25 -04:00
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " remove " , short_help = " Remove OSD. " )
@click.argument ( " osdid " )
2022-04-29 11:16:33 -04:00
@click.option (
" -f " ,
" --force " ,
" force_flag " ,
is_flag = True ,
default = False ,
help = " Force removal even if steps fail " ,
)
2019-06-21 15:52:28 -04:00
@click.option (
2021-11-06 03:02:43 -04:00
" -y " ,
" --yes " ,
" confirm_flag " ,
is_flag = True ,
default = False ,
help = " Confirm the removal " ,
2019-06-21 15:52:28 -04:00
)
2020-06-05 14:49:53 -04:00
@cluster_req
2022-04-29 11:16:33 -04:00
def ceph_osd_remove ( osdid , force_flag , confirm_flag ) :
2018-10-28 22:15:25 -04:00
"""
2020-01-04 14:06:36 -05:00
Remove a Ceph OSD with ID OSDID .
2020-11-06 19:05:48 -05:00
2021-09-26 01:14:00 -04:00
DANGER : This will completely remove the OSD from the cluster . OSDs will rebalance which will negatively affect performance and available space . It is STRONGLY RECOMMENDED to set an OSD out ( using ' pvc storage osd out ' ) and allow the cluster to fully rebalance ( verified with ' pvc storage status ' ) before removing an OSD .
2022-04-29 11:16:33 -04:00
NOTE : The " -f " / " --force " option is useful after replacing a failed node , to ensure the OSD is removed even if the OSD in question does not properly exist on the node after a rebuild .
2018-10-28 22:15:25 -04:00
"""
2021-11-06 03:02:43 -04:00
if not confirm_flag and not config [ " unsafe " ] :
2020-01-08 10:34:27 -05:00
try :
2021-11-06 03:02:43 -04:00
click . confirm ( " Remove OSD {} " . format ( osdid ) , prompt_suffix = " ? " , abort = True )
2020-11-06 18:55:10 -05:00
except Exception :
2019-06-21 15:52:28 -04:00
exit ( 0 )
2022-04-29 11:16:33 -04:00
retcode , retmsg = pvc_ceph . ceph_osd_remove ( config , osdid , force_flag )
2019-12-29 20:33:51 -05:00
cleanup ( retcode , retmsg )
2018-10-28 22:15:25 -04:00
2020-11-07 14:45:24 -05:00
2018-11-01 22:00:59 -04:00
###############################################################################
2020-01-11 16:02:53 -05:00
# pvc storage osd in
2018-11-01 22:00:59 -04:00
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " in " , short_help = " Online OSD. " )
@click.argument ( " osdid " )
2020-06-05 14:49:53 -04:00
@cluster_req
2018-11-01 22:00:59 -04:00
def ceph_osd_in ( osdid ) :
"""
2020-01-04 14:06:36 -05:00
Set a Ceph OSD with ID OSDID online .
2018-11-01 22:00:59 -04:00
"""
2021-11-06 03:02:43 -04:00
retcode , retmsg = pvc_ceph . ceph_osd_state ( config , osdid , " in " )
2019-12-29 20:33:51 -05:00
cleanup ( retcode , retmsg )
2018-11-01 22:00:59 -04:00
2020-11-07 14:45:24 -05:00
2018-11-01 22:00:59 -04:00
###############################################################################
2020-01-11 16:02:53 -05:00
# pvc storage osd out
2018-11-01 22:00:59 -04:00
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " out " , short_help = " Offline OSD. " )
@click.argument ( " osdid " )
2020-06-05 14:49:53 -04:00
@cluster_req
2018-11-01 22:00:59 -04:00
def ceph_osd_out ( osdid ) :
"""
2020-01-04 14:06:36 -05:00
Set a Ceph OSD with ID OSDID offline .
2018-11-01 22:00:59 -04:00
"""
2021-11-06 03:02:43 -04:00
retcode , retmsg = pvc_ceph . ceph_osd_state ( config , osdid , " out " )
2019-12-29 20:33:51 -05:00
cleanup ( retcode , retmsg )
2018-11-01 22:00:59 -04:00
2020-11-07 14:45:24 -05:00
2018-11-01 22:00:59 -04:00
###############################################################################
2020-01-11 16:02:53 -05:00
# pvc storage osd set
2018-11-01 22:00:59 -04:00
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " set " , short_help = " Set property. " )
@click.argument ( " osd_property " )
2020-06-05 14:49:53 -04:00
@cluster_req
2018-11-01 22:00:59 -04:00
def ceph_osd_set ( osd_property ) :
"""
Set a Ceph OSD property OSD_PROPERTY on the cluster .
Valid properties are :
2020-11-06 19:44:14 -05:00
full | pause | noup | nodown | noout | noin | nobackfill | norebalance | norecover | noscrub | nodeep - scrub | notieragent | sortbitwise | recovery_deletes | require_jewel_osds | require_kraken_osds
2018-11-01 22:00:59 -04:00
"""
2021-11-06 03:02:43 -04:00
retcode , retmsg = pvc_ceph . ceph_osd_option ( config , osd_property , " set " )
2019-12-29 20:33:51 -05:00
cleanup ( retcode , retmsg )
2018-11-01 22:00:59 -04:00
2020-11-07 14:45:24 -05:00
2018-11-01 22:00:59 -04:00
###############################################################################
2020-01-11 16:02:53 -05:00
# pvc storage osd unset
2018-11-01 22:00:59 -04:00
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " unset " , short_help = " Unset property. " )
@click.argument ( " osd_property " )
2020-06-05 14:49:53 -04:00
@cluster_req
2018-11-01 22:00:59 -04:00
def ceph_osd_unset ( osd_property ) :
"""
Unset a Ceph OSD property OSD_PROPERTY on the cluster .
Valid properties are :
2020-11-06 19:44:14 -05:00
full | pause | noup | nodown | noout | noin | nobackfill | norebalance | norecover | noscrub | nodeep - scrub | notieragent | sortbitwise | recovery_deletes | require_jewel_osds | require_kraken_osds
2018-11-01 22:00:59 -04:00
"""
2021-11-06 03:02:43 -04:00
retcode , retmsg = pvc_ceph . ceph_osd_option ( config , osd_property , " unset " )
2019-12-29 20:33:51 -05:00
cleanup ( retcode , retmsg )
2018-11-01 22:00:59 -04:00
2020-11-07 14:45:24 -05:00
2018-10-30 09:17:32 -04:00
###############################################################################
2020-01-11 16:02:53 -05:00
# pvc storage osd list
2018-10-30 09:17:32 -04:00
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " list " , short_help = " List cluster OSDs. " )
@click.argument ( " limit " , default = None , required = False )
2020-06-05 14:49:53 -04:00
@cluster_req
2018-10-30 09:17:32 -04:00
def ceph_osd_list ( limit ) :
"""
2020-01-04 14:06:36 -05:00
List all Ceph OSDs ; optionally only match elements matching ID regex LIMIT .
2018-10-30 09:17:32 -04:00
"""
2019-12-29 20:33:51 -05:00
retcode , retdata = pvc_ceph . ceph_osd_list ( config , limit )
2019-07-05 00:29:47 -04:00
if retcode :
2020-01-05 12:35:00 -05:00
retdata = pvc_ceph . format_list_osd ( retdata )
2019-12-29 20:33:51 -05:00
cleanup ( retcode , retdata )
2018-10-30 09:17:32 -04:00
2020-11-07 14:45:24 -05:00
2018-10-27 18:11:58 -04:00
###############################################################################
2020-01-11 16:02:53 -05:00
# pvc storage pool
2018-10-27 18:11:58 -04:00
###############################################################################
2021-11-06 03:02:43 -04:00
@click.group (
name = " pool " ,
short_help = " Manage RBD pools in the PVC storage cluster. " ,
context_settings = CONTEXT_SETTINGS ,
)
2018-10-27 18:11:58 -04:00
def ceph_pool ( ) :
"""
Manage the Ceph RBD pools of the PVC cluster .
"""
2020-11-07 14:45:24 -05:00
pass
2018-09-21 23:43:30 -04:00
2018-10-31 23:38:17 -04:00
###############################################################################
2020-01-11 16:02:53 -05:00
# pvc storage pool add
2018-10-31 23:38:17 -04:00
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " add " , short_help = " Add new RBD pool. " )
@click.argument ( " name " )
@click.argument ( " pgs " )
2021-12-28 20:39:50 -05:00
@click.option (
" -t " ,
" --tier " ,
" tier " ,
default = " default " ,
show_default = True ,
type = click . Choice ( [ " default " , " hdd " , " ssd " , " nvme " ] ) ,
help = """
The device tier to limit the pool to . Default is all OSD tiers , and specific tiers can be specified instead . At least one full set of OSDs for a given tier must be present for the tier to be specified , or the pool creation will fail .
""" ,
)
2019-08-23 14:12:15 -04:00
@click.option (
2021-11-06 03:02:43 -04:00
" --replcfg " ,
" replcfg " ,
default = " copies=3,mincopies=2 " ,
show_default = True ,
required = False ,
2019-08-23 14:12:15 -04:00
help = """
2021-12-28 20:39:50 -05:00
The replication configuration , specifying both a " copies " and " mincopies " value , separated by a comma , e . g . " copies=3,mincopies=2 " . The " copies " value specifies the total number of replicas and should not exceed the total number of nodes ; the " mincopies " value specifies the minimum number of available copies to allow writes . For additional details please see the Cluster Architecture documentation .
2021-11-06 03:02:43 -04:00
""" ,
2019-08-23 14:12:15 -04:00
)
2020-06-05 14:49:53 -04:00
@cluster_req
2021-12-28 20:39:50 -05:00
def ceph_pool_add ( name , pgs , tier , replcfg ) :
2018-10-31 23:38:17 -04:00
"""
Add a new Ceph RBD pool with name NAME and PGS placement groups .
2021-12-28 21:41:41 -05:00
The placement group count must be a non - zero power of 2.
2018-10-31 23:38:17 -04:00
"""
2021-12-28 20:39:50 -05:00
retcode , retmsg = pvc_ceph . ceph_pool_add ( config , name , pgs , replcfg , tier )
2019-12-29 20:33:51 -05:00
cleanup ( retcode , retmsg )
2018-10-31 23:38:17 -04:00
2020-11-07 14:45:24 -05:00
2018-10-31 23:38:17 -04:00
###############################################################################
2020-01-11 16:02:53 -05:00
# pvc storage pool remove
2018-10-31 23:38:17 -04:00
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " remove " , short_help = " Remove RBD pool. " )
@click.argument ( " name " )
2019-06-21 15:52:28 -04:00
@click.option (
2021-11-06 03:02:43 -04:00
" -y " ,
" --yes " ,
" confirm_flag " ,
is_flag = True ,
default = False ,
help = " Confirm the removal " ,
2019-06-21 15:52:28 -04:00
)
2020-06-05 14:49:53 -04:00
@cluster_req
2020-01-08 10:34:27 -05:00
def ceph_pool_remove ( name , confirm_flag ) :
2018-10-31 23:38:17 -04:00
"""
Remove a Ceph RBD pool with name NAME and all volumes on it .
2020-01-08 10:34:27 -05:00
DANGER : This will completely remove the pool and all volumes contained in it from the cluster .
"""
2021-11-06 03:02:43 -04:00
if not confirm_flag and not config [ " unsafe " ] :
2020-01-08 10:34:27 -05:00
try :
2021-11-06 03:02:43 -04:00
click . confirm (
" Remove RBD pool {} " . format ( name ) , prompt_suffix = " ? " , abort = True
)
2020-11-06 18:55:10 -05:00
except Exception :
2020-01-08 10:34:27 -05:00
exit ( 0 )
2019-06-21 15:52:28 -04:00
2019-12-29 20:33:51 -05:00
retcode , retmsg = pvc_ceph . ceph_pool_remove ( config , name )
cleanup ( retcode , retmsg )
2018-10-31 23:38:17 -04:00
2020-11-07 14:45:24 -05:00
2021-12-28 21:41:41 -05:00
###############################################################################
# pvc storage pool set-pgs
###############################################################################
@click.command ( name = " set-pgs " , short_help = " Set PGs of an RBD pool. " )
@click.argument ( " name " )
@click.argument ( " pgs " )
@cluster_req
def ceph_pool_set_pgs ( name , pgs ) :
"""
Set the placement groups ( PGs ) count for the pool NAME to PGS .
The placement group count must be a non - zero power of 2.
Placement group counts may be increased or decreased as required though frequent alteration is not recommended .
"""
retcode , retmsg = pvc_ceph . ceph_pool_set_pgs ( config , name , pgs )
cleanup ( retcode , retmsg )
2018-10-31 23:38:17 -04:00
###############################################################################
2020-01-11 16:02:53 -05:00
# pvc storage pool list
2018-10-31 23:38:17 -04:00
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " list " , short_help = " List cluster RBD pools. " )
@click.argument ( " limit " , default = None , required = False )
2020-06-05 14:49:53 -04:00
@cluster_req
2018-10-31 23:38:17 -04:00
def ceph_pool_list ( limit ) :
"""
2020-01-04 14:06:36 -05:00
List all Ceph RBD pools ; optionally only match elements matching name regex LIMIT .
2018-10-31 23:38:17 -04:00
"""
2019-12-29 20:33:51 -05:00
retcode , retdata = pvc_ceph . ceph_pool_list ( config , limit )
2019-07-05 00:29:47 -04:00
if retcode :
2020-01-05 12:35:00 -05:00
retdata = pvc_ceph . format_list_pool ( retdata )
2019-12-29 20:33:51 -05:00
cleanup ( retcode , retdata )
2018-10-31 23:38:17 -04:00
2020-11-07 14:45:24 -05:00
2019-06-19 00:23:14 -04:00
###############################################################################
2020-01-11 16:02:53 -05:00
# pvc storage volume
2019-06-19 00:23:14 -04:00
###############################################################################
2021-11-06 03:02:43 -04:00
@click.group (
name = " volume " ,
short_help = " Manage RBD volumes in the PVC storage cluster. " ,
context_settings = CONTEXT_SETTINGS ,
)
2019-06-19 00:23:14 -04:00
def ceph_volume ( ) :
"""
Manage the Ceph RBD volumes of the PVC cluster .
"""
2020-11-07 14:45:24 -05:00
pass
2019-06-19 00:23:14 -04:00
2019-06-19 00:12:44 -04:00
###############################################################################
2020-01-11 16:02:53 -05:00
# pvc storage volume add
2019-06-19 00:12:44 -04:00
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " add " , short_help = " Add new RBD volume. " )
@click.argument ( " pool " )
@click.argument ( " name " )
@click.argument ( " size " )
2020-06-05 14:49:53 -04:00
@cluster_req
2019-06-19 00:12:44 -04:00
def ceph_volume_add ( pool , name , size ) :
"""
2019-06-21 09:22:24 -04:00
Add a new Ceph RBD volume with name NAME and size SIZE [ in human units , e . g . 1024 M , 20 G , etc . ] to pool POOL .
2019-06-19 00:12:44 -04:00
"""
2019-12-29 20:33:51 -05:00
retcode , retmsg = pvc_ceph . ceph_volume_add ( config , pool , name , size )
cleanup ( retcode , retmsg )
2019-06-19 00:12:44 -04:00
2020-11-07 14:45:24 -05:00
2020-02-09 20:42:56 -05:00
###############################################################################
2021-11-06 03:02:43 -04:00
# pvc storage volume upload
###############################################################################
@click.command ( name = " upload " , short_help = " Upload a local image file to RBD volume. " )
@click.argument ( " pool " )
@click.argument ( " name " )
@click.argument ( " image_file " )
2020-02-09 20:42:56 -05:00
@click.option (
2021-11-06 03:02:43 -04:00
" -f " ,
" --format " ,
" image_format " ,
default = " raw " ,
show_default = True ,
help = " The format of the source image. " ,
2020-02-09 20:42:56 -05:00
)
2020-06-05 14:49:53 -04:00
@cluster_req
2020-02-09 20:42:56 -05:00
def ceph_volume_upload ( pool , name , image_format , image_file ) :
"""
Upload a disk image file IMAGE_FILE to the RBD volume NAME in pool POOL .
The volume NAME must exist in the pool before uploading to it , and must be large enough to fit the disk image in raw format .
If the image format is " raw " , the image is uploaded directly to the target volume without modification . Otherwise , it will be converted into raw format by " qemu-img convert " on the remote side before writing using a temporary volume . The image format must be a valid format recognized by " qemu-img " , such as " vmdk " or " qcow2 " .
"""
if not os . path . exists ( image_file ) :
2021-11-08 00:04:20 -05:00
echo ( " ERROR: File ' {} ' does not exist! " . format ( image_file ) )
2020-02-09 20:42:56 -05:00
exit ( 1 )
2021-11-06 03:02:43 -04:00
retcode , retmsg = pvc_ceph . ceph_volume_upload (
config , pool , name , image_format , image_file
)
2020-02-09 20:42:56 -05:00
cleanup ( retcode , retmsg )
2020-11-07 14:45:24 -05:00
2019-06-19 00:12:44 -04:00
###############################################################################
2020-01-11 16:02:53 -05:00
# pvc storage volume remove
2019-06-19 00:12:44 -04:00
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " remove " , short_help = " Remove RBD volume. " )
@click.argument ( " pool " )
@click.argument ( " name " )
2019-06-21 15:52:28 -04:00
@click.option (
2021-11-06 03:02:43 -04:00
" -y " ,
" --yes " ,
" confirm_flag " ,
is_flag = True ,
default = False ,
help = " Confirm the removal " ,
2019-06-21 15:52:28 -04:00
)
2020-06-05 14:49:53 -04:00
@cluster_req
2020-01-08 10:34:27 -05:00
def ceph_volume_remove ( pool , name , confirm_flag ) :
2019-06-19 00:12:44 -04:00
"""
Remove a Ceph RBD volume with name NAME from pool POOL .
2020-11-06 19:05:48 -05:00
2020-01-08 10:34:27 -05:00
DANGER : This will completely remove the volume and all data contained in it .
2019-06-19 00:12:44 -04:00
"""
2021-11-06 03:02:43 -04:00
if not confirm_flag and not config [ " unsafe " ] :
2020-01-08 10:34:27 -05:00
try :
2021-11-06 03:02:43 -04:00
click . confirm (
" Remove volume {} / {} " . format ( pool , name ) , prompt_suffix = " ? " , abort = True
)
2020-11-06 18:55:10 -05:00
except Exception :
2019-06-21 15:52:28 -04:00
exit ( 0 )
2019-12-29 20:33:51 -05:00
retcode , retmsg = pvc_ceph . ceph_volume_remove ( config , pool , name )
cleanup ( retcode , retmsg )
2019-06-19 00:12:44 -04:00
2020-11-07 14:45:24 -05:00
2019-07-26 14:24:22 -04:00
###############################################################################
2020-01-11 16:02:53 -05:00
# pvc storage volume resize
2019-07-26 14:24:22 -04:00
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " resize " , short_help = " Resize RBD volume. " )
@click.argument ( " pool " )
@click.argument ( " name " )
@click.argument ( " size " )
2020-06-05 14:49:53 -04:00
@cluster_req
2019-07-26 14:24:22 -04:00
def ceph_volume_resize ( pool , name , size ) :
"""
Resize an existing Ceph RBD volume with name NAME in pool POOL to size SIZE [ in human units , e . g . 1024 M , 20 G , etc . ] .
"""
2019-12-29 20:33:51 -05:00
retcode , retmsg = pvc_ceph . ceph_volume_modify ( config , pool , name , new_size = size )
cleanup ( retcode , retmsg )
2019-07-26 14:24:22 -04:00
2020-11-07 14:45:24 -05:00
2019-07-26 14:24:22 -04:00
###############################################################################
2020-01-11 16:02:53 -05:00
# pvc storage volume rename
2019-07-26 14:24:22 -04:00
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " rename " , short_help = " Rename RBD volume. " )
@click.argument ( " pool " )
@click.argument ( " name " )
@click.argument ( " new_name " )
2020-06-05 14:49:53 -04:00
@cluster_req
2019-07-26 14:24:22 -04:00
def ceph_volume_rename ( pool , name , new_name ) :
"""
Rename an existing Ceph RBD volume with name NAME in pool POOL to name NEW_NAME .
"""
2019-12-29 20:33:51 -05:00
retcode , retmsg = pvc_ceph . ceph_volume_modify ( config , pool , name , new_name = new_name )
cleanup ( retcode , retmsg )
2019-07-26 14:24:22 -04:00
2020-11-07 14:45:24 -05:00
2019-10-10 14:11:13 -04:00
###############################################################################
2020-01-11 16:02:53 -05:00
# pvc storage volume clone
2019-10-10 14:11:13 -04:00
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " clone " , short_help = " Clone RBD volume. " )
@click.argument ( " pool " )
@click.argument ( " name " )
@click.argument ( " new_name " )
2020-06-05 14:49:53 -04:00
@cluster_req
2019-10-10 14:11:13 -04:00
def ceph_volume_clone ( pool , name , new_name ) :
"""
Clone a Ceph RBD volume with name NAME in pool POOL to name NEW_NAME in pool POOL .
"""
2019-12-29 20:33:51 -05:00
retcode , retmsg = pvc_ceph . ceph_volume_clone ( config , pool , name , new_name )
cleanup ( retcode , retmsg )
2019-10-10 14:11:13 -04:00
2020-11-07 14:45:24 -05:00
2019-06-19 00:12:44 -04:00
###############################################################################
2020-01-11 16:02:53 -05:00
# pvc storage volume list
2019-06-19 00:12:44 -04:00
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " list " , short_help = " List cluster RBD volumes. " )
@click.argument ( " limit " , default = None , required = False )
2019-06-19 14:11:03 -04:00
@click.option (
2021-11-06 03:02:43 -04:00
" -p " ,
" --pool " ,
" pool " ,
default = None ,
show_default = True ,
help = " Show volumes from this pool only. " ,
2019-06-19 14:11:03 -04:00
)
2020-06-05 14:49:53 -04:00
@cluster_req
2019-06-19 14:11:03 -04:00
def ceph_volume_list ( limit , pool ) :
2019-06-19 00:12:44 -04:00
"""
2020-01-04 14:06:36 -05:00
List all Ceph RBD volumes ; optionally only match elements matching name regex LIMIT .
2019-06-19 00:12:44 -04:00
"""
2019-12-29 20:33:51 -05:00
retcode , retdata = pvc_ceph . ceph_volume_list ( config , limit , pool )
2019-07-05 00:29:47 -04:00
if retcode :
2020-01-05 12:35:00 -05:00
retdata = pvc_ceph . format_list_volume ( retdata )
2019-12-29 20:33:51 -05:00
cleanup ( retcode , retdata )
2019-06-19 00:12:44 -04:00
2020-11-07 14:45:24 -05:00
2019-06-19 00:23:14 -04:00
###############################################################################
2020-01-11 16:02:53 -05:00
# pvc storage volume snapshot
2019-06-19 00:23:14 -04:00
###############################################################################
2021-11-06 03:02:43 -04:00
@click.group (
name = " snapshot " ,
short_help = " Manage RBD volume snapshots in the PVC storage cluster. " ,
context_settings = CONTEXT_SETTINGS ,
)
2019-06-19 00:23:14 -04:00
def ceph_volume_snapshot ( ) :
"""
Manage the Ceph RBD volume snapshots of the PVC cluster .
"""
2020-11-07 14:45:24 -05:00
pass
2019-06-19 00:23:14 -04:00
2019-06-19 00:12:44 -04:00
###############################################################################
2020-01-11 16:02:53 -05:00
# pvc storage volume snapshot add
2019-06-19 00:12:44 -04:00
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " add " , short_help = " Add new RBD volume snapshot. " )
@click.argument ( " pool " )
@click.argument ( " volume " )
@click.argument ( " name " )
2020-06-05 14:49:53 -04:00
@cluster_req
2019-06-19 00:23:14 -04:00
def ceph_volume_snapshot_add ( pool , volume , name ) :
2019-06-19 00:12:44 -04:00
"""
2019-07-28 23:00:35 -04:00
Add a snapshot with name NAME of Ceph RBD volume VOLUME in pool POOL .
2019-06-19 00:12:44 -04:00
"""
2019-12-29 20:33:51 -05:00
retcode , retmsg = pvc_ceph . ceph_snapshot_add ( config , pool , volume , name )
cleanup ( retcode , retmsg )
2019-06-19 00:12:44 -04:00
2020-11-07 14:45:24 -05:00
2019-07-28 23:00:35 -04:00
###############################################################################
2020-01-11 16:02:53 -05:00
# pvc storage volume snapshot rename
2019-07-28 23:00:35 -04:00
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " rename " , short_help = " Rename RBD volume snapshot. " )
@click.argument ( " pool " )
@click.argument ( " volume " )
@click.argument ( " name " )
@click.argument ( " new_name " )
2020-06-05 14:49:53 -04:00
@cluster_req
2019-07-28 23:00:35 -04:00
def ceph_volume_snapshot_rename ( pool , volume , name , new_name ) :
"""
Rename an existing Ceph RBD volume snapshot with name NAME to name NEW_NAME for volume VOLUME in pool POOL .
"""
2021-11-06 03:02:43 -04:00
retcode , retmsg = pvc_ceph . ceph_snapshot_modify (
config , pool , volume , name , new_name = new_name
)
2019-12-29 20:33:51 -05:00
cleanup ( retcode , retmsg )
2019-07-28 23:00:35 -04:00
2020-11-07 14:45:24 -05:00
2019-06-19 00:12:44 -04:00
###############################################################################
2020-01-11 16:02:53 -05:00
# pvc storage volume snapshot remove
2019-06-19 00:12:44 -04:00
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " remove " , short_help = " Remove RBD volume snapshot. " )
@click.argument ( " pool " )
@click.argument ( " volume " )
@click.argument ( " name " )
2019-06-21 15:52:28 -04:00
@click.option (
2021-11-06 03:02:43 -04:00
" -y " ,
" --yes " ,
" confirm_flag " ,
is_flag = True ,
default = False ,
help = " Confirm the removal " ,
2019-06-21 15:52:28 -04:00
)
2020-06-05 14:49:53 -04:00
@cluster_req
2020-01-08 10:34:27 -05:00
def ceph_volume_snapshot_remove ( pool , volume , name , confirm_flag ) :
2019-06-19 00:12:44 -04:00
"""
2019-07-28 23:00:35 -04:00
Remove a Ceph RBD volume snapshot with name NAME from volume VOLUME in pool POOL .
2019-06-19 00:12:44 -04:00
2020-01-08 10:34:27 -05:00
DANGER : This will completely remove the snapshot .
"""
2021-11-06 03:02:43 -04:00
if not confirm_flag and not config [ " unsafe " ] :
2020-01-08 10:34:27 -05:00
try :
2021-11-06 03:02:43 -04:00
click . confirm (
" Remove snapshot {} for volume {} / {} " . format ( name , pool , volume ) ,
prompt_suffix = " ? " ,
abort = True ,
)
2020-11-06 18:55:10 -05:00
except Exception :
2019-06-21 15:52:28 -04:00
exit ( 0 )
2019-12-29 20:33:51 -05:00
retcode , retmsg = pvc_ceph . ceph_snapshot_remove ( config , pool , volume , name )
cleanup ( retcode , retmsg )
2019-06-19 00:12:44 -04:00
2020-11-07 14:45:24 -05:00
2019-06-19 00:12:44 -04:00
###############################################################################
2020-01-11 16:02:53 -05:00
# pvc storage volume snapshot list
2019-06-19 00:12:44 -04:00
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " list " , short_help = " List cluster RBD volume shapshots. " )
@click.argument ( " limit " , default = None , required = False )
2019-06-19 15:22:44 -04:00
@click.option (
2021-11-06 03:02:43 -04:00
" -p " ,
" --pool " ,
" pool " ,
default = None ,
show_default = True ,
help = " Show snapshots from this pool only. " ,
2019-06-19 00:12:44 -04:00
)
2019-06-19 15:22:44 -04:00
@click.option (
2021-11-06 03:02:43 -04:00
" -o " ,
" --volume " ,
" volume " ,
default = None ,
show_default = True ,
help = " Show snapshots from this volume only. " ,
2019-06-19 00:12:44 -04:00
)
2020-06-05 14:49:53 -04:00
@cluster_req
2019-06-19 00:23:14 -04:00
def ceph_volume_snapshot_list ( pool , volume , limit ) :
2019-06-19 00:12:44 -04:00
"""
2019-06-19 15:22:44 -04:00
List all Ceph RBD volume snapshots ; optionally only match elements matching name regex LIMIT .
2019-06-19 00:12:44 -04:00
"""
2019-12-29 20:33:51 -05:00
retcode , retdata = pvc_ceph . ceph_snapshot_list ( config , limit , volume , pool )
2019-07-05 00:29:47 -04:00
if retcode :
2020-01-05 12:35:00 -05:00
retdata = pvc_ceph . format_list_snapshot ( retdata )
2019-12-29 20:33:51 -05:00
cleanup ( retcode , retdata )
2019-06-19 00:12:44 -04:00
2020-01-02 11:18:46 -05:00
###############################################################################
# pvc provisioner
###############################################################################
2021-11-06 03:02:43 -04:00
@click.group (
name = " provisioner " ,
short_help = " Manage PVC provisioner. " ,
context_settings = CONTEXT_SETTINGS ,
)
2020-01-02 11:18:46 -05:00
def cli_provisioner ( ) :
"""
Manage the PVC provisioner .
"""
2020-11-07 14:45:24 -05:00
pass
2020-01-02 11:18:46 -05:00
###############################################################################
# pvc provisioner template
###############################################################################
2021-11-06 03:02:43 -04:00
@click.group (
name = " template " ,
short_help = " Manage PVC provisioner templates. " ,
context_settings = CONTEXT_SETTINGS ,
)
2020-01-02 11:18:46 -05:00
def provisioner_template ( ) :
"""
Manage the PVC provisioner template system .
"""
2020-11-07 14:45:24 -05:00
pass
2020-01-02 11:18:46 -05:00
###############################################################################
# pvc provisioner template list
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " list " , short_help = " List all templates. " )
@click.argument ( " limit " , default = None , required = False )
2020-06-05 14:49:53 -04:00
@cluster_req
2020-01-04 11:58:30 -05:00
def provisioner_template_list ( limit ) :
2020-01-02 11:18:46 -05:00
"""
List all templates in the PVC cluster provisioner .
"""
retcode , retdata = pvc_provisioner . template_list ( config , limit )
if retcode :
2020-01-05 12:35:00 -05:00
retdata = pvc_provisioner . format_list_template ( retdata )
2020-01-02 11:18:46 -05:00
cleanup ( retcode , retdata )
2020-11-07 14:45:24 -05:00
2020-01-04 11:58:30 -05:00
###############################################################################
# pvc provisioner template system
###############################################################################
2021-11-06 03:02:43 -04:00
@click.group (
name = " system " ,
short_help = " Manage PVC provisioner system templates. " ,
context_settings = CONTEXT_SETTINGS ,
)
2020-01-04 11:58:30 -05:00
def provisioner_template_system ( ) :
"""
Manage the PVC provisioner system templates .
"""
2020-11-07 14:45:24 -05:00
pass
2020-01-04 11:58:30 -05:00
###############################################################################
# pvc provisioner template system list
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " list " , short_help = " List all system templates. " )
@click.argument ( " limit " , default = None , required = False )
2020-06-05 14:49:53 -04:00
@cluster_req
2020-01-04 11:58:30 -05:00
def provisioner_template_system_list ( limit ) :
"""
List all system templates in the PVC cluster provisioner .
"""
2021-11-06 03:02:43 -04:00
retcode , retdata = pvc_provisioner . template_list (
config , limit , template_type = " system "
)
2020-01-04 11:58:30 -05:00
if retcode :
2021-11-06 03:02:43 -04:00
retdata = pvc_provisioner . format_list_template ( retdata , template_type = " system " )
2020-01-04 11:58:30 -05:00
cleanup ( retcode , retdata )
2020-11-07 14:45:24 -05:00
2020-01-04 11:58:30 -05:00
###############################################################################
# pvc provisioner template system add
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " add " , short_help = " Add new system template. " )
@click.argument ( " name " )
2020-01-04 11:58:30 -05:00
@click.option (
2021-11-06 03:02:43 -04:00
" -u " , " --vcpus " , " vcpus " , required = True , type = int , help = " The number of vCPUs. "
2020-01-04 11:58:30 -05:00
)
@click.option (
2021-11-06 03:02:43 -04:00
" -m " , " --vram " , " vram " , required = True , type = int , help = " The amount of vRAM (in MB). "
2020-01-04 11:58:30 -05:00
)
@click.option (
2021-11-06 03:02:43 -04:00
" -s/-S " ,
" --serial/--no-serial " ,
" serial " ,
is_flag = True ,
default = False ,
help = " Enable the virtual serial console. " ,
2020-01-04 11:58:30 -05:00
)
@click.option (
2021-11-06 03:02:43 -04:00
" -n/-N " ,
" --vnc/--no-vnc " ,
" vnc " ,
is_flag = True ,
default = False ,
help = " Enable/disable the VNC console. " ,
2020-01-04 11:58:30 -05:00
)
@click.option (
2021-11-06 03:02:43 -04:00
" -b " ,
" --vnc-bind " ,
" vnc_bind " ,
2020-01-04 11:58:30 -05:00
default = None ,
2021-11-06 03:02:43 -04:00
help = " Bind VNC to this IP address instead of localhost. " ,
2020-01-04 11:58:30 -05:00
)
@click.option (
2021-11-06 03:02:43 -04:00
" --node-limit " ,
" node_limit " ,
2020-01-04 11:58:30 -05:00
default = None ,
2021-11-06 03:02:43 -04:00
help = " Limit VM operation to this CSV list of node(s). " ,
2020-01-04 11:58:30 -05:00
)
@click.option (
2021-11-06 03:02:43 -04:00
" --node-selector " ,
" node_selector " ,
2022-06-10 02:03:12 -04:00
type = click . Choice (
[ " mem " , " memfree " , " vcpus " , " vms " , " load " , " none " ] , case_sensitive = False
) ,
2021-11-06 03:02:43 -04:00
default = " none " ,
help = ' Method to determine optimal target node during autoselect; " none " will use the default for the cluster. ' ,
2020-01-04 11:58:30 -05:00
)
@click.option (
2021-11-06 03:02:43 -04:00
" --node-autostart " ,
" node_autostart " ,
is_flag = True ,
default = False ,
help = " Autostart VM with their parent Node on first/next boot. " ,
2020-01-04 11:58:30 -05:00
)
2020-10-29 11:31:32 -04:00
@click.option (
2021-11-06 03:02:43 -04:00
" --migration-method " ,
" migration_method " ,
type = click . Choice ( [ " none " , " live " , " shutdown " ] , case_sensitive = False ) ,
2020-11-07 13:11:03 -05:00
default = None , # Use cluster default
2021-11-06 03:02:43 -04:00
help = " The preferred migration method of the VM between nodes " ,
2020-10-29 11:31:32 -04:00
)
2020-06-05 14:49:53 -04:00
@cluster_req
2021-11-06 03:02:43 -04:00
def provisioner_template_system_add (
name ,
vcpus ,
vram ,
serial ,
vnc ,
vnc_bind ,
node_limit ,
node_selector ,
node_autostart ,
migration_method ,
) :
2020-01-04 11:58:30 -05:00
"""
Add a new system template NAME to the PVC cluster provisioner .
2022-06-10 02:14:15 -04:00
For details on the possible " --node-selector " values , please see help for the command " pvc vm define " .
2020-01-04 11:58:30 -05:00
"""
params = dict ( )
2021-11-06 03:02:43 -04:00
params [ " name " ] = name
params [ " vcpus " ] = vcpus
params [ " vram " ] = vram
params [ " serial " ] = serial
params [ " vnc " ] = vnc
2020-01-04 11:58:30 -05:00
if vnc :
2021-11-06 03:02:43 -04:00
params [ " vnc_bind " ] = vnc_bind
2020-01-04 11:58:30 -05:00
if node_limit :
2021-11-06 03:02:43 -04:00
params [ " node_limit " ] = node_limit
2020-01-04 11:58:30 -05:00
if node_selector :
2021-11-06 03:02:43 -04:00
params [ " node_selector " ] = node_selector
2020-01-04 11:58:30 -05:00
if node_autostart :
2021-11-06 03:02:43 -04:00
params [ " node_autostart " ] = node_autostart
2020-10-29 11:31:32 -04:00
if migration_method :
2021-11-06 03:02:43 -04:00
params [ " migration_method " ] = migration_method
2020-01-04 11:58:30 -05:00
2021-11-06 03:02:43 -04:00
retcode , retdata = pvc_provisioner . template_add (
config , params , template_type = " system "
)
2020-01-04 11:58:30 -05:00
cleanup ( retcode , retdata )
2020-11-07 14:45:24 -05:00
2020-02-18 16:18:27 -05:00
###############################################################################
# pvc provisioner template system modify
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " modify " , short_help = " Modify an existing system template. " )
@click.argument ( " name " )
@click.option ( " -u " , " --vcpus " , " vcpus " , type = int , help = " The number of vCPUs. " )
@click.option ( " -m " , " --vram " , " vram " , type = int , help = " The amount of vRAM (in MB). " )
2020-02-18 16:18:27 -05:00
@click.option (
2021-11-06 03:02:43 -04:00
" -s/-S " ,
" --serial/--no-serial " ,
" serial " ,
is_flag = True ,
default = None ,
help = " Enable the virtual serial console. " ,
2020-02-18 16:18:27 -05:00
)
@click.option (
2021-11-06 03:02:43 -04:00
" -n/-N " ,
" --vnc/--no-vnc " ,
" vnc " ,
is_flag = True ,
default = None ,
help = " Enable/disable the VNC console. " ,
2020-02-18 16:18:27 -05:00
)
@click.option (
2021-11-06 03:02:43 -04:00
" -b " ,
" --vnc-bind " ,
" vnc_bind " ,
help = " Bind VNC to this IP address instead of localhost. " ,
2020-02-18 16:18:27 -05:00
)
@click.option (
2021-11-06 03:02:43 -04:00
" --node-limit " , " node_limit " , help = " Limit VM operation to this CSV list of node(s). "
2020-02-18 16:18:27 -05:00
)
@click.option (
2021-11-06 03:02:43 -04:00
" --node-selector " ,
" node_selector " ,
2022-06-10 02:03:12 -04:00
type = click . Choice (
[ " mem " , " memfree " , " vcpus " , " vms " , " load " , " none " ] , case_sensitive = False
) ,
2021-11-06 03:02:43 -04:00
help = ' Method to determine optimal target node during autoselect; " none " will use the default for the cluster. ' ,
2020-02-18 16:18:27 -05:00
)
@click.option (
2021-11-06 03:02:43 -04:00
" --node-autostart " ,
" node_autostart " ,
is_flag = True ,
default = None ,
help = " Autostart VM with their parent Node on first/next boot. " ,
2020-02-18 16:18:27 -05:00
)
2020-10-29 11:31:32 -04:00
@click.option (
2021-11-06 03:02:43 -04:00
" --migration-method " ,
" migration_method " ,
type = click . Choice ( [ " none " , " live " , " shutdown " ] , case_sensitive = False ) ,
2020-11-07 13:11:03 -05:00
default = None , # Use cluster default
2021-11-06 03:02:43 -04:00
help = " The preferred migration method of the VM between nodes " ,
2020-10-29 11:31:32 -04:00
)
2020-06-05 14:49:53 -04:00
@cluster_req
2021-11-06 03:02:43 -04:00
def provisioner_template_system_modify (
name ,
vcpus ,
vram ,
serial ,
vnc ,
vnc_bind ,
node_limit ,
node_selector ,
node_autostart ,
migration_method ,
) :
2020-02-18 16:18:27 -05:00
"""
Add a new system template NAME to the PVC cluster provisioner .
2022-06-10 02:14:15 -04:00
For details on the possible " --node-selector " values , please see help for the command " pvc vm define " .
2020-02-18 16:18:27 -05:00
"""
params = dict ( )
2021-11-06 03:02:43 -04:00
params [ " vcpus " ] = vcpus
params [ " vram " ] = vram
params [ " serial " ] = serial
params [ " vnc " ] = vnc
params [ " vnc_bind " ] = vnc_bind
params [ " node_limit " ] = node_limit
params [ " node_selector " ] = node_selector
params [ " node_autostart " ] = node_autostart
params [ " migration_method " ] = migration_method
retcode , retdata = pvc_provisioner . template_modify (
config , params , name , template_type = " system "
)
2020-02-18 16:18:27 -05:00
cleanup ( retcode , retdata )
2020-11-07 14:45:24 -05:00
2020-01-04 11:58:30 -05:00
###############################################################################
# pvc provisioner template system remove
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " remove " , short_help = " Remove system template. " )
@click.argument ( " name " )
2020-01-08 10:34:27 -05:00
@click.option (
2021-11-06 03:02:43 -04:00
" -y " ,
" --yes " ,
" confirm_flag " ,
is_flag = True ,
default = False ,
help = " Confirm the removal " ,
2020-01-08 10:34:27 -05:00
)
2020-06-05 14:49:53 -04:00
@cluster_req
2020-01-08 10:34:27 -05:00
def provisioner_template_system_remove ( name , confirm_flag ) :
2020-01-04 11:58:30 -05:00
"""
2020-01-04 13:04:01 -05:00
Remove system template NAME from the PVC cluster provisioner .
2020-01-04 11:58:30 -05:00
"""
2021-11-06 03:02:43 -04:00
if not confirm_flag and not config [ " unsafe " ] :
2020-01-08 10:34:27 -05:00
try :
2021-11-06 03:02:43 -04:00
click . confirm (
" Remove system template {} " . format ( name ) , prompt_suffix = " ? " , abort = True
)
2020-11-06 18:55:10 -05:00
except Exception :
2020-01-08 10:34:27 -05:00
exit ( 0 )
2021-11-06 03:02:43 -04:00
retcode , retdata = pvc_provisioner . template_remove (
config , name , template_type = " system "
)
2020-01-04 11:58:30 -05:00
cleanup ( retcode , retdata )
###############################################################################
# pvc provisioner template network
###############################################################################
2021-11-06 03:02:43 -04:00
@click.group (
name = " network " ,
short_help = " Manage PVC provisioner network templates. " ,
context_settings = CONTEXT_SETTINGS ,
)
2020-01-04 11:58:30 -05:00
def provisioner_template_network ( ) :
"""
Manage the PVC provisioner network templates .
"""
2020-11-07 14:45:24 -05:00
pass
2020-01-04 11:58:30 -05:00
###############################################################################
# pvc provisioner template network list
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " list " , short_help = " List all network templates. " )
@click.argument ( " limit " , default = None , required = False )
2020-06-05 14:49:53 -04:00
@cluster_req
2020-01-04 11:58:30 -05:00
def provisioner_template_network_list ( limit ) :
"""
List all network templates in the PVC cluster provisioner .
"""
2021-11-06 03:02:43 -04:00
retcode , retdata = pvc_provisioner . template_list (
config , limit , template_type = " network "
)
2020-01-04 11:58:30 -05:00
if retcode :
2021-11-06 03:02:43 -04:00
retdata = pvc_provisioner . format_list_template ( retdata , template_type = " network " )
2020-01-04 11:58:30 -05:00
cleanup ( retcode , retdata )
2020-11-07 14:45:24 -05:00
2020-01-04 11:58:30 -05:00
###############################################################################
# pvc provisioner template network add
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " add " , short_help = " Add new network template. " )
@click.argument ( " name " )
2020-01-04 11:58:30 -05:00
@click.option (
2021-11-06 03:02:43 -04:00
" -m " ,
" --mac-template " ,
" mac_template " ,
2020-01-04 11:58:30 -05:00
default = None ,
2021-11-06 03:02:43 -04:00
help = " Use this template for MAC addresses. " ,
2020-01-04 11:58:30 -05:00
)
2020-06-05 14:49:53 -04:00
@cluster_req
2020-01-04 11:58:30 -05:00
def provisioner_template_network_add ( name , mac_template ) :
"""
Add a new network template to the PVC cluster provisioner .
MAC address templates are used to provide predictable MAC addresses for provisioned VMs .
The normal format of a MAC template is :
{ prefix } : XX : XX : { vmid } { netid }
The { prefix } variable is replaced by the provisioner with a standard prefix ( " 52:54:01 " ) ,
which is different from the randomly - generated MAC prefix ( " 52:54:00 " ) to avoid accidental
overlap of MAC addresses .
The { vmid } variable is replaced by a single hexidecimal digit representing the VM ' s ID,
the numerical suffix portion of its name ; VMs without a suffix numeral have ID 0. VMs with
IDs greater than 15 ( hexidecimal " f " ) will wrap back to 0.
The { netid } variable is replaced by the sequential identifier , starting at 0 , of the
network VNI of the interface ; for example , the first interface is 0 , the second is 1 , etc .
The four X digits are use - configurable . Use these digits to uniquely define the MAC
address .
Example : pvc provisioner template network add - - mac - template " {prefix} :2f:1f: {vmid} {netid} " test - template
The location of the two per - VM variables can be adjusted at the administrator ' s discretion,
or removed if not required ( e . g . a single - network template , or template for a single VM ) .
In such situations , be careful to avoid accidental overlap with other templates ' variable
portions .
"""
params = dict ( )
2021-11-06 03:02:43 -04:00
params [ " name " ] = name
params [ " mac_template " ] = mac_template
2020-01-04 11:58:30 -05:00
2021-11-06 03:02:43 -04:00
retcode , retdata = pvc_provisioner . template_add (
config , params , template_type = " network "
)
2020-01-04 11:58:30 -05:00
cleanup ( retcode , retdata )
2020-11-07 14:45:24 -05:00
2020-01-04 11:58:30 -05:00
###############################################################################
# pvc provisioner template network remove
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " remove " , short_help = " Remove network template. " )
@click.argument ( " name " )
2020-01-08 10:34:27 -05:00
@click.option (
2021-11-06 03:02:43 -04:00
" -y " ,
" --yes " ,
" confirm_flag " ,
is_flag = True ,
default = False ,
help = " Confirm the removal " ,
2020-01-08 10:34:27 -05:00
)
2020-06-05 14:49:53 -04:00
@cluster_req
2020-01-08 10:34:27 -05:00
def provisioner_template_network_remove ( name , confirm_flag ) :
2020-01-04 11:58:30 -05:00
"""
2020-01-04 13:04:01 -05:00
Remove network template MAME from the PVC cluster provisioner .
2020-01-04 11:58:30 -05:00
"""
2021-11-06 03:02:43 -04:00
if not confirm_flag and not config [ " unsafe " ] :
2020-01-08 10:34:27 -05:00
try :
2021-11-06 03:02:43 -04:00
click . confirm (
" Remove network template {} " . format ( name ) ,
prompt_suffix = " ? " ,
abort = True ,
)
2020-11-06 18:55:10 -05:00
except Exception :
2020-01-08 10:34:27 -05:00
exit ( 0 )
2021-11-06 03:02:43 -04:00
retcode , retdata = pvc_provisioner . template_remove (
config , name , template_type = " network "
)
2020-01-04 11:58:30 -05:00
cleanup ( retcode , retdata )
2020-11-07 14:45:24 -05:00
2020-01-04 11:58:30 -05:00
###############################################################################
# pvc provisioner template network vni
###############################################################################
2021-11-06 03:02:43 -04:00
@click.group (
name = " vni " ,
short_help = " Manage PVC provisioner network template VNIs. " ,
context_settings = CONTEXT_SETTINGS ,
)
2020-01-04 11:58:30 -05:00
def provisioner_template_network_vni ( ) :
"""
Manage the network VNIs in PVC provisioner network templates .
"""
2020-11-07 14:45:24 -05:00
pass
2020-01-04 11:58:30 -05:00
###############################################################################
# pvc provisioner template network vni add
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " add " , short_help = " Add network VNI to network template. " )
@click.argument ( " name " )
@click.argument ( " vni " )
2020-06-05 14:49:53 -04:00
@cluster_req
2020-01-04 11:58:30 -05:00
def provisioner_template_network_vni_add ( name , vni ) :
"""
Add a new network VNI to network template NAME .
2020-01-20 21:15:15 -05:00
Networks will be added to VMs in the order they are added and displayed within the template .
2020-01-04 11:58:30 -05:00
"""
params = dict ( )
2021-11-06 03:02:43 -04:00
retcode , retdata = pvc_provisioner . template_element_add (
config , name , vni , params , element_type = " net " , template_type = " network "
)
2020-01-04 11:58:30 -05:00
cleanup ( retcode , retdata )
2020-11-07 14:45:24 -05:00
2020-01-04 11:58:30 -05:00
###############################################################################
# pvc provisioner template network vni remove
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " remove " , short_help = " Remove network VNI from network template. " )
@click.argument ( " name " )
@click.argument ( " vni " )
2020-01-08 10:34:27 -05:00
@click.option (
2021-11-06 03:02:43 -04:00
" -y " ,
" --yes " ,
" confirm_flag " ,
is_flag = True ,
default = False ,
help = " Confirm the removal " ,
2020-01-08 10:34:27 -05:00
)
2020-06-05 14:49:53 -04:00
@cluster_req
2020-01-08 10:34:27 -05:00
def provisioner_template_network_vni_remove ( name , vni , confirm_flag ) :
2020-01-04 11:58:30 -05:00
"""
2020-01-04 13:04:01 -05:00
Remove network VNI from network template NAME .
2020-01-04 11:58:30 -05:00
"""
2021-11-06 03:02:43 -04:00
if not confirm_flag and not config [ " unsafe " ] :
2020-01-08 10:34:27 -05:00
try :
2021-11-06 03:02:43 -04:00
click . confirm (
" Remove VNI {} from network template {} " . format ( vni , name ) ,
prompt_suffix = " ? " ,
abort = True ,
)
2020-11-06 18:55:10 -05:00
except Exception :
2020-01-08 10:34:27 -05:00
exit ( 0 )
2020-01-04 11:58:30 -05:00
2021-11-06 03:02:43 -04:00
retcode , retdata = pvc_provisioner . template_element_remove (
config , name , vni , element_type = " net " , template_type = " network "
)
2020-01-04 11:58:30 -05:00
cleanup ( retcode , retdata )
###############################################################################
# pvc provisioner template storage
###############################################################################
2021-11-06 03:02:43 -04:00
@click.group (
name = " storage " ,
short_help = " Manage PVC provisioner storage templates. " ,
context_settings = CONTEXT_SETTINGS ,
)
2020-01-04 11:58:30 -05:00
def provisioner_template_storage ( ) :
"""
Manage the PVC provisioner storage templates .
"""
2020-11-07 14:45:24 -05:00
pass
2020-01-04 11:58:30 -05:00
###############################################################################
# pvc provisioner template storage list
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " list " , short_help = " List all storage templates. " )
@click.argument ( " limit " , default = None , required = False )
2020-06-05 14:49:53 -04:00
@cluster_req
2020-01-04 11:58:30 -05:00
def provisioner_template_storage_list ( limit ) :
"""
List all storage templates in the PVC cluster provisioner .
"""
2021-11-06 03:02:43 -04:00
retcode , retdata = pvc_provisioner . template_list (
config , limit , template_type = " storage "
)
2020-01-04 11:58:30 -05:00
if retcode :
2021-11-06 03:02:43 -04:00
retdata = pvc_provisioner . format_list_template ( retdata , template_type = " storage " )
2020-01-04 11:58:30 -05:00
cleanup ( retcode , retdata )
2020-11-07 14:45:24 -05:00
2020-01-04 11:58:30 -05:00
###############################################################################
# pvc provisioner template storage add
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " add " , short_help = " Add new storage template. " )
@click.argument ( " name " )
2020-06-05 14:49:53 -04:00
@cluster_req
2020-01-04 11:58:30 -05:00
def provisioner_template_storage_add ( name ) :
"""
Add a new storage template to the PVC cluster provisioner .
"""
params = dict ( )
2021-11-06 03:02:43 -04:00
params [ " name " ] = name
2020-01-04 11:58:30 -05:00
2021-11-06 03:02:43 -04:00
retcode , retdata = pvc_provisioner . template_add (
config , params , template_type = " storage "
)
2020-01-04 11:58:30 -05:00
cleanup ( retcode , retdata )
2020-11-07 14:45:24 -05:00
2020-01-04 11:58:30 -05:00
###############################################################################
# pvc provisioner template storage remove
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " remove " , short_help = " Remove storage template. " )
@click.argument ( " name " )
2020-01-08 10:34:27 -05:00
@click.option (
2021-11-06 03:02:43 -04:00
" -y " ,
" --yes " ,
" confirm_flag " ,
is_flag = True ,
default = False ,
help = " Confirm the removal " ,
2020-01-08 10:34:27 -05:00
)
2020-06-05 14:49:53 -04:00
@cluster_req
2020-01-08 10:34:27 -05:00
def provisioner_template_storage_remove ( name , confirm_flag ) :
2020-01-04 11:58:30 -05:00
"""
2020-01-04 13:04:01 -05:00
Remove storage template NAME from the PVC cluster provisioner .
2020-01-04 11:58:30 -05:00
"""
2021-11-06 03:02:43 -04:00
if not confirm_flag and not config [ " unsafe " ] :
2020-01-08 10:34:27 -05:00
try :
2021-11-06 03:02:43 -04:00
click . confirm (
" Remove storage template {} " . format ( name ) ,
prompt_suffix = " ? " ,
abort = True ,
)
2020-11-06 18:55:10 -05:00
except Exception :
2020-01-08 10:34:27 -05:00
exit ( 0 )
2021-11-06 03:02:43 -04:00
retcode , retdata = pvc_provisioner . template_remove (
config , name , template_type = " storage "
)
2020-01-04 11:58:30 -05:00
cleanup ( retcode , retdata )
2020-11-07 14:45:24 -05:00
2020-01-04 11:58:30 -05:00
###############################################################################
# pvc provisioner template storage disk
###############################################################################
2021-11-06 03:02:43 -04:00
@click.group (
name = " disk " ,
short_help = " Manage PVC provisioner storage template disks. " ,
context_settings = CONTEXT_SETTINGS ,
)
2020-01-04 11:58:30 -05:00
def provisioner_template_storage_disk ( ) :
"""
Manage the disks in PVC provisioner storage templates .
"""
2020-11-07 14:45:24 -05:00
pass
2020-01-04 11:58:30 -05:00
###############################################################################
# pvc provisioner template storage disk add
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " add " , short_help = " Add disk to storage template. " )
@click.argument ( " name " )
@click.argument ( " disk " )
2020-01-04 11:58:30 -05:00
@click.option (
2021-11-06 03:02:43 -04:00
" -p " , " --pool " , " pool " , required = True , help = " The storage pool for the disk. "
2020-01-04 11:58:30 -05:00
)
@click.option (
2021-11-06 03:02:43 -04:00
" -i " ,
" --source-volume " ,
" source_volume " ,
2020-01-05 19:11:52 -05:00
default = None ,
2021-11-06 03:02:43 -04:00
help = " The source volume to clone " ,
2020-01-05 19:11:52 -05:00
)
@click.option (
2021-11-06 03:02:43 -04:00
" -s " , " --size " , " size " , type = int , default = None , help = " The size of the disk (in GB). "
2020-01-04 11:58:30 -05:00
)
@click.option (
2021-11-06 03:02:43 -04:00
" -f " , " --filesystem " , " filesystem " , default = None , help = " The filesystem of the disk. "
2020-01-04 11:58:30 -05:00
)
@click.option (
2021-11-06 03:02:43 -04:00
" --fsarg " ,
" fsargs " ,
default = None ,
multiple = True ,
help = " Additional argument for filesystem creation, in arg=value format without leading dashes. " ,
2020-01-04 11:58:30 -05:00
)
@click.option (
2021-11-06 03:02:43 -04:00
" -m " ,
" --mountpoint " ,
" mountpoint " ,
2020-01-04 11:58:30 -05:00
default = None ,
2021-11-06 03:02:43 -04:00
help = " The target Linux mountpoint of the disk; requires a filesystem. " ,
2020-01-04 11:58:30 -05:00
)
2020-06-05 14:49:53 -04:00
@cluster_req
2021-11-06 03:02:43 -04:00
def provisioner_template_storage_disk_add (
name , disk , pool , source_volume , size , filesystem , fsargs , mountpoint
) :
2020-01-04 11:58:30 -05:00
"""
Add a new DISK to storage template NAME .
2020-01-20 21:15:15 -05:00
DISK must be a Linux - style sdX / vdX disk identifier , such as " sda " or " vdb " . All disks in a template must use the same identifier format .
2020-11-06 19:05:48 -05:00
2020-01-20 21:15:15 -05:00
Disks will be added to VMs in sdX / vdX order . For disks with mountpoints , ensure this order is sensible .
2020-01-04 11:58:30 -05:00
"""
2020-01-05 19:11:52 -05:00
if source_volume and ( size or filesystem or mountpoint ) :
2021-11-08 00:04:20 -05:00
echo (
2021-11-06 03:02:43 -04:00
' The " --source-volume " option is not compatible with the " --size " , " --filesystem " , or " --mountpoint " options. '
)
2020-01-05 19:11:52 -05:00
exit ( 1 )
2020-01-04 11:58:30 -05:00
params = dict ( )
2021-11-06 03:02:43 -04:00
params [ " pool " ] = pool
params [ " source_volume " ] = source_volume
params [ " disk_size " ] = size
2020-01-04 11:58:30 -05:00
if filesystem :
2021-11-06 03:02:43 -04:00
params [ " filesystem " ] = filesystem
2020-01-04 11:58:30 -05:00
if filesystem and fsargs :
dash_fsargs = list ( )
for arg in fsargs :
2021-11-06 03:02:43 -04:00
arg_len = len ( arg . split ( " = " ) [ 0 ] )
2020-01-04 11:58:30 -05:00
if arg_len == 1 :
2021-11-06 03:02:43 -04:00
dash_fsargs . append ( " - " + arg )
2020-01-04 11:58:30 -05:00
else :
2021-11-06 03:02:43 -04:00
dash_fsargs . append ( " -- " + arg )
params [ " filesystem_arg " ] = dash_fsargs
2020-01-04 11:58:30 -05:00
if filesystem and mountpoint :
2021-11-06 03:02:43 -04:00
params [ " mountpoint " ] = mountpoint
2020-01-04 11:58:30 -05:00
2021-11-06 03:02:43 -04:00
retcode , retdata = pvc_provisioner . template_element_add (
config , name , disk , params , element_type = " disk " , template_type = " storage "
)
2020-01-04 11:58:30 -05:00
cleanup ( retcode , retdata )
2020-11-07 14:45:24 -05:00
2020-01-04 11:58:30 -05:00
###############################################################################
# pvc provisioner template storage disk remove
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " remove " , short_help = " Remove disk from storage template. " )
@click.argument ( " name " )
@click.argument ( " disk " )
2020-01-08 10:34:27 -05:00
@click.option (
2021-11-06 03:02:43 -04:00
" -y " ,
" --yes " ,
" confirm_flag " ,
is_flag = True ,
default = False ,
help = " Confirm the removal " ,
2020-01-08 10:34:27 -05:00
)
2020-06-05 14:49:53 -04:00
@cluster_req
2020-01-08 10:34:27 -05:00
def provisioner_template_storage_disk_remove ( name , disk , confirm_flag ) :
2020-01-04 11:58:30 -05:00
"""
2020-01-04 13:04:01 -05:00
Remove DISK from storage template NAME .
DISK must be a Linux - style disk identifier such as " sda " or " vdb " .
2020-01-04 11:58:30 -05:00
"""
2021-11-06 03:02:43 -04:00
if not confirm_flag and not config [ " unsafe " ] :
2020-01-08 10:34:27 -05:00
try :
2021-11-06 03:02:43 -04:00
click . confirm (
" Remove disk {} from storage template {} " . format ( disk , name ) ,
prompt_suffix = " ? " ,
abort = True ,
)
2020-11-06 18:55:10 -05:00
except Exception :
2020-01-08 10:34:27 -05:00
exit ( 0 )
2020-01-04 11:58:30 -05:00
2021-11-06 03:02:43 -04:00
retcode , retdata = pvc_provisioner . template_element_remove (
config , name , disk , element_type = " disk " , template_type = " storage "
)
2020-01-04 11:58:30 -05:00
cleanup ( retcode , retdata )
2020-01-04 13:04:01 -05:00
###############################################################################
# pvc provisioner userdata
###############################################################################
2021-11-06 03:02:43 -04:00
@click.group (
name = " userdata " ,
short_help = " Manage PVC provisioner userdata documents. " ,
context_settings = CONTEXT_SETTINGS ,
)
2020-01-04 13:04:01 -05:00
def provisioner_userdata ( ) :
"""
Manage userdata documents in the PVC provisioner .
"""
2020-11-07 14:45:24 -05:00
pass
2020-01-04 13:04:01 -05:00
###############################################################################
# pvc provisioner userdata list
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " list " , short_help = " List all userdata documents. " )
@click.argument ( " limit " , default = None , required = False )
2020-01-04 13:04:01 -05:00
@click.option (
2021-11-06 03:02:43 -04:00
" -f " ,
" --full " ,
" full " ,
is_flag = True ,
default = False ,
help = " Show all lines of the document instead of first 4. " ,
2020-01-04 13:04:01 -05:00
)
2020-06-05 14:49:53 -04:00
@cluster_req
2020-01-04 13:04:01 -05:00
def provisioner_userdata_list ( limit , full ) :
"""
List all userdata documents in the PVC cluster provisioner .
"""
retcode , retdata = pvc_provisioner . userdata_list ( config , limit )
if retcode :
if not full :
lines = 4
else :
lines = None
2020-01-05 12:35:00 -05:00
retdata = pvc_provisioner . format_list_userdata ( retdata , lines )
2020-01-04 13:04:01 -05:00
cleanup ( retcode , retdata )
2020-11-07 14:45:24 -05:00
2020-02-27 14:31:08 -05:00
###############################################################################
# pvc provisioner userdata show
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " show " , short_help = " Show contents of userdata documents. " )
@click.argument ( " name " )
2020-06-05 14:49:53 -04:00
@cluster_req
2020-02-27 14:31:08 -05:00
def provisioner_userdata_show ( name ) :
"""
Show the full contents of userdata document NAME .
"""
retcode , retdata = pvc_provisioner . userdata_show ( config , name )
cleanup ( retcode , retdata )
2020-11-07 14:45:24 -05:00
2020-01-04 13:04:01 -05:00
###############################################################################
# pvc provisioner userdata add
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " add " , short_help = " Define userdata document from file. " )
@click.argument ( " name " )
@click.argument ( " filename " , type = click . File ( ) )
2020-06-05 14:49:53 -04:00
@cluster_req
2020-01-04 13:04:01 -05:00
def provisioner_userdata_add ( name , filename ) :
"""
Add a new userdata document NAME from file FILENAME .
"""
2020-08-12 14:09:56 -04:00
# Open the YAML file
2020-01-04 13:04:01 -05:00
userdata = filename . read ( )
filename . close ( )
2020-08-12 14:09:56 -04:00
try :
2020-12-15 00:30:20 -05:00
yaml . load ( userdata , Loader = yaml . SafeLoader )
2020-08-12 14:09:56 -04:00
except Exception as e :
2021-11-08 00:04:20 -05:00
echo ( " Error: Userdata document is malformed " )
2020-08-12 14:09:56 -04:00
cleanup ( False , e )
2020-01-04 13:04:01 -05:00
params = dict ( )
2021-11-06 03:02:43 -04:00
params [ " name " ] = name
params [ " data " ] = userdata . strip ( )
2020-01-04 13:04:01 -05:00
retcode , retmsg = pvc_provisioner . userdata_add ( config , params )
cleanup ( retcode , retmsg )
2020-11-07 14:45:24 -05:00
2020-01-04 13:04:01 -05:00
###############################################################################
# pvc provisioner userdata modify
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " modify " , short_help = " Modify existing userdata document. " )
2020-01-04 13:04:01 -05:00
@click.option (
2021-11-06 03:02:43 -04:00
" -e " ,
" --editor " ,
" editor " ,
is_flag = True ,
help = " Use local editor to modify existing document. " ,
2020-01-04 13:04:01 -05:00
)
2021-11-06 03:02:43 -04:00
@click.argument ( " name " )
@click.argument ( " filename " , type = click . File ( ) , default = None , required = False )
2020-06-05 14:49:53 -04:00
@cluster_req
2020-01-04 13:04:01 -05:00
def provisioner_userdata_modify ( name , filename , editor ) :
"""
Modify existing userdata document NAME , either in - editor or with replacement FILE .
"""
2020-11-06 19:36:36 -05:00
if editor is False and filename is None :
2020-01-04 13:04:01 -05:00
cleanup ( False , ' Either a file or the " --editor " option must be specified. ' )
2020-11-06 19:35:19 -05:00
if editor is True :
2020-01-04 13:04:01 -05:00
# Grab the current config
retcode , retdata = pvc_provisioner . userdata_info ( config , name )
if not retcode :
2021-11-08 00:04:20 -05:00
echo ( retdata )
2020-01-04 13:04:01 -05:00
exit ( 1 )
2021-11-06 03:02:43 -04:00
current_userdata = retdata [ " userdata " ] . strip ( )
2020-01-04 13:04:01 -05:00
2021-11-06 03:02:43 -04:00
new_userdata = click . edit (
text = current_userdata , require_save = True , extension = " .yaml "
)
2020-01-08 09:33:01 -05:00
if new_userdata is None :
2021-11-08 00:04:20 -05:00
echo ( " Aborting with no modifications. " )
2020-01-04 13:04:01 -05:00
exit ( 0 )
2020-01-08 09:33:01 -05:00
else :
new_userdata = new_userdata . strip ( )
2020-01-04 13:04:01 -05:00
2020-01-08 09:33:01 -05:00
# Show a diff and confirm
2021-11-08 00:04:20 -05:00
echo ( " Pending modifications: " )
echo ( " " )
2021-11-06 03:02:43 -04:00
diff = list (
difflib . unified_diff (
current_userdata . split ( " \n " ) ,
new_userdata . split ( " \n " ) ,
fromfile = " current " ,
tofile = " modified " ,
fromfiledate = " " ,
tofiledate = " " ,
n = 3 ,
lineterm = " " ,
)
)
2020-01-04 13:04:01 -05:00
for line in diff :
2021-11-06 03:02:43 -04:00
if re . match ( r " ^ \ + " , line ) is not None :
2021-11-08 00:04:20 -05:00
echo ( colorama . Fore . GREEN + line + colorama . Fore . RESET )
2021-11-06 03:02:43 -04:00
elif re . match ( r " ^ \ - " , line ) is not None :
2021-11-08 00:04:20 -05:00
echo ( colorama . Fore . RED + line + colorama . Fore . RESET )
2021-11-06 03:02:43 -04:00
elif re . match ( r " ^ \ ^ " , line ) is not None :
2021-11-08 00:04:20 -05:00
echo ( colorama . Fore . BLUE + line + colorama . Fore . RESET )
2020-01-04 13:04:01 -05:00
else :
2021-11-08 00:04:20 -05:00
echo ( line )
echo ( " " )
2020-01-04 13:04:01 -05:00
2021-11-06 03:02:43 -04:00
click . confirm ( " Write modifications to cluster? " , abort = True )
2020-01-04 13:04:01 -05:00
userdata = new_userdata
# We're operating in replace mode
else :
# Open the new file
userdata = filename . read ( ) . strip ( )
filename . close ( )
2020-08-12 14:09:56 -04:00
try :
2020-12-15 00:30:20 -05:00
yaml . load ( userdata , Loader = yaml . SafeLoader )
2020-08-12 14:09:56 -04:00
except Exception as e :
2021-11-08 00:04:20 -05:00
echo ( " Error: Userdata document is malformed " )
2020-08-12 14:09:56 -04:00
cleanup ( False , e )
2020-01-04 13:04:01 -05:00
params = dict ( )
2021-11-06 03:02:43 -04:00
params [ " data " ] = userdata
2020-01-04 13:04:01 -05:00
retcode , retmsg = pvc_provisioner . userdata_modify ( config , name , params )
cleanup ( retcode , retmsg )
2020-11-07 14:45:24 -05:00
2020-01-04 13:04:01 -05:00
###############################################################################
# pvc provisioner userdata remove
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " remove " , short_help = " Remove userdata document. " )
@click.argument ( " name " )
2020-01-08 10:34:27 -05:00
@click.option (
2021-11-06 03:02:43 -04:00
" -y " ,
" --yes " ,
" confirm_flag " ,
is_flag = True ,
default = False ,
help = " Confirm the removal " ,
2020-01-08 10:34:27 -05:00
)
2020-06-05 14:49:53 -04:00
@cluster_req
2020-01-08 10:34:27 -05:00
def provisioner_userdata_remove ( name , confirm_flag ) :
2020-01-04 13:04:01 -05:00
"""
Remove userdata document NAME from the PVC cluster provisioner .
"""
2021-11-06 03:02:43 -04:00
if not confirm_flag and not config [ " unsafe " ] :
2020-01-08 10:34:27 -05:00
try :
2021-11-06 03:02:43 -04:00
click . confirm (
" Remove userdata document {} " . format ( name ) ,
prompt_suffix = " ? " ,
abort = True ,
)
2020-11-06 18:55:10 -05:00
except Exception :
2020-01-08 10:34:27 -05:00
exit ( 0 )
2020-01-04 13:04:01 -05:00
retcode , retdata = pvc_provisioner . userdata_remove ( config , name )
cleanup ( retcode , retdata )
###############################################################################
# pvc provisioner script
###############################################################################
2021-11-06 03:02:43 -04:00
@click.group (
name = " script " ,
short_help = " Manage PVC provisioner scripts. " ,
context_settings = CONTEXT_SETTINGS ,
)
2020-01-04 13:04:01 -05:00
def provisioner_script ( ) :
"""
Manage scripts in the PVC provisioner .
"""
2020-11-07 14:45:24 -05:00
pass
2020-01-04 13:04:01 -05:00
###############################################################################
# pvc provisioner script list
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " list " , short_help = " List all scripts. " )
@click.argument ( " limit " , default = None , required = False )
2020-01-04 13:04:01 -05:00
@click.option (
2021-11-06 03:02:43 -04:00
" -f " ,
" --full " ,
" full " ,
is_flag = True ,
default = False ,
help = " Show all lines of the document instead of first 4. " ,
2020-01-04 13:04:01 -05:00
)
2020-06-05 14:49:53 -04:00
@cluster_req
2020-01-04 13:04:01 -05:00
def provisioner_script_list ( limit , full ) :
"""
List all scripts in the PVC cluster provisioner .
"""
retcode , retdata = pvc_provisioner . script_list ( config , limit )
if retcode :
if not full :
lines = 4
else :
lines = None
2020-01-05 12:35:00 -05:00
retdata = pvc_provisioner . format_list_script ( retdata , lines )
2020-01-04 13:04:01 -05:00
cleanup ( retcode , retdata )
2020-11-07 14:45:24 -05:00
2020-02-27 14:31:08 -05:00
###############################################################################
# pvc provisioner script show
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " show " , short_help = " Show contents of script documents. " )
@click.argument ( " name " )
2020-06-05 14:49:53 -04:00
@cluster_req
2020-02-27 14:31:08 -05:00
def provisioner_script_show ( name ) :
"""
Show the full contents of script document NAME .
"""
retcode , retdata = pvc_provisioner . script_show ( config , name )
cleanup ( retcode , retdata )
2020-11-07 14:45:24 -05:00
2020-01-04 13:04:01 -05:00
###############################################################################
# pvc provisioner script add
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " add " , short_help = " Define script from file. " )
@click.argument ( " name " )
@click.argument ( " filename " , type = click . File ( ) )
2020-06-05 14:49:53 -04:00
@cluster_req
2020-01-04 13:04:01 -05:00
def provisioner_script_add ( name , filename ) :
"""
Add a new script NAME from file FILENAME .
"""
# Open the XML file
script = filename . read ( )
filename . close ( )
params = dict ( )
2021-11-06 03:02:43 -04:00
params [ " name " ] = name
params [ " data " ] = script . strip ( )
2020-01-04 13:04:01 -05:00
retcode , retmsg = pvc_provisioner . script_add ( config , params )
cleanup ( retcode , retmsg )
2020-11-07 14:45:24 -05:00
2020-01-04 13:04:01 -05:00
###############################################################################
# pvc provisioner script modify
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " modify " , short_help = " Modify existing script. " )
2020-01-04 13:04:01 -05:00
@click.option (
2021-11-06 03:02:43 -04:00
" -e " ,
" --editor " ,
" editor " ,
is_flag = True ,
help = " Use local editor to modify existing document. " ,
2020-01-04 13:04:01 -05:00
)
2021-11-06 03:02:43 -04:00
@click.argument ( " name " )
@click.argument ( " filename " , type = click . File ( ) , default = None , required = False )
2020-06-05 14:49:53 -04:00
@cluster_req
2020-01-04 13:04:01 -05:00
def provisioner_script_modify ( name , filename , editor ) :
"""
Modify existing script NAME , either in - editor or with replacement FILE .
"""
2020-11-06 19:36:36 -05:00
if editor is False and filename is None :
2020-01-04 13:04:01 -05:00
cleanup ( False , ' Either a file or the " --editor " option must be specified. ' )
2020-11-06 19:35:19 -05:00
if editor is True :
2020-01-04 13:04:01 -05:00
# Grab the current config
retcode , retdata = pvc_provisioner . script_info ( config , name )
if not retcode :
2021-11-08 00:04:20 -05:00
echo ( retdata )
2020-01-04 13:04:01 -05:00
exit ( 1 )
2021-11-06 03:02:43 -04:00
current_script = retdata [ " script " ] . strip ( )
2020-01-04 13:04:01 -05:00
2021-11-06 03:02:43 -04:00
new_script = click . edit ( text = current_script , require_save = True , extension = " .py " )
2020-01-08 09:33:01 -05:00
if new_script is None :
2021-11-08 00:04:20 -05:00
echo ( " Aborting with no modifications. " )
2020-01-04 13:04:01 -05:00
exit ( 0 )
2020-01-08 09:33:01 -05:00
else :
new_script = new_script . strip ( )
2020-01-04 13:04:01 -05:00
2020-01-08 09:33:01 -05:00
# Show a diff and confirm
2021-11-08 00:04:20 -05:00
echo ( " Pending modifications: " )
echo ( " " )
2021-11-06 03:02:43 -04:00
diff = list (
difflib . unified_diff (
current_script . split ( " \n " ) ,
new_script . split ( " \n " ) ,
fromfile = " current " ,
tofile = " modified " ,
fromfiledate = " " ,
tofiledate = " " ,
n = 3 ,
lineterm = " " ,
)
)
2020-01-04 13:04:01 -05:00
for line in diff :
2021-11-06 03:02:43 -04:00
if re . match ( r " ^ \ + " , line ) is not None :
2021-11-08 00:04:20 -05:00
echo ( colorama . Fore . GREEN + line + colorama . Fore . RESET )
2021-11-06 03:02:43 -04:00
elif re . match ( r " ^ \ - " , line ) is not None :
2021-11-08 00:04:20 -05:00
echo ( colorama . Fore . RED + line + colorama . Fore . RESET )
2021-11-06 03:02:43 -04:00
elif re . match ( r " ^ \ ^ " , line ) is not None :
2021-11-08 00:04:20 -05:00
echo ( colorama . Fore . BLUE + line + colorama . Fore . RESET )
2020-01-04 13:04:01 -05:00
else :
2021-11-08 00:04:20 -05:00
echo ( line )
echo ( " " )
2020-01-04 13:04:01 -05:00
2021-11-06 03:02:43 -04:00
click . confirm ( " Write modifications to cluster? " , abort = True )
2020-01-04 13:04:01 -05:00
script = new_script
# We're operating in replace mode
else :
# Open the new file
script = filename . read ( ) . strip ( )
filename . close ( )
params = dict ( )
2021-11-06 03:02:43 -04:00
params [ " data " ] = script
2020-01-04 13:04:01 -05:00
retcode , retmsg = pvc_provisioner . script_modify ( config , name , params )
cleanup ( retcode , retmsg )
2020-11-07 14:45:24 -05:00
2020-01-04 13:04:01 -05:00
###############################################################################
# pvc provisioner script remove
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " remove " , short_help = " Remove script. " )
@click.argument ( " name " )
2020-01-08 10:34:27 -05:00
@click.option (
2021-11-06 03:02:43 -04:00
" -y " ,
" --yes " ,
" confirm_flag " ,
is_flag = True ,
default = False ,
help = " Confirm the removal " ,
2020-01-08 10:34:27 -05:00
)
2020-06-05 14:49:53 -04:00
@cluster_req
2020-01-08 10:34:27 -05:00
def provisioner_script_remove ( name , confirm_flag ) :
2020-01-04 13:04:01 -05:00
"""
Remove script NAME from the PVC cluster provisioner .
"""
2021-11-06 03:02:43 -04:00
if not confirm_flag and not config [ " unsafe " ] :
2020-01-08 10:34:27 -05:00
try :
2021-11-06 03:02:43 -04:00
click . confirm (
" Remove provisioning script {} " . format ( name ) ,
prompt_suffix = " ? " ,
abort = True ,
)
2020-11-06 18:55:10 -05:00
except Exception :
2020-01-08 10:34:27 -05:00
exit ( 0 )
2020-01-04 13:04:01 -05:00
retcode , retdata = pvc_provisioner . script_remove ( config , name )
cleanup ( retcode , retdata )
2020-01-04 11:58:30 -05:00
2020-01-02 11:18:46 -05:00
2020-02-17 22:52:49 -05:00
###############################################################################
# pvc provisioner ova
###############################################################################
2021-11-06 03:02:43 -04:00
@click.group (
name = " ova " ,
short_help = " Manage PVC provisioner OVA images. " ,
context_settings = CONTEXT_SETTINGS ,
)
2020-02-17 22:52:49 -05:00
def provisioner_ova ( ) :
"""
Manage ovas in the PVC provisioner .
"""
2020-11-07 14:45:24 -05:00
pass
2020-02-17 22:52:49 -05:00
###############################################################################
# pvc provisioner ova list
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " list " , short_help = " List all OVA images. " )
@click.argument ( " limit " , default = None , required = False )
2020-06-05 14:49:53 -04:00
@cluster_req
2020-02-17 22:52:49 -05:00
def provisioner_ova_list ( limit ) :
"""
List all OVA images in the PVC cluster provisioner .
"""
retcode , retdata = pvc_provisioner . ova_list ( config , limit )
if retcode :
retdata = pvc_provisioner . format_list_ova ( retdata )
cleanup ( retcode , retdata )
2020-11-07 14:45:24 -05:00
2020-02-17 22:52:49 -05:00
###############################################################################
# pvc provisioner ova upload
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " upload " , short_help = " Upload OVA file. " )
@click.argument ( " name " )
@click.argument ( " filename " )
2020-02-17 22:52:49 -05:00
@click.option (
2021-11-06 03:02:43 -04:00
" -p " , " --pool " , " pool " , required = True , help = " The storage pool for the OVA images. "
2020-02-17 22:52:49 -05:00
)
2020-06-05 14:49:53 -04:00
@cluster_req
2020-02-17 22:52:49 -05:00
def provisioner_ova_upload ( name , filename , pool ) :
"""
Upload a new OVA image NAME from FILENAME .
Only single - file ( . ova ) OVA / OVF images are supported . For multi - file ( . ovf + . vmdk ) OVF images , concatenate them with " tar " then upload the resulting file .
Once uploaded , a provisioner system template and OVA - type profile , each named NAME , will be created to store the configuration of the OVA .
Note that the provisioner profile for the OVA will not contain any network template definitions , and will ignore network definitions from the OVA itself . The administrator must modify the profile ' s network template as appropriate to set the desired network configuration.
Storage templates , provisioning scripts , and arguments for OVA - type profiles will be ignored and should not be set .
"""
if not os . path . exists ( filename ) :
2021-11-08 00:04:20 -05:00
echo ( " ERROR: File ' {} ' does not exist! " . format ( filename ) )
2020-02-17 22:52:49 -05:00
exit ( 1 )
params = dict ( )
2021-11-06 03:02:43 -04:00
params [ " pool " ] = pool
params [ " ova_size " ] = os . path . getsize ( filename )
2020-02-17 22:52:49 -05:00
retcode , retdata = pvc_provisioner . ova_upload ( config , name , filename , params )
cleanup ( retcode , retdata )
2020-11-07 14:45:24 -05:00
2020-02-17 22:52:49 -05:00
###############################################################################
# pvc provisioner ova remove
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " remove " , short_help = " Remove OVA image. " )
@click.argument ( " name " )
2020-02-17 22:52:49 -05:00
@click.option (
2021-11-06 03:02:43 -04:00
" -y " ,
" --yes " ,
" confirm_flag " ,
is_flag = True ,
default = False ,
help = " Confirm the removal " ,
2020-02-17 22:52:49 -05:00
)
2020-06-05 14:49:53 -04:00
@cluster_req
2020-02-17 22:52:49 -05:00
def provisioner_ova_remove ( name , confirm_flag ) :
"""
Remove OVA image NAME from the PVC cluster provisioner .
"""
2021-11-06 03:02:43 -04:00
if not confirm_flag and not config [ " unsafe " ] :
2020-02-17 22:52:49 -05:00
try :
2021-11-06 03:02:43 -04:00
click . confirm (
" Remove OVA image {} " . format ( name ) , prompt_suffix = " ? " , abort = True
)
2020-11-06 18:55:10 -05:00
except Exception :
2020-02-17 22:52:49 -05:00
exit ( 0 )
retcode , retdata = pvc_provisioner . ova_remove ( config , name )
cleanup ( retcode , retdata )
2020-01-04 14:06:36 -05:00
###############################################################################
# pvc provisioner profile
###############################################################################
2021-11-06 03:02:43 -04:00
@click.group (
name = " profile " ,
short_help = " Manage PVC provisioner profiless. " ,
context_settings = CONTEXT_SETTINGS ,
)
2020-01-04 14:06:36 -05:00
def provisioner_profile ( ) :
"""
Manage profiles in the PVC provisioner .
"""
2020-11-07 14:45:24 -05:00
pass
2020-01-04 14:06:36 -05:00
###############################################################################
# pvc provisioner profile list
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " list " , short_help = " List all profiles. " )
@click.argument ( " limit " , default = None , required = False )
2020-06-05 14:49:53 -04:00
@cluster_req
2020-01-04 14:06:36 -05:00
def provisioner_profile_list ( limit ) :
"""
List all profiles in the PVC cluster provisioner .
"""
retcode , retdata = pvc_provisioner . profile_list ( config , limit )
if retcode :
2020-01-05 12:35:00 -05:00
retdata = pvc_provisioner . format_list_profile ( retdata )
2020-01-04 14:06:36 -05:00
cleanup ( retcode , retdata )
2020-11-07 14:45:24 -05:00
2020-01-04 14:06:36 -05:00
###############################################################################
# pvc provisioner profile add
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " add " , short_help = " Add provisioner profile. " )
@click.argument ( " name " )
2020-01-04 14:06:36 -05:00
@click.option (
2021-11-06 03:02:43 -04:00
" -p " ,
" --profile-type " ,
" profile_type " ,
default = " provisioner " ,
show_default = True ,
type = click . Choice ( [ " provisioner " , " ova " ] , case_sensitive = False ) ,
help = " The type of profile. " ,
2020-01-04 14:06:36 -05:00
)
@click.option (
2021-11-06 03:02:43 -04:00
" -s " ,
" --system-template " ,
" system_template " ,
2022-10-06 10:27:08 -04:00
required = True ,
help = " The system template for the profile (required). " ,
2020-01-04 14:06:36 -05:00
)
@click.option (
2021-11-06 03:02:43 -04:00
" -n " ,
" --network-template " ,
" network_template " ,
help = " The network template for the profile. " ,
2020-01-04 14:06:36 -05:00
)
@click.option (
2021-11-06 03:02:43 -04:00
" -t " ,
" --storage-template " ,
" storage_template " ,
help = " The storage template for the profile. " ,
2020-01-04 14:06:36 -05:00
)
@click.option (
2022-10-06 10:27:08 -04:00
" -u " ,
" --userdata " ,
" userdata " ,
help = " The userdata document for the profile. " ,
)
@click.option (
" -x " ,
" --script " ,
" script " ,
required = True ,
help = " The script for the profile (required). " ,
)
@click.option (
" -o " ,
" --ova " ,
" ova " ,
help = " The OVA image for the profile; set automatically with ' provisioner ova upload ' . " ,
2020-01-04 14:06:36 -05:00
)
2020-02-17 22:52:49 -05:00
@click.option (
2021-11-06 03:02:43 -04:00
" -a " ,
" --script-arg " ,
" script_args " ,
default = [ ] ,
multiple = True ,
help = " Additional argument to the script install() function in key=value format. " ,
2020-01-04 14:06:36 -05:00
)
2020-06-05 14:49:53 -04:00
@cluster_req
2021-11-06 03:02:43 -04:00
def provisioner_profile_add (
name ,
profile_type ,
system_template ,
network_template ,
storage_template ,
userdata ,
script ,
ova ,
script_args ,
) :
2020-01-04 14:06:36 -05:00
"""
Add a new provisioner profile NAME .
"""
params = dict ( )
2021-11-06 03:02:43 -04:00
params [ " name " ] = name
params [ " profile_type " ] = profile_type
params [ " system_template " ] = system_template
params [ " network_template " ] = network_template
params [ " storage_template " ] = storage_template
params [ " userdata " ] = userdata
params [ " script " ] = script
params [ " ova " ] = ova
params [ " arg " ] = script_args
2020-01-04 14:06:36 -05:00
retcode , retdata = pvc_provisioner . profile_add ( config , params )
cleanup ( retcode , retdata )
2020-11-07 14:45:24 -05:00
2020-01-04 14:06:36 -05:00
###############################################################################
# pvc provisioner profile modify
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " modify " , short_help = " Modify provisioner profile. " )
@click.argument ( " name " )
2020-01-04 14:06:36 -05:00
@click.option (
2021-11-06 03:02:43 -04:00
" -s " ,
" --system-template " ,
" system_template " ,
2020-01-04 14:06:36 -05:00
default = None ,
2021-11-06 03:02:43 -04:00
help = " The system template for the profile. " ,
2020-01-04 14:06:36 -05:00
)
@click.option (
2021-11-06 03:02:43 -04:00
" -n " ,
" --network-template " ,
" network_template " ,
2020-01-04 14:06:36 -05:00
default = None ,
2021-11-06 03:02:43 -04:00
help = " The network template for the profile. " ,
2020-01-04 14:06:36 -05:00
)
@click.option (
2021-11-06 03:02:43 -04:00
" -t " ,
" --storage-template " ,
" storage_template " ,
2020-01-04 14:06:36 -05:00
default = None ,
2021-11-06 03:02:43 -04:00
help = " The storage template for the profile. " ,
2020-01-04 14:06:36 -05:00
)
@click.option (
2021-11-06 03:02:43 -04:00
" -u " ,
" --userdata " ,
" userdata " ,
2020-01-04 14:06:36 -05:00
default = None ,
2021-11-06 03:02:43 -04:00
help = " The userdata document for the profile. " ,
2020-01-04 14:06:36 -05:00
)
@click.option (
2021-11-06 03:02:43 -04:00
" -x " , " --script " , " script " , default = None , help = " The script for the profile. "
2020-01-04 14:06:36 -05:00
)
@click.option (
2021-11-06 03:02:43 -04:00
" -d " ,
" --delete-script-args " ,
" delete_script_args " ,
default = False ,
is_flag = True ,
help = " Delete any existing script arguments. " ,
2020-01-04 14:06:36 -05:00
)
@click.option (
2021-11-06 03:02:43 -04:00
" -a " ,
" --script-arg " ,
" script_args " ,
default = None ,
multiple = True ,
help = " Additional argument to the script install() function in key=value format. " ,
2020-01-04 14:06:36 -05:00
)
2020-06-05 14:49:53 -04:00
@cluster_req
2021-11-06 03:02:43 -04:00
def provisioner_profile_modify (
name ,
system_template ,
network_template ,
storage_template ,
userdata ,
script ,
delete_script_args ,
script_args ,
) :
2020-01-04 14:06:36 -05:00
"""
Modify existing provisioner profile NAME .
"""
params = dict ( )
if system_template is not None :
2021-11-06 03:02:43 -04:00
params [ " system_template " ] = system_template
2020-01-04 14:06:36 -05:00
if network_template is not None :
2021-11-06 03:02:43 -04:00
params [ " network_template " ] = network_template
2020-01-04 14:06:36 -05:00
if storage_template is not None :
2021-11-06 03:02:43 -04:00
params [ " storage_template " ] = storage_template
2020-01-04 14:06:36 -05:00
if userdata is not None :
2021-11-06 03:02:43 -04:00
params [ " userdata " ] = userdata
2020-01-04 14:06:36 -05:00
if script is not None :
2021-11-06 03:02:43 -04:00
params [ " script " ] = script
2020-01-04 14:06:36 -05:00
if delete_script_args :
2021-11-06 03:02:43 -04:00
params [ " arg " ] = [ ]
2020-01-04 14:06:36 -05:00
if script_args is not None :
2021-11-06 03:02:43 -04:00
params [ " arg " ] = script_args
2020-01-04 14:06:36 -05:00
retcode , retdata = pvc_provisioner . profile_modify ( config , name , params )
cleanup ( retcode , retdata )
2020-11-07 14:45:24 -05:00
2020-01-04 14:06:36 -05:00
###############################################################################
# pvc provisioner profile remove
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " remove " , short_help = " Remove profile. " )
@click.argument ( " name " )
2020-01-08 10:34:27 -05:00
@click.option (
2021-11-06 03:02:43 -04:00
" -y " ,
" --yes " ,
" confirm_flag " ,
is_flag = True ,
default = False ,
help = " Confirm the removal " ,
2020-01-08 10:34:27 -05:00
)
2020-06-05 14:49:53 -04:00
@cluster_req
2020-01-08 10:34:27 -05:00
def provisioner_profile_remove ( name , confirm_flag ) :
2020-01-04 14:06:36 -05:00
"""
Remove profile NAME from the PVC cluster provisioner .
"""
2021-11-06 03:02:43 -04:00
if not confirm_flag and not config [ " unsafe " ] :
2020-01-08 10:34:27 -05:00
try :
2021-11-06 03:02:43 -04:00
click . confirm (
" Remove profile {} " . format ( name ) , prompt_suffix = " ? " , abort = True
)
2020-11-06 18:55:10 -05:00
except Exception :
2020-01-08 10:34:27 -05:00
exit ( 0 )
2020-01-04 14:06:36 -05:00
retcode , retdata = pvc_provisioner . profile_remove ( config , name )
cleanup ( retcode , retdata )
2020-01-02 11:18:46 -05:00
2020-01-04 14:31:22 -05:00
###############################################################################
# pvc provisioner create
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " create " , short_help = " Create new VM. " )
@click.argument ( " name " )
@click.argument ( " profile " )
2020-07-08 13:18:12 -04:00
@click.option (
2021-11-06 03:02:43 -04:00
" -a " ,
" --script-arg " ,
" script_args " ,
default = [ ] ,
multiple = True ,
help = " Additional argument to the script install() function in key=value format. " ,
2020-07-08 13:18:12 -04:00
)
2020-01-08 20:13:26 -05:00
@click.option (
2021-11-06 03:02:43 -04:00
" -d/-D " ,
" --define/--no-define " ,
" define_flag " ,
is_flag = True ,
default = True ,
show_default = True ,
help = " Define the VM automatically during provisioning. " ,
2020-01-09 09:46:58 -05:00
)
2020-01-08 20:13:26 -05:00
@click.option (
2021-11-06 03:02:43 -04:00
" -s/-S " ,
" --start/--no-start " ,
" start_flag " ,
is_flag = True ,
default = True ,
show_default = True ,
help = " Start the VM automatically upon completion of provisioning. " ,
2020-01-09 09:46:58 -05:00
)
2020-01-08 14:41:19 -05:00
@click.option (
2021-11-06 03:02:43 -04:00
" -w " ,
" --wait " ,
" wait_flag " ,
is_flag = True ,
default = False ,
help = " Wait for provisioning to complete, showing progress " ,
2020-01-08 14:41:19 -05:00
)
2020-06-05 14:49:53 -04:00
@cluster_req
2020-07-08 13:18:12 -04:00
def provisioner_create ( name , profile , wait_flag , define_flag , start_flag , script_args ) :
2020-01-04 14:31:22 -05:00
"""
Create a new VM NAME with profile PROFILE .
2020-01-08 20:13:26 -05:00
The " --no-start " flag can be used to prevent automatic startup of the VM once provisioning
is completed . This can be useful for the administrator to preform additional actions to
the VM after provisioning is completed . Note that the VM will remain in " provision " state
until its state is explicitly changed ( e . g . with " pvc vm start " ) .
The " --no-define " flag implies " --no-start " , and can be used to prevent definition of the
created VM on the PVC cluster . This can be useful for the administrator to create a " template "
set of VM disks via the normal provisioner , but without ever starting the resulting VM . The
resulting disk ( s ) can then be used as source volumes in other disk templates .
2020-07-08 13:18:12 -04:00
The " --script-arg " option can be specified as many times as required to pass additional ,
VM - specific arguments to the provisioner install ( ) function , beyond those set by the profile .
2020-01-04 14:31:22 -05:00
"""
2020-01-08 20:13:26 -05:00
if not define_flag :
start_flag = False
2021-11-06 03:02:43 -04:00
retcode , retdata = pvc_provisioner . vm_create (
config , name , profile , wait_flag , define_flag , start_flag , script_args
)
2020-01-08 14:41:19 -05:00
if retcode and wait_flag :
task_id = retdata
2021-11-08 00:04:20 -05:00
echo ( " Task ID: {} " . format ( task_id ) )
2021-11-25 09:33:26 -05:00
echo ( " " )
2020-01-08 14:41:19 -05:00
# Wait for the task to start
2021-11-08 00:04:20 -05:00
echo ( " Waiting for task to start... " , nl = False )
2020-01-08 14:41:19 -05:00
while True :
time . sleep ( 1 )
task_status = pvc_provisioner . task_status ( config , task_id , is_watching = True )
2021-11-06 03:02:43 -04:00
if task_status . get ( " state " ) != " PENDING " :
2020-01-08 14:41:19 -05:00
break
2021-11-08 00:04:20 -05:00
echo ( " . " , nl = False )
echo ( " done. " )
2021-11-25 09:33:26 -05:00
echo ( " " )
2020-01-08 14:41:19 -05:00
# Start following the task state, updating progress as we go
2021-11-06 03:02:43 -04:00
total_task = task_status . get ( " total " )
2020-01-08 17:07:57 -05:00
with click . progressbar ( length = total_task , show_eta = False ) as bar :
2020-01-08 14:41:19 -05:00
last_task = 0
maxlen = 0
while True :
time . sleep ( 1 )
2021-11-06 03:02:43 -04:00
if task_status . get ( " state " ) != " RUNNING " :
2020-01-08 14:41:19 -05:00
break
2021-11-06 03:02:43 -04:00
if task_status . get ( " current " ) > last_task :
current_task = int ( task_status . get ( " current " ) )
2020-01-08 14:41:19 -05:00
bar . update ( current_task - last_task )
last_task = current_task
# The extensive spaces at the end cause this to overwrite longer previous messages
2021-11-06 03:02:43 -04:00
curlen = len ( str ( task_status . get ( " status " ) ) )
2020-01-08 14:41:19 -05:00
if curlen > maxlen :
maxlen = curlen
lendiff = maxlen - curlen
overwrite_whitespace = " " * lendiff
2021-11-08 00:04:20 -05:00
echo (
2021-11-06 03:02:43 -04:00
" " + task_status . get ( " status " ) + overwrite_whitespace ,
nl = False ,
)
task_status = pvc_provisioner . task_status (
config , task_id , is_watching = True
)
if task_status . get ( " state " ) == " SUCCESS " :
2020-01-08 17:07:57 -05:00
bar . update ( total_task - last_task )
2020-01-08 14:41:19 -05:00
2021-11-25 09:33:26 -05:00
echo ( " " )
2021-11-06 03:02:43 -04:00
retdata = task_status . get ( " state " ) + " : " + task_status . get ( " status " )
2020-01-04 14:31:22 -05:00
2020-01-08 14:41:19 -05:00
cleanup ( retcode , retdata )
2020-01-04 14:31:22 -05:00
2020-11-07 14:45:24 -05:00
2020-01-04 14:31:22 -05:00
###############################################################################
# pvc provisioner status
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " status " , short_help = " Show status of provisioner job. " )
@click.argument ( " job " , required = False , default = None )
2020-06-05 14:49:53 -04:00
@cluster_req
2020-01-04 14:31:22 -05:00
def provisioner_status ( job ) :
"""
2020-01-12 14:01:47 -05:00
Show status of provisioner job JOB or a list of jobs .
2020-01-04 14:31:22 -05:00
"""
retcode , retdata = pvc_provisioner . task_status ( config , job )
2020-01-12 14:23:11 -05:00
if job is None and retcode :
retdata = pvc_provisioner . format_list_task ( retdata )
2020-01-04 14:31:22 -05:00
cleanup ( retcode , retdata )
2020-01-02 11:18:46 -05:00
2020-01-09 10:53:27 -05:00
###############################################################################
# pvc maintenance
###############################################################################
2021-11-06 03:02:43 -04:00
@click.group (
name = " maintenance " ,
short_help = " Manage PVC cluster maintenance state. " ,
context_settings = CONTEXT_SETTINGS ,
)
2020-01-09 10:53:27 -05:00
def cli_maintenance ( ) :
"""
Manage the maintenance mode of the PVC cluster .
"""
2020-11-07 14:45:24 -05:00
pass
2020-01-02 11:18:46 -05:00
2020-01-09 10:53:27 -05:00
###############################################################################
# pvc maintenance on
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " on " , short_help = " Enable cluster maintenance mode. " )
2020-06-05 14:49:53 -04:00
@cluster_req
2020-01-09 10:53:27 -05:00
def maintenance_on ( ) :
"""
Enable maintenance mode on the PVC cluster .
"""
2021-11-06 03:02:43 -04:00
retcode , retdata = pvc_cluster . maintenance_mode ( config , " true " )
2020-01-09 10:53:27 -05:00
cleanup ( retcode , retdata )
2020-01-02 11:18:46 -05:00
2020-11-07 14:45:24 -05:00
2020-01-09 10:53:27 -05:00
###############################################################################
# pvc maintenance off
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " off " , short_help = " Disable cluster maintenance mode. " )
2020-06-05 14:49:53 -04:00
@cluster_req
2020-01-09 10:53:27 -05:00
def maintenance_off ( ) :
"""
Disable maintenance mode on the PVC cluster .
"""
2021-11-06 03:02:43 -04:00
retcode , retdata = pvc_cluster . maintenance_mode ( config , " false " )
2020-01-09 10:53:27 -05:00
cleanup ( retcode , retdata )
2020-01-02 11:18:46 -05:00
2019-08-25 21:18:33 -04:00
###############################################################################
2019-10-22 11:23:12 -04:00
# pvc status
2019-08-25 21:18:33 -04:00
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " status " , short_help = " Show current cluster status. " )
2019-10-22 11:23:12 -04:00
@click.option (
2021-11-06 03:02:43 -04:00
" -f " ,
" --format " ,
" oformat " ,
default = " plain " ,
show_default = True ,
type = click . Choice ( [ " plain " , " short " , " json " , " json-pretty " ] ) ,
help = " Output format of cluster status information. " ,
2019-10-22 11:23:12 -04:00
)
2020-06-05 14:49:53 -04:00
@cluster_req
2019-10-22 11:23:12 -04:00
def status_cluster ( oformat ) :
"""
Show basic information and health for the active PVC cluster .
2020-11-17 12:32:16 -05:00
Output formats :
2021-04-12 15:55:59 -04:00
2020-11-17 12:32:16 -05:00
plain : Full text , full colour output for human - readability .
2021-04-12 15:55:59 -04:00
2020-11-17 12:32:16 -05:00
short : Health - only , full colour output for human - readability .
2021-04-12 15:55:59 -04:00
2020-11-17 12:32:16 -05:00
json : Compact JSON representation for machine parsing .
2021-04-12 15:55:59 -04:00
2020-11-17 12:32:16 -05:00
json - pretty : Pretty - printed JSON representation for machine parsing or human - readability .
2019-10-22 11:23:12 -04:00
"""
2020-01-02 12:18:41 -05:00
2019-12-29 20:33:51 -05:00
retcode , retdata = pvc_cluster . get_info ( config )
2019-10-22 11:23:12 -04:00
if retcode :
2020-01-05 12:35:00 -05:00
retdata = pvc_cluster . format_info ( retdata , oformat )
2019-12-29 20:33:51 -05:00
cleanup ( retcode , retdata )
2019-10-10 14:09:40 -04:00
2020-11-07 14:45:24 -05:00
2020-11-24 02:39:06 -05:00
###############################################################################
# pvc task
###############################################################################
2021-11-06 03:02:43 -04:00
@click.group (
name = " task " ,
short_help = " Perform PVC cluster tasks. " ,
context_settings = CONTEXT_SETTINGS ,
)
2020-11-24 02:39:06 -05:00
def cli_task ( ) :
"""
Perform administrative tasks against the PVC cluster .
"""
pass
###############################################################################
# pvc task backup
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " backup " , short_help = " Create JSON backup of cluster. " )
2020-11-24 02:39:06 -05:00
@click.option (
2021-11-06 03:02:43 -04:00
" -f " ,
" --file " ,
" filename " ,
default = None ,
type = click . File ( mode = " w " ) ,
help = " Write backup data to this file. " ,
2020-11-24 02:39:06 -05:00
)
@cluster_req
def task_backup ( filename ) :
"""
Create a JSON - format backup of the cluster Zookeeper database .
"""
retcode , retdata = pvc_cluster . backup ( config )
2021-06-13 21:57:36 -04:00
if retcode :
if filename is not None :
json . dump ( json . loads ( retdata ) , filename )
cleanup ( retcode , ' Backup written to " {} " . ' . format ( filename . name ) )
else :
cleanup ( retcode , retdata )
else :
cleanup ( retcode , retdata )
2020-11-24 02:39:06 -05:00
###############################################################################
# pvc task restore
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " restore " , short_help = " Restore JSON backup to cluster. " )
2020-11-24 02:39:06 -05:00
@click.option (
2021-11-06 03:02:43 -04:00
" -f " ,
" --file " ,
" filename " ,
required = True ,
default = None ,
type = click . File ( ) ,
help = " Read backup data from this file. " ,
2020-11-24 02:39:06 -05:00
)
@click.option (
2021-11-06 03:02:43 -04:00
" -y " ,
" --yes " ,
" confirm_flag " ,
is_flag = True ,
default = False ,
help = " Confirm the restore " ,
2020-11-24 02:39:06 -05:00
)
@cluster_req
def task_restore ( filename , confirm_flag ) :
"""
Restore the JSON backup data from a file to the cluster .
"""
2021-11-06 03:02:43 -04:00
if not confirm_flag and not config [ " unsafe " ] :
2020-11-24 02:39:06 -05:00
try :
2021-11-06 03:02:43 -04:00
click . confirm (
' Replace all existing cluster data from coordinators with backup file " {} " ' . format (
filename . name
) ,
prompt_suffix = " ? " ,
abort = True ,
)
2020-11-24 02:39:06 -05:00
except Exception :
exit ( 0 )
cluster_data = json . loads ( filename . read ( ) )
retcode , retmsg = pvc_cluster . restore ( config , cluster_data )
cleanup ( retcode , retmsg )
2019-10-22 11:23:12 -04:00
###############################################################################
2020-11-25 10:36:48 -05:00
# pvc task init
2019-10-22 11:23:12 -04:00
###############################################################################
2021-11-06 03:02:43 -04:00
@click.command ( name = " init " , short_help = " Initialize a new cluster. " )
2021-05-30 23:59:17 -04:00
@click.option (
2021-11-06 03:02:43 -04:00
" -o " ,
" --overwrite " ,
" overwrite_flag " ,
is_flag = True ,
default = False ,
help = " Remove and overwrite any existing data " ,
2021-05-30 23:59:17 -04:00
)
2019-06-21 14:16:32 -04:00
@click.option (
2021-11-06 03:02:43 -04:00
" -y " ,
" --yes " ,
" confirm_flag " ,
is_flag = True ,
default = False ,
help = " Confirm the initialization " ,
2019-06-21 14:16:32 -04:00
)
2020-06-05 14:49:53 -04:00
@cluster_req
2021-05-30 23:59:17 -04:00
def task_init ( confirm_flag , overwrite_flag ) :
2018-06-06 01:07:59 -04:00
"""
2019-03-10 20:40:03 -04:00
Perform initialization of a new PVC cluster .
2021-05-30 23:59:17 -04:00
If the ' -o ' / ' --overwrite ' option is specified , all existing data in the cluster will be deleted
before new , empty data is written .
It is not advisable to do this against a running cluster - all node daemons should be stopped
first and the API daemon started manually before running this command .
2018-06-06 01:07:59 -04:00
"""
2021-11-06 03:02:43 -04:00
if not confirm_flag and not config [ " unsafe " ] :
2020-01-08 10:34:27 -05:00
try :
2021-11-06 03:02:43 -04:00
click . confirm (
" Remove all existing cluster data from coordinators and initialize a new cluster " ,
prompt_suffix = " ? " ,
abort = True ,
)
2020-11-06 18:55:10 -05:00
except Exception :
2019-06-21 15:38:32 -04:00
exit ( 0 )
2019-08-20 09:19:56 -04:00
# Easter-egg
2021-11-08 00:04:20 -05:00
echo ( " Some music while we ' re Layin ' Pipe? https://youtu.be/sw8S_Kv89IU " )
2019-08-20 09:19:56 -04:00
2021-05-30 23:59:17 -04:00
retcode , retmsg = pvc_cluster . initialize ( config , overwrite_flag )
2019-12-29 20:33:51 -05:00
cleanup ( retcode , retmsg )
2018-06-05 01:39:59 -04:00
2020-11-07 14:45:24 -05:00
2018-06-06 01:07:59 -04:00
###############################################################################
# pvc
###############################################################################
2018-06-05 01:39:59 -04:00
@click.group ( context_settings = CONTEXT_SETTINGS )
2018-06-06 01:07:59 -04:00
@click.option (
2021-11-06 03:02:43 -04:00
" -c " ,
" --cluster " ,
" _cluster " ,
envvar = " PVC_CLUSTER " ,
default = None ,
help = " Cluster to connect to. " ,
2018-06-06 01:07:59 -04:00
)
2019-12-26 11:20:57 -05:00
@click.option (
2021-11-06 03:02:43 -04:00
" -v " ,
" --debug " ,
" _debug " ,
envvar = " PVC_DEBUG " ,
is_flag = True ,
default = False ,
help = " Additional debug details. " ,
2019-12-26 11:20:57 -05:00
)
2020-06-25 11:09:55 -04:00
@click.option (
2021-11-06 03:02:43 -04:00
" -q " ,
" --quiet " ,
" _quiet " ,
envvar = " PVC_QUIET " ,
is_flag = True ,
default = False ,
help = " Suppress cluster connection information. " ,
2020-06-25 11:09:55 -04:00
)
2021-04-08 12:48:38 -04:00
@click.option (
2021-11-06 03:02:43 -04:00
" -u " ,
" --unsafe " ,
" _unsafe " ,
envvar = " PVC_UNSAFE " ,
is_flag = True ,
default = False ,
help = ' Allow unsafe operations without confirmation/ " --yes " argument. ' ,
2021-04-08 12:48:38 -04:00
)
2021-11-08 00:04:20 -05:00
@click.option (
" --colour " ,
2021-11-08 00:09:59 -05:00
" --color " ,
2021-11-08 00:04:20 -05:00
" _colour " ,
envvar = " PVC_COLOUR " ,
is_flag = True ,
default = False ,
help = " Force colourized output. " ,
)
2021-10-11 15:34:41 -04:00
@click.option (
2021-11-06 03:02:43 -04:00
" --version " , is_flag = True , callback = print_version , expose_value = False , is_eager = True
2021-10-11 15:34:41 -04:00
)
2021-11-08 00:04:20 -05:00
def cli ( _cluster , _debug , _quiet , _unsafe , _colour ) :
2018-06-06 01:07:59 -04:00
"""
Parallel Virtual Cluster CLI management tool
2018-06-20 14:33:40 -04:00
2018-07-18 22:30:23 -04:00
Environment variables :
2019-12-30 13:27:40 -05:00
" PVC_CLUSTER " : Set the cluster to access instead of using - - cluster / - c
2021-04-08 14:27:55 -04:00
2021-04-08 12:48:38 -04:00
" PVC_DEBUG " : Enable additional debugging details instead of using - - debug / - v
2021-04-08 14:27:55 -04:00
2021-04-08 12:48:38 -04:00
" PVC_QUIET " : Suppress stderr connection output from client instead of using - - quiet / - q
2021-04-08 14:27:55 -04:00
2021-11-08 00:07:21 -05:00
" PVC_UNSAFE " : Always suppress confirmations instead of needing - - unsafe / - u or - - yes / - y ; USE WITH EXTREME CARE
2018-10-25 11:54:05 -04:00
2021-11-08 00:07:21 -05:00
" PVC_COLOUR " : Force colour on the output even if Click determines it is not a console ( e . g . with ' watch ' )
2021-11-08 00:04:20 -05:00
2019-12-30 13:27:40 -05:00
If no PVC_CLUSTER / - - cluster is specified , attempts first to load the " local " cluster , checking
2020-02-08 19:16:19 -05:00
for an API configuration in " /etc/pvc/pvcapid.yaml " . If this is also not found , abort .
2018-06-06 01:07:59 -04:00
"""
2019-12-26 11:20:57 -05:00
global config
2019-12-30 13:27:40 -05:00
store_data = get_store ( store_path )
config = get_config ( store_data , _cluster )
2022-01-13 18:36:20 -05:00
# There is only one cluster and no local cluster, so even if nothing was passed, use it
if len ( store_data ) == 1 and _cluster is None and config . get ( " badcfg " , None ) :
config = get_config ( store_data , list ( store_data . keys ( ) ) [ 0 ] )
2021-11-06 03:02:43 -04:00
if not config . get ( " badcfg " , None ) :
config [ " debug " ] = _debug
config [ " unsafe " ] = _unsafe
2021-11-08 00:04:20 -05:00
config [ " colour " ] = _colour
2020-01-06 09:23:35 -05:00
2020-06-25 11:09:55 -04:00
if not _quiet :
2021-11-06 03:02:43 -04:00
if config [ " api_scheme " ] == " https " and not config [ " verify_ssl " ] :
ssl_unverified_msg = " (unverified) "
2020-08-27 13:23:24 -04:00
else :
2021-11-06 03:02:43 -04:00
ssl_unverified_msg = " "
2021-11-08 00:04:20 -05:00
echo (
2020-08-27 13:23:24 -04:00
' Using cluster " {} " - Host: " {} " Scheme: " {} {} " Prefix: " {} " ' . format (
2021-11-06 03:02:43 -04:00
config [ " cluster " ] ,
config [ " api_host " ] ,
config [ " api_scheme " ] ,
2020-08-27 13:23:24 -04:00
ssl_unverified_msg ,
2021-11-06 03:02:43 -04:00
config [ " api_prefix " ] ,
2020-06-25 11:09:55 -04:00
) ,
2021-11-06 03:02:43 -04:00
err = True ,
2020-06-25 11:09:55 -04:00
)
2021-11-08 00:04:20 -05:00
echo ( " " , err = True )
2020-11-07 13:17:49 -05:00
2021-12-10 16:17:33 -05:00
audit ( )
2018-06-05 01:39:59 -04:00
#
# Click command tree
#
2020-01-02 11:18:46 -05:00
cli_cluster . add_command ( cluster_add )
cli_cluster . add_command ( cluster_remove )
cli_cluster . add_command ( cluster_list )
2018-10-14 02:01:35 -04:00
cli_node . add_command ( node_secondary )
cli_node . add_command ( node_primary )
2018-09-20 03:25:58 -04:00
cli_node . add_command ( node_flush )
cli_node . add_command ( node_ready )
cli_node . add_command ( node_unflush )
2021-07-18 17:37:49 -04:00
cli_node . add_command ( node_log )
2018-09-20 03:25:58 -04:00
cli_node . add_command ( node_info )
cli_node . add_command ( node_list )
2021-07-13 19:04:56 -04:00
vm_tags . add_command ( vm_tags_get )
vm_tags . add_command ( vm_tags_add )
vm_tags . add_command ( vm_tags_remove )
2020-11-07 17:35:45 -05:00
vm_vcpu . add_command ( vm_vcpu_get )
vm_vcpu . add_command ( vm_vcpu_set )
2020-11-07 16:02:56 -05:00
2020-11-07 18:01:43 -05:00
vm_memory . add_command ( vm_memory_get )
vm_memory . add_command ( vm_memory_set )
2020-11-07 16:02:56 -05:00
2020-11-07 22:52:12 -05:00
vm_network . add_command ( vm_network_get )
vm_network . add_command ( vm_network_add )
vm_network . add_command ( vm_network_remove )
2020-11-07 16:02:56 -05:00
2020-11-08 00:48:50 -05:00
vm_volume . add_command ( vm_volume_get )
vm_volume . add_command ( vm_volume_add )
vm_volume . add_command ( vm_volume_remove )
2020-11-07 16:02:56 -05:00
2018-09-20 03:25:58 -04:00
cli_vm . add_command ( vm_define )
2019-10-12 01:17:39 -04:00
cli_vm . add_command ( vm_meta )
2018-09-20 03:25:58 -04:00
cli_vm . add_command ( vm_modify )
2021-05-23 16:41:42 -04:00
cli_vm . add_command ( vm_rename )
2018-09-20 03:25:58 -04:00
cli_vm . add_command ( vm_undefine )
2019-06-27 11:19:48 -04:00
cli_vm . add_command ( vm_remove )
2019-03-12 21:09:54 -04:00
cli_vm . add_command ( vm_dump )
2018-09-20 03:25:58 -04:00
cli_vm . add_command ( vm_start )
cli_vm . add_command ( vm_restart )
cli_vm . add_command ( vm_shutdown )
cli_vm . add_command ( vm_stop )
2019-10-23 23:37:42 -04:00
cli_vm . add_command ( vm_disable )
2018-09-20 03:25:58 -04:00
cli_vm . add_command ( vm_move )
cli_vm . add_command ( vm_migrate )
cli_vm . add_command ( vm_unmigrate )
2019-08-07 13:42:01 -04:00
cli_vm . add_command ( vm_flush_locks )
2021-07-13 19:04:56 -04:00
cli_vm . add_command ( vm_tags )
2020-11-07 16:02:56 -05:00
cli_vm . add_command ( vm_vcpu )
cli_vm . add_command ( vm_memory )
cli_vm . add_command ( vm_network )
cli_vm . add_command ( vm_volume )
2018-09-20 03:25:58 -04:00
cli_vm . add_command ( vm_info )
2019-04-11 19:06:06 -04:00
cli_vm . add_command ( vm_log )
2018-09-20 03:25:58 -04:00
cli_vm . add_command ( vm_list )
2018-09-21 23:43:30 -04:00
cli_network . add_command ( net_add )
2018-09-23 15:26:20 -04:00
cli_network . add_command ( net_modify )
2018-09-21 23:43:30 -04:00
cli_network . add_command ( net_remove )
cli_network . add_command ( net_info )
cli_network . add_command ( net_list )
2018-09-28 20:31:56 -04:00
cli_network . add_command ( net_dhcp )
cli_network . add_command ( net_acl )
2021-06-21 17:12:53 -04:00
cli_network . add_command ( net_sriov )
2018-09-28 20:31:56 -04:00
net_dhcp . add_command ( net_dhcp_list )
2019-12-29 16:13:32 -05:00
net_dhcp . add_command ( net_dhcp_add )
net_dhcp . add_command ( net_dhcp_remove )
2018-09-21 23:43:30 -04:00
2018-10-17 00:23:27 -04:00
net_acl . add_command ( net_acl_add )
net_acl . add_command ( net_acl_remove )
net_acl . add_command ( net_acl_list )
2021-06-21 17:12:53 -04:00
net_sriov . add_command ( net_sriov_pf )
net_sriov . add_command ( net_sriov_vf )
net_sriov_pf . add_command ( net_sriov_pf_list )
net_sriov_vf . add_command ( net_sriov_vf_list )
net_sriov_vf . add_command ( net_sriov_vf_info )
net_sriov_vf . add_command ( net_sriov_vf_set )
2020-08-24 14:57:52 -04:00
ceph_benchmark . add_command ( ceph_benchmark_run )
2020-08-25 12:16:23 -04:00
ceph_benchmark . add_command ( ceph_benchmark_info )
2020-08-24 14:57:52 -04:00
ceph_benchmark . add_command ( ceph_benchmark_list )
2021-09-23 13:59:49 -04:00
ceph_osd . add_command ( ceph_osd_create_db_vg )
2018-10-28 22:15:25 -04:00
ceph_osd . add_command ( ceph_osd_add )
2022-05-06 15:31:58 -04:00
ceph_osd . add_command ( ceph_osd_replace )
ceph_osd . add_command ( ceph_osd_refresh )
2018-10-29 17:51:08 -04:00
ceph_osd . add_command ( ceph_osd_remove )
2018-11-01 22:00:59 -04:00
ceph_osd . add_command ( ceph_osd_in )
ceph_osd . add_command ( ceph_osd_out )
ceph_osd . add_command ( ceph_osd_set )
ceph_osd . add_command ( ceph_osd_unset )
2018-10-30 09:17:32 -04:00
ceph_osd . add_command ( ceph_osd_list )
2018-10-27 18:11:58 -04:00
2018-10-31 23:38:17 -04:00
ceph_pool . add_command ( ceph_pool_add )
ceph_pool . add_command ( ceph_pool_remove )
2021-12-28 21:41:41 -05:00
ceph_pool . add_command ( ceph_pool_set_pgs )
2018-10-31 23:38:17 -04:00
ceph_pool . add_command ( ceph_pool_list )
2018-10-27 18:11:58 -04:00
2019-06-19 00:12:44 -04:00
ceph_volume . add_command ( ceph_volume_add )
2020-02-09 20:42:56 -05:00
ceph_volume . add_command ( ceph_volume_upload )
2019-07-26 14:24:22 -04:00
ceph_volume . add_command ( ceph_volume_resize )
ceph_volume . add_command ( ceph_volume_rename )
2019-12-29 20:33:51 -05:00
ceph_volume . add_command ( ceph_volume_clone )
2019-06-19 00:12:44 -04:00
ceph_volume . add_command ( ceph_volume_remove )
ceph_volume . add_command ( ceph_volume_list )
ceph_volume . add_command ( ceph_volume_snapshot )
ceph_volume_snapshot . add_command ( ceph_volume_snapshot_add )
2019-07-28 23:00:35 -04:00
ceph_volume_snapshot . add_command ( ceph_volume_snapshot_rename )
2019-06-19 00:12:44 -04:00
ceph_volume_snapshot . add_command ( ceph_volume_snapshot_remove )
ceph_volume_snapshot . add_command ( ceph_volume_snapshot_list )
2020-01-11 16:02:53 -05:00
cli_storage . add_command ( ceph_status )
cli_storage . add_command ( ceph_util )
2020-08-24 14:57:52 -04:00
cli_storage . add_command ( ceph_benchmark )
2020-01-11 16:02:53 -05:00
cli_storage . add_command ( ceph_osd )
cli_storage . add_command ( ceph_pool )
cli_storage . add_command ( ceph_volume )
2019-07-10 15:14:17 -04:00
2020-01-04 11:58:30 -05:00
provisioner_template_system . add_command ( provisioner_template_system_list )
provisioner_template_system . add_command ( provisioner_template_system_add )
2020-02-18 16:18:27 -05:00
provisioner_template_system . add_command ( provisioner_template_system_modify )
2020-01-04 11:58:30 -05:00
provisioner_template_system . add_command ( provisioner_template_system_remove )
provisioner_template_network . add_command ( provisioner_template_network_list )
provisioner_template_network . add_command ( provisioner_template_network_add )
provisioner_template_network . add_command ( provisioner_template_network_remove )
provisioner_template_network . add_command ( provisioner_template_network_vni )
provisioner_template_network_vni . add_command ( provisioner_template_network_vni_add )
provisioner_template_network_vni . add_command ( provisioner_template_network_vni_remove )
provisioner_template_storage . add_command ( provisioner_template_storage_list )
provisioner_template_storage . add_command ( provisioner_template_storage_add )
provisioner_template_storage . add_command ( provisioner_template_storage_remove )
provisioner_template_storage . add_command ( provisioner_template_storage_disk )
provisioner_template_storage_disk . add_command ( provisioner_template_storage_disk_add )
provisioner_template_storage_disk . add_command ( provisioner_template_storage_disk_remove )
provisioner_template . add_command ( provisioner_template_system )
provisioner_template . add_command ( provisioner_template_network )
provisioner_template . add_command ( provisioner_template_storage )
provisioner_template . add_command ( provisioner_template_list )
2019-12-30 13:27:40 -05:00
2020-01-04 13:04:01 -05:00
provisioner_userdata . add_command ( provisioner_userdata_list )
2020-02-27 14:31:08 -05:00
provisioner_userdata . add_command ( provisioner_userdata_show )
2020-01-04 13:04:01 -05:00
provisioner_userdata . add_command ( provisioner_userdata_add )
provisioner_userdata . add_command ( provisioner_userdata_modify )
provisioner_userdata . add_command ( provisioner_userdata_remove )
provisioner_script . add_command ( provisioner_script_list )
2020-02-27 14:31:08 -05:00
provisioner_script . add_command ( provisioner_script_show )
2020-01-04 13:04:01 -05:00
provisioner_script . add_command ( provisioner_script_add )
provisioner_script . add_command ( provisioner_script_modify )
provisioner_script . add_command ( provisioner_script_remove )
2020-02-17 22:52:49 -05:00
provisioner_ova . add_command ( provisioner_ova_list )
provisioner_ova . add_command ( provisioner_ova_upload )
provisioner_ova . add_command ( provisioner_ova_remove )
2020-01-04 14:06:36 -05:00
provisioner_profile . add_command ( provisioner_profile_list )
provisioner_profile . add_command ( provisioner_profile_add )
provisioner_profile . add_command ( provisioner_profile_modify )
provisioner_profile . add_command ( provisioner_profile_remove )
2020-01-02 11:18:46 -05:00
cli_provisioner . add_command ( provisioner_template )
2020-01-04 13:04:01 -05:00
cli_provisioner . add_command ( provisioner_userdata )
cli_provisioner . add_command ( provisioner_script )
2020-02-17 22:52:49 -05:00
cli_provisioner . add_command ( provisioner_ova )
2020-01-04 14:06:36 -05:00
cli_provisioner . add_command ( provisioner_profile )
2020-01-04 14:31:22 -05:00
cli_provisioner . add_command ( provisioner_create )
cli_provisioner . add_command ( provisioner_status )
2020-01-02 11:18:46 -05:00
2020-01-09 10:53:27 -05:00
cli_maintenance . add_command ( maintenance_on )
cli_maintenance . add_command ( maintenance_off )
2020-11-24 02:39:06 -05:00
cli_task . add_command ( task_backup )
cli_task . add_command ( task_restore )
cli_task . add_command ( task_init )
2020-01-02 11:18:46 -05:00
cli . add_command ( cli_cluster )
2018-09-20 03:25:58 -04:00
cli . add_command ( cli_node )
cli . add_command ( cli_vm )
2018-09-21 23:43:30 -04:00
cli . add_command ( cli_network )
2019-07-10 15:14:17 -04:00
cli . add_command ( cli_storage )
2020-01-02 11:18:46 -05:00
cli . add_command ( cli_provisioner )
2020-01-09 10:53:27 -05:00
cli . add_command ( cli_maintenance )
2020-11-24 02:39:06 -05:00
cli . add_command ( cli_task )
2019-10-22 11:23:12 -04:00
cli . add_command ( status_cluster )
2018-06-05 01:39:59 -04:00
2019-12-30 13:27:40 -05:00
2018-06-05 01:39:59 -04:00
#
# Main entry point
#
def main ( ) :
return cli ( obj = { } )
2020-11-07 13:17:49 -05:00
2021-11-06 03:02:43 -04:00
if __name__ == " __main__ " :
2018-06-05 01:39:59 -04:00
main ( )