2018-05-31 20:26:44 -04:00
#!/usr/bin/env python3
2018-06-06 01:47:53 -04:00
# pvcd.py - PVC client command-line interface
# Part of the Parallel Virtual Cluster (PVC) system
#
# Copyright (C) 2018 Joshua M. Boniface <joshua@boniface.me>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# 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 tempfile
import os
import subprocess
import difflib
import re
import colorama
2019-03-12 22:55:29 -04:00
import yaml
2018-06-14 12:07:46 -04:00
2018-09-21 23:43:30 -04:00
import client_lib . common as pvc_common
import client_lib . node as pvc_node
import client_lib . vm as pvc_vm
import client_lib . network as pvc_network
2018-10-27 18:11:58 -04:00
import client_lib . ceph as pvc_ceph
2019-03-17 12:56:52 -04:00
#import client_lib.provisioner as pvc_provisioner
2018-06-05 01:39:59 -04:00
2018-06-14 11:57:36 -04:00
myhostname = socket . gethostname ( )
zk_host = ' '
2018-06-11 01:35:50 -04:00
CONTEXT_SETTINGS = dict ( help_option_names = [ ' -h ' , ' --help ' ] , max_content_width = 120 )
2018-09-20 03:25:58 -04:00
def cleanup ( retcode , retmsg , zk_conn ) :
2018-09-21 23:43:30 -04:00
pvc_common . stopZKConnection ( zk_conn )
2018-09-20 03:25:58 -04:00
if retcode == True :
if retmsg != ' ' :
click . echo ( retmsg )
exit ( 0 )
else :
if retmsg != ' ' :
click . echo ( retmsg )
exit ( 1 )
2018-06-05 01:39:59 -04:00
###############################################################################
# pvc node
###############################################################################
2018-10-14 02:01:35 -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 .
"""
pass
2018-10-14 02:01:35 -04:00
###############################################################################
# pvc node secondary
###############################################################################
@click.command ( name = ' secondary ' , short_help = ' Set a node in secondary node status. ' )
@click.argument (
' node '
)
def node_secondary ( node ) :
"""
Take NODE out of primary router mode .
"""
zk_conn = pvc_common . startZKConnection ( zk_host )
retcode , retmsg = pvc_node . secondary_node ( zk_conn , node )
cleanup ( retcode , retmsg , zk_conn )
###############################################################################
# pvc node primary
###############################################################################
@click.command ( name = ' primary ' , short_help = ' Set a node in primary status. ' )
@click.argument (
' node '
)
def node_primary ( node ) :
"""
Put NODE into primary router mode .
"""
zk_conn = pvc_common . startZKConnection ( zk_host )
retcode , retmsg = pvc_node . primary_node ( zk_conn , node )
cleanup ( retcode , retmsg , zk_conn )
2018-06-05 01:39:59 -04:00
###############################################################################
# pvc node flush
###############################################################################
2018-07-18 22:28:49 -04:00
@click.command ( name = ' flush ' , short_help = ' Take a node out of service. ' )
2018-07-17 01:48:15 -04:00
@click.option (
' -w ' , ' --wait ' , ' wait ' , is_flag = True , default = False ,
help = ' Wait for migrations to complete before returning. '
)
2018-06-16 22:22:07 -04:00
@click.argument (
' node ' , default = myhostname
2018-06-06 20:49:07 -04:00
)
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
"""
2018-09-20 03:25:58 -04:00
2018-09-21 23:43:30 -04:00
zk_conn = pvc_common . startZKConnection ( zk_host )
2018-09-23 01:05:54 -04:00
retcode , retmsg = pvc_node . flush_node ( zk_conn , node , wait )
cleanup ( retcode , retmsg , zk_conn )
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
###############################################################################
2018-07-18 22:28:49 -04:00
@click.command ( name = ' ready ' , short_help = ' Restore node to service. ' )
2018-06-16 22:22:07 -04:00
@click.argument (
' node ' , default = myhostname
2018-06-06 20:49:07 -04:00
)
2018-09-20 03:25:58 -04:00
def node_ready ( node ) :
2018-07-18 22:58:41 -04:00
"""
Restore NODE to active service and migrate back all VMs . If unspecified , defaults to this host .
"""
2018-09-21 23:43:30 -04:00
zk_conn = pvc_common . startZKConnection ( zk_host )
2018-09-23 01:05:54 -04:00
retcode , retmsg = pvc_node . ready_node ( zk_conn , node )
cleanup ( retcode , retmsg , zk_conn )
2018-06-26 23:46:03 -04:00
2018-07-18 22:28:49 -04:00
@click.command ( name = ' unflush ' , short_help = ' Restore node to service. ' )
2018-06-26 23:46:03 -04:00
@click.argument (
' node ' , default = myhostname
)
2018-09-20 03:25:58 -04:00
def node_unflush ( node ) :
2018-07-18 22:58:41 -04:00
"""
Restore NODE to active service and migrate back all VMs . If unspecified , defaults to this host .
"""
2018-09-21 23:43:30 -04:00
zk_conn = pvc_common . startZKConnection ( zk_host )
2018-09-23 01:05:54 -04:00
retcode , retmsg = pvc_node . ready_node ( zk_conn , node )
cleanup ( retcode , retmsg , zk_conn )
2018-06-05 01:39:59 -04:00
2018-06-11 02:49:47 -04:00
###############################################################################
# pvc node info
###############################################################################
2018-07-18 22:28:49 -04:00
@click.command ( name = ' info ' , short_help = ' Show details of a node object. ' )
2018-06-16 22:22:07 -04:00
@click.argument (
' node ' , default = myhostname
2018-06-11 02:49:47 -04:00
)
@click.option (
' -l ' , ' --long ' , ' long_output ' , is_flag = True , default = False ,
help = ' Display more detailed information. '
)
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
"""
2018-09-21 23:43:30 -04:00
zk_conn = pvc_common . startZKConnection ( zk_host )
2018-09-24 15:20:12 -04:00
retcode , retmsg = pvc_node . get_info ( zk_conn , node , long_output )
2018-09-20 03:25:58 -04:00
cleanup ( retcode , retmsg , zk_conn )
2018-06-11 02:49:47 -04:00
###############################################################################
# pvc node list
###############################################################################
2018-07-18 22:28:49 -04:00
@click.command ( name = ' list ' , short_help = ' List all node objects. ' )
2018-07-19 21:58:11 -04:00
@click.argument (
' limit ' , default = None , required = False
)
def node_list ( limit ) :
2018-06-11 02:49:47 -04:00
"""
2018-10-14 02:01:35 -04:00
List all nodes in the cluster ; optionally only match names matching regex LIMIT .
2018-06-11 02:49:47 -04:00
"""
2018-09-21 23:43:30 -04:00
zk_conn = pvc_common . startZKConnection ( zk_host )
retcode , retmsg = pvc_node . get_list ( zk_conn , limit )
2018-09-20 03:25:58 -04:00
cleanup ( retcode , retmsg , zk_conn )
2018-06-11 02:49:47 -04:00
2018-06-05 01:39:59 -04:00
###############################################################################
# pvc vm
###############################################################################
2018-07-18 22:30:23 -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 .
"""
pass
2019-03-10 20:40:03 -04:00
###############################################################################
# pvc vm add
###############################################################################
@click.command ( name = ' add ' , s hort_help = ' Add a new virtual machine to the provisioning queue. ' )
@click.option (
2019-03-12 23:17:31 -04:00
' --target ' , ' target_node ' ,
2019-03-10 20:40:03 -04:00
help = ' Home node for this domain; autodetect if unspecified. '
)
@click.option (
' --cluster ' , ' is_cluster ' ,
is_flag = True ,
help = ' Create a cluster VM. '
)
@click.option (
' --system-template ' , ' system_template ' ,
required = True ,
help = ' System resource template for this domain. '
)
@click.option (
' --network-template ' , ' network_template ' ,
required = True ,
help = ' Network resource template for this domain. '
)
@click.option (
' --storage-template ' , ' storage_template ' ,
required = True ,
help = ' Storage resource template for this domain. '
)
@click.argument (
' vmname '
)
def vm_add ( vmname , target_node , is_cluster , system_template , network_template , storage_template ) :
"""
Add a new VM VMNAME to the provisioning queue .
Note : Cluster VMs are those which will only run on Coordinator hosts . Usually , these VMs will use the ' cluster ' network template , or possibly a custom template including the upstream network as well . Use these sparingly , as they are designed primarily for cluster control or upstream bridge VMs .
"""
zk_conn = pvc_common . startZKConnection ( zk_host )
retcode , retmsg = pvc_provisioner . add_vm (
zk_conn ,
vmname = vmname ,
target_node = target_node ,
is_cluster = is_cluster ,
system_template = system_template ,
network_template = network_template ,
storage_template = storage_template
)
cleanup ( retcode , retmsg , zk_conn )
2018-06-05 01:39:59 -04:00
###############################################################################
# pvc vm define
###############################################################################
@click.command ( name = ' define ' , short_help = ' Define a new virtual machine from a Libvirt XML file. ' )
@click.option (
2019-03-12 23:17:31 -04:00
' -t ' , ' --target ' , ' target_node ' ,
2018-10-14 02:01:35 -04:00
help = ' Home node for this domain; autodetect if unspecified. '
2018-07-18 12:15:39 -04:00
)
@click.option (
2018-07-18 22:22:12 -04:00
' -s ' , ' --selector ' , ' selector ' , default = ' mem ' , show_default = True ,
2018-07-18 12:15:39 -04:00
type = click . Choice ( [ ' mem ' , ' load ' , ' vcpus ' , ' vms ' ] ) ,
2018-10-14 02:01:35 -04:00
help = ' Method to determine optimal target node during autodetect. '
2018-06-05 01:39:59 -04:00
)
2018-06-16 22:22:07 -04:00
@click.argument (
' config ' , type = click . File ( )
)
2018-10-14 02:01:35 -04:00
def vm_define ( config , target_node , selector ) :
2018-06-05 01:39:59 -04:00
"""
2018-06-16 22:22:07 -04:00
Define a new virtual machine from Libvirt XML configuration file CONFIG .
2018-06-05 01:39:59 -04:00
"""
2018-06-06 12:00:52 -04:00
# Open the XML file
2018-09-20 03:25:58 -04:00
config_data = config . read ( )
2018-06-16 22:22:07 -04:00
config . close ( )
2018-06-06 12:00:52 -04:00
2018-09-21 23:43:30 -04:00
zk_conn = pvc_common . startZKConnection ( zk_host )
2018-10-14 02:01:35 -04:00
retcode , retmsg = pvc_vm . define_vm ( zk_conn , config_data , target_node , selector )
2018-09-20 03:25:58 -04:00
cleanup ( retcode , retmsg , zk_conn )
2018-06-06 12:00:52 -04:00
2018-07-20 00:38:31 -04:00
###############################################################################
# pvc vm modify
###############################################################################
@click.command ( name = ' modify ' , short_help = ' Modify an existing VM configuration. ' )
@click.option (
' -e ' , ' --editor ' , ' editor ' , is_flag = True ,
help = ' Use local editor to modify existing config. '
)
@click.option (
' -r ' , ' --restart ' , ' restart ' , is_flag = True ,
help = ' Immediately restart VM to apply new config. '
)
@click.argument (
' domain '
)
@click.argument (
' config ' , type = click . File ( ) , default = None , required = False
)
2018-09-20 03:25:58 -04:00
def vm_modify ( domain , config , editor , restart ) :
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 .
"""
if editor == False and config == None :
2018-09-20 03:25:58 -04:00
cleanup ( False , ' Either an XML config file or the " --editor " option must be specified. ' )
2018-07-20 00:38:31 -04:00
2018-09-21 23:43:30 -04:00
zk_conn = pvc_common . startZKConnection ( zk_host )
2018-07-20 00:38:31 -04:00
if editor == True :
2018-09-21 23:43:30 -04:00
dom_uuid = pvc_vm . getDomainUUID ( zk_conn , domain )
2018-09-20 03:25:58 -04:00
if dom_uuid == None :
cleanup ( False , ' ERROR: Could not find VM " {} " in the cluster! ' . format ( domain ) )
2018-09-25 02:32:08 -04:00
dom_name = pvc_vm . getDomainName ( zk_conn , dom_uuid )
2018-09-20 03:25:58 -04:00
2018-07-20 00:38:31 -04:00
# Grab the current config
current_vm_config = zk_conn . get ( ' /domains/ {} /xml ' . format ( dom_uuid ) ) [ 0 ] . decode ( ' ascii ' )
# Write it to a tempfile
fd , path = tempfile . mkstemp ( )
fw = os . fdopen ( fd , ' w ' )
fw . write ( current_vm_config )
fw . close ( )
# Edit it
editor = os . getenv ( ' EDITOR ' , ' vi ' )
subprocess . call ( ' %s %s ' % ( editor , path ) , shell = True )
# Open the tempfile to read
with open ( path , ' r ' ) as fr :
new_vm_config = fr . read ( )
fr . close ( )
# Delete the tempfile
os . unlink ( path )
# Show a diff and confirm
diff = list ( difflib . unified_diff ( current_vm_config . split ( ' \n ' ) , new_vm_config . split ( ' \n ' ) , fromfile = ' current ' , tofile = ' modified ' , fromfiledate = ' ' , tofiledate = ' ' , n = 3 , lineterm = ' ' ) )
if len ( diff ) < 1 :
click . echo ( ' Aborting with no modifications. ' )
exit ( 0 )
click . echo ( ' Pending modifications: ' )
click . echo ( ' ' )
for line in diff :
if re . match ( ' ^ \ + ' , line ) != None :
click . echo ( colorama . Fore . GREEN + line + colorama . Fore . RESET )
elif re . match ( ' ^ \ - ' , line ) != None :
click . echo ( colorama . Fore . RED + line + colorama . Fore . RESET )
elif re . match ( ' ^ \ ^ ' , line ) != None :
click . echo ( colorama . Fore . BLUE + line + colorama . Fore . RESET )
else :
click . echo ( line )
click . echo ( ' ' )
click . confirm ( ' Write modifications to Zookeeper? ' , abort = True )
2018-09-25 02:36:37 -04:00
if restart :
click . echo ( ' Writing modified config of VM " {} " and restarting. ' . format ( dom_name ) )
else :
click . echo ( ' Writing modified config of VM " {} " . ' . format ( dom_name ) )
2018-07-20 00:38:31 -04:00
# We're operating in replace mode
else :
# Open the XML file
new_vm_config = config . read ( )
config . close ( )
2018-09-25 02:36:37 -04:00
if restart :
click . echo ( ' Replacing config of VM " {} " with file " {} " and restarting. ' . format ( dom_name , config ) )
else :
click . echo ( ' Replacing config of VM " {} " with file " {} " . ' . format ( dom_name , config ) )
2018-07-20 00:38:31 -04:00
2018-09-25 02:32:08 -04:00
retcode , retmsg = pvc_vm . modify_vm ( zk_conn , domain , restart , new_vm_config )
2018-09-20 03:25:58 -04:00
cleanup ( retcode , retmsg , zk_conn )
2018-07-20 00:38:31 -04:00
2018-06-06 12:00:52 -04:00
###############################################################################
# pvc vm undefine
###############################################################################
@click.command ( name = ' undefine ' , short_help = ' Undefine and stop a virtual machine. ' )
2018-06-16 22:22:07 -04:00
@click.argument (
' domain '
2018-06-06 12:00:52 -04:00
)
2018-09-20 03:25:58 -04:00
def vm_undefine ( domain ) :
2018-06-06 12:00:52 -04:00
"""
2018-06-16 22:22:07 -04:00
Stop virtual machine DOMAIN and remove it from the cluster database . DOMAIN may be a UUID or name .
2018-06-06 12:00:52 -04:00
"""
2018-06-06 12:28:15 -04:00
# Ensure at least one search method is set
2018-06-16 22:22:07 -04:00
if domain == None :
click . echo ( " ERROR: You must specify either a name or UUID value. " )
2018-08-29 21:31:47 -04:00
exit ( 1 )
2018-06-06 12:28:15 -04:00
2018-06-06 12:00:52 -04:00
# Open a Zookeeper connection
2018-09-21 23:43:30 -04:00
zk_conn = pvc_common . startZKConnection ( zk_host )
retcode , retmsg = pvc_vm . undefine_vm ( zk_conn , domain )
2018-09-20 03:25:58 -04:00
cleanup ( retcode , retmsg , zk_conn )
2018-06-05 01:39:59 -04:00
2019-03-12 21:09:54 -04:00
###############################################################################
# pvc vm dump
###############################################################################
@click.command ( name = ' dump ' , short_help = ' Dump a virtual machine XML to stdout. ' )
@click.argument (
' domain '
)
def vm_dump ( domain ) :
"""
Dump the Libvirt XML definition of virtual machine DOMAIN to stdout . DOMAIN may be a UUID or name .
"""
# Ensure at least one search method is set
if domain == None :
click . echo ( " ERROR: You must specify either a name or UUID value. " )
exit ( 1 )
# Open a Zookeeper connection
zk_conn = pvc_common . startZKConnection ( zk_host )
retcode , retmsg = pvc_vm . dump_vm ( zk_conn , domain )
cleanup ( retcode , retmsg , zk_conn )
2018-06-05 01:39:59 -04:00
###############################################################################
# pvc vm start
###############################################################################
@click.command ( name = ' start ' , short_help = ' Start up a defined virtual machine. ' )
2018-06-16 22:22:07 -04:00
@click.argument (
' domain '
2018-06-05 01:39:59 -04:00
)
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
"""
# Open a Zookeeper connection
2018-09-21 23:43:30 -04:00
zk_conn = pvc_common . startZKConnection ( zk_host )
retcode , retmsg = pvc_vm . start_vm ( zk_conn , domain )
2018-09-20 03:25:58 -04:00
cleanup ( retcode , retmsg , zk_conn )
2018-06-05 01:39:59 -04:00
2018-06-13 12:49:51 -04:00
###############################################################################
# pvc vm restart
###############################################################################
2018-06-17 02:24:06 -04:00
@click.command ( name = ' restart ' , short_help = ' Restart a running virtual machine. ' )
2018-06-16 22:22:07 -04:00
@click.argument (
' domain '
2018-06-13 12:49:51 -04:00
)
2018-09-20 03:25:58 -04:00
def vm_restart ( domain ) :
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
"""
# Open a Zookeeper connection
2018-09-21 23:43:30 -04:00
zk_conn = pvc_common . startZKConnection ( zk_host )
retcode , retmsg = pvc_vm . restart_vm ( zk_conn , domain )
2018-09-20 03:25:58 -04:00
cleanup ( retcode , retmsg , zk_conn )
2018-06-13 12:49:51 -04:00
2018-06-05 01:39:59 -04:00
###############################################################################
# pvc vm shutdown
###############################################################################
@click.command ( name = ' shutdown ' , short_help = ' Gracefully shut down a running virtual machine. ' )
2018-06-16 22:22:07 -04:00
@click.argument (
' domain '
2018-06-05 01:39:59 -04:00
)
2018-09-20 03:25:58 -04:00
def vm_shutdown ( domain ) :
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
"""
# Open a Zookeeper connection
2018-09-21 23:43:30 -04:00
zk_conn = pvc_common . startZKConnection ( zk_host )
retcode , retmsg = pvc_vm . shutdown_vm ( zk_conn , domain )
2018-09-20 03:25:58 -04:00
cleanup ( retcode , retmsg , zk_conn )
2018-06-05 01:39:59 -04:00
###############################################################################
# pvc vm stop
###############################################################################
@click.command ( name = ' stop ' , short_help = ' Forcibly halt a running virtual machine. ' )
2018-06-16 22:22:07 -04:00
@click.argument (
' domain '
2018-06-05 01:39:59 -04:00
)
2018-09-20 03:25:58 -04:00
def vm_stop ( domain ) :
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
"""
# Open a Zookeeper connection
2018-09-21 23:43:30 -04:00
zk_conn = pvc_common . startZKConnection ( zk_host )
retcode , retmsg = pvc_vm . stop_vm ( zk_conn , domain )
2018-09-20 03:25:58 -04:00
cleanup ( retcode , retmsg , zk_conn )
2018-06-05 01:39:59 -04:00
2018-06-10 21:03:41 -04:00
###############################################################################
# pvc vm move
###############################################################################
@click.command ( name = ' move ' , short_help = ' Permanently move a virtual machine to another node. ' )
2018-06-16 22:22:07 -04:00
@click.argument (
' domain '
2018-06-10 21:03:41 -04:00
)
@click.option (
2019-03-12 23:17:31 -04:00
' -t ' , ' --target ' , ' target_node ' , default = None ,
2018-10-14 02:01:35 -04:00
help = ' Target node to migrate to; autodetect if unspecified. '
2018-06-10 21:03:41 -04:00
)
2018-07-18 12:15:39 -04:00
@click.option (
2018-07-18 22:22:12 -04:00
' -s ' , ' --selector ' , ' selector ' , default = ' mem ' , show_default = True ,
2018-07-18 12:15:39 -04:00
type = click . Choice ( [ ' mem ' , ' load ' , ' vcpus ' , ' vms ' ] ) ,
2018-10-14 02:01:35 -04:00
help = ' Method to determine optimal target node during autodetect. '
2018-07-18 12:15:39 -04:00
)
2018-10-14 02:01:35 -04:00
def vm_move ( domain , target_node , selector ) :
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
"""
# Open a Zookeeper connection
2018-09-21 23:43:30 -04:00
zk_conn = pvc_common . startZKConnection ( zk_host )
2018-10-14 02:01:35 -04:00
retcode , retmsg = pvc_vm . move_vm ( zk_conn , domain , target_node , selector )
2018-09-20 03:25:58 -04:00
cleanup ( retcode , retmsg , zk_conn )
2018-06-10 21:03:41 -04:00
2018-06-05 22:06:08 -04:00
###############################################################################
# pvc vm migrate
###############################################################################
2018-06-22 12:24:53 -04:00
@click.command ( name = ' migrate ' , short_help = ' Temporarily migrate a virtual machine to another node. ' )
2018-06-16 22:22:07 -04:00
@click.argument (
' domain '
2018-06-05 22:06:08 -04:00
)
@click.option (
2019-03-12 23:17:31 -04:00
' -t ' , ' --target ' , ' target_node ' , default = None ,
2018-10-14 02:01:35 -04:00
help = ' Target node to migrate to; autodetect if unspecified. '
2018-06-05 22:06:08 -04:00
)
2018-07-18 12:15:39 -04:00
@click.option (
2018-07-18 22:22:12 -04:00
' -s ' , ' --selector ' , ' selector ' , default = ' mem ' , show_default = True ,
2018-07-18 12:15:39 -04:00
type = click . Choice ( [ ' mem ' , ' load ' , ' vcpus ' , ' vms ' ] ) ,
2018-10-14 02:01:35 -04:00
help = ' Method to determine optimal target node during autodetect. '
2018-07-18 12:15:39 -04:00
)
2018-06-05 22:06:08 -04:00
@click.option (
' -f ' , ' --force ' , ' force_migrate ' , is_flag = True , default = False ,
help = ' Force migrate an already migrated VM. '
)
2018-10-14 02:01:35 -04:00
def vm_migrate ( domain , target_node , selector , force_migrate ) :
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
"""
2018-06-05 22:06:08 -04:00
# Open a Zookeeper connection
2018-09-21 23:43:30 -04:00
zk_conn = pvc_common . startZKConnection ( zk_host )
2018-10-14 02:01:35 -04:00
retcode , retmsg = pvc_vm . migrate_vm ( zk_conn , domain , target_node , selector , force_migrate )
2018-09-20 03:25:58 -04:00
cleanup ( retcode , retmsg , zk_conn )
2018-06-05 22:06:08 -04:00
###############################################################################
# pvc vm unmigrate
###############################################################################
2018-06-05 01:39:59 -04:00
@click.command ( name = ' unmigrate ' , short_help = ' Restore a migrated virtual machine to its original node. ' )
2018-06-16 22:22:07 -04:00
@click.argument (
' domain '
2018-06-05 22:06:08 -04:00
)
2018-09-20 03:25:58 -04:00
def vm_unmigrate ( domain ) :
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
"""
2018-06-05 22:06:08 -04:00
# Open a Zookeeper connection
2018-09-21 23:43:30 -04:00
zk_conn = pvc_common . startZKConnection ( zk_host )
retcode , retmsg = pvc_vm . unmigrate_vm ( zk_conn , domain )
2018-09-20 03:25:58 -04:00
cleanup ( retcode , retmsg , zk_conn )
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
###############################################################################
2018-07-18 22:28:49 -04:00
@click.command ( name = ' info ' , short_help = ' Show details of a VM object. ' )
2018-06-16 22:22:07 -04:00
@click.argument (
' domain '
2018-06-05 01:39:59 -04:00
)
2018-06-05 18:45:54 -04:00
@click.option (
' -l ' , ' --long ' , ' long_output ' , is_flag = True , default = False ,
help = ' Display more detailed information. '
)
2018-06-16 22:22:07 -04:00
def vm_info ( domain , long_output ) :
2018-06-05 01:39:59 -04:00
"""
2018-06-16 22:22:07 -04: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
2018-06-16 22:22:07 -04:00
# Open a Zookeeper connection
2018-09-21 23:43:30 -04:00
zk_conn = pvc_common . startZKConnection ( zk_host )
retcode , retmsg = pvc_vm . get_info ( zk_conn , domain , long_output )
2018-09-20 03:25:58 -04:00
cleanup ( retcode , retmsg , zk_conn )
2018-06-05 01:39:59 -04: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
###############################################################################
2018-07-18 22:28:49 -04:00
@click.command ( name = ' list ' , short_help = ' List all VM objects. ' )
2018-07-19 21:58:11 -04:00
@click.argument (
' limit ' , default = None , required = False
)
2018-06-11 01:24:14 -04:00
@click.option (
2019-03-12 23:17:31 -04:00
' -t ' , ' --target ' , ' target_node ' , default = None ,
help = ' Limit list to specified node. '
2018-06-11 01:24:14 -04:00
)
2019-03-12 21:30:01 -04:00
@click.option (
' -r ' , ' --raw ' , ' raw ' , is_flag = True , default = False ,
help = ' Display the raw list of VM names. '
)
2019-03-12 23:17:31 -04:00
def vm_list ( target_node , limit , raw ) :
2018-07-18 22:58:41 -04:00
"""
2018-07-19 21:58:11 -04:00
List all virtual machines in the cluster ; optionally only match names 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
"""
2018-09-21 23:43:30 -04:00
zk_conn = pvc_common . startZKConnection ( zk_host )
2019-03-12 23:17:31 -04:00
retcode , retmsg = pvc_vm . get_list ( zk_conn , target_node , limit , raw )
2018-09-20 03:25:58 -04:00
cleanup ( retcode , retmsg , zk_conn )
2018-06-10 20:21:00 -04:00
2018-09-21 23:43:30 -04:00
###############################################################################
# pvc network
###############################################################################
@click.group ( name = ' network ' , short_help = ' Manage a PVC virtual network. ' , context_settings = CONTEXT_SETTINGS )
def cli_network ( ) :
"""
Manage the state of a VXLAN network in the PVC cluster .
"""
pass
###############################################################################
# pvc network add
###############################################################################
@click.command ( name = ' add ' , short_help = ' Add a new virtual network to the cluster. ' )
@click.option (
' -d ' , ' --description ' , ' description ' ,
2018-10-17 00:23:27 -04:00
required = True ,
2018-11-13 01:22:15 -05:00
help = ' Description of the network; must be unique and not contain whitespace. '
2018-09-28 20:42:24 -04:00
)
@click.option (
2019-03-15 11:28:49 -04:00
' -p ' , ' --type ' , ' nettype ' ,
2018-09-28 20:42:24 -04:00
required = True ,
2019-03-15 11:28:49 -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. '
)
@click.option (
' -n ' , ' --domain ' , ' domain ' ,
default = None ,
2018-09-28 20:42:24 -04:00
help = ' Domain name of the network. '
2018-09-21 23:43:30 -04:00
)
@click.option (
' -i ' , ' --ipnet ' , ' ip_network ' ,
2018-11-13 01:22:15 -05:00
default = None ,
help = ' CIDR-format IPv4 network address for subnet. '
)
@click.option (
' -i6 ' , ' --ipnet6 ' , ' ip6_network ' ,
default = None ,
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 (
' -g ' , ' --gateway ' , ' ip_gateway ' ,
2018-11-13 01:22:15 -05:00
default = None ,
help = ' Default IPv4 gateway address for subnet. '
)
@click.option (
' -g6 ' , ' --gateway6 ' , ' ip6_gateway ' ,
default = None ,
help = ' Default IPv6 gateway address for subnet. [default: " X::1 " ] '
2018-09-21 23:43:30 -04:00
)
@click.option (
2018-09-23 15:26:20 -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 ,
2018-11-13 01:22:15 -05: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 (
' --dhcp-start ' , ' dhcp_start ' ,
default = None ,
2018-11-13 01:22:15 -05:00
help = ' IPv4 DHCP range start address. '
2018-09-29 02:54:48 -04:00
)
@click.option (
' --dhcp-end ' , ' dhcp_end ' ,
default = None ,
2018-11-13 01:22:15 -05:00
help = ' IPv4 DHCP range end address. '
2018-09-29 02:54:48 -04:00
)
2018-09-21 23:43:30 -04:00
@click.argument (
' vni '
)
2019-03-15 11:28:49 -04:00
def net_add ( vni , description , nettype , domain , ip_network , ip_gateway , ip6_network , ip6_gateway , dhcp_flag , dhcp_start , dhcp_end ) :
2018-09-21 23:43:30 -04:00
"""
Add a new virtual network with VXLAN identifier VNI to the cluster .
2019-03-15 11:28:49 -04:00
Examples :
pvc network add 101 - - type bridged
> Creates vLAN 101 and a simple bridge on the VNI dev interface .
pvc network add 1001 - - type managed - - domain test . local - - ipnet 10.1 .1 .0 / 24 - - gateway 10.1 .1 .1
> 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
"""
2019-03-15 11:28:49 -04:00
if nettype == ' managed ' and not ip_network and not ip6_network :
2018-11-13 01:22:15 -05:00
click . echo ( ' Error: At least one of " -i " / " --ipnet " or " -i6 " / " --ipnet6 " must be specified. ' )
2019-03-15 11:28:49 -04:00
exit ( 1 )
2018-11-13 01:22:15 -05:00
2018-09-21 23:43:30 -04:00
zk_conn = pvc_common . startZKConnection ( zk_host )
2019-03-15 11:28:49 -04:00
retcode , retmsg = pvc_network . add_network ( zk_conn , vni , description , nettype , domain , ip_network , ip_gateway , ip6_network , ip6_gateway , dhcp_flag , dhcp_start , dhcp_end )
2018-09-21 23:43:30 -04:00
cleanup ( retcode , retmsg , zk_conn )
2018-09-23 15:26:20 -04:00
###############################################################################
# pvc network modify
###############################################################################
@click.command ( name = ' modify ' , short_help = ' Modify an existing virtual network. ' )
@click.option (
' -d ' , ' --description ' , ' description ' ,
default = None ,
2018-10-17 00:23:27 -04:00
help = ' Description of the network; must be unique and not contain whitespace. '
2018-09-23 15:26:20 -04:00
)
2018-10-03 20:22:42 -04:00
@click.option (
' -n ' , ' --domain ' , ' domain ' ,
default = None ,
help = ' Domain name of the network. '
)
2018-09-23 15:26:20 -04:00
@click.option (
2018-11-14 00:19:43 -05:00
' -i ' , ' --ipnet ' , ' ip4_network ' ,
2018-09-23 15:26:20 -04:00
default = None ,
2018-11-13 01:22:15 -05:00
help = ' CIDR-format IPv4 network address for subnet. '
)
@click.option (
' -i6 ' , ' --ipnet6 ' , ' ip6_network ' ,
default = None ,
help = ' CIDR-format IPv6 network address for subnet. '
2018-09-23 15:26:20 -04:00
)
@click.option (
2018-11-14 00:19:43 -05:00
' -g ' , ' --gateway ' , ' ip4_gateway ' ,
2018-09-23 15:26:20 -04:00
default = None ,
2018-11-13 01:22:15 -05:00
help = ' Default IPv4 gateway address for subnet. '
)
@click.option (
' -g6 ' , ' --gateway6 ' , ' ip6_gateway ' ,
default = None ,
help = ' Default IPv6 gateway address for subnet. '
2018-09-23 15:26:20 -04:00
)
@click.option (
' --dhcp/--no-dhcp ' , ' dhcp_flag ' ,
is_flag = True ,
2018-10-17 00:23:27 -04:00
default = None ,
2018-09-23 15:26:20 -04:00
help = ' Enable/disable DHCP for clients on subnet. '
)
2018-10-03 20:22:42 -04:00
@click.option (
' --dhcp-start ' , ' dhcp_start ' ,
default = None ,
help = ' DHCP range start address. '
)
@click.option (
' --dhcp-end ' , ' dhcp_end ' ,
default = None ,
help = ' DHCP range end address. '
)
2018-09-23 15:26:20 -04:00
@click.argument (
' vni '
)
2018-11-14 00:19:43 -05:00
def net_modify ( vni , description , domain , 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 .
Example :
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
"""
zk_conn = pvc_common . startZKConnection ( zk_host )
2018-11-14 00:19:43 -05:00
retcode , retmsg = pvc_network . modify_network ( zk_conn , vni , description = description , domain = domain , ip6_network = ip6_network , ip6_gateway = ip6_gateway , ip4_network = ip4_network , ip4_gateway = ip4_gateway , dhcp_flag = dhcp_flag , dhcp_start = dhcp_start , dhcp_end = dhcp_end )
2018-09-23 15:26:20 -04:00
cleanup ( retcode , retmsg , zk_conn )
2018-09-21 23:43:30 -04:00
###############################################################################
# pvc network remove
###############################################################################
@click.command ( name = ' remove ' , short_help = ' Remove a virtual network from the cluster. ' )
@click.argument (
' net '
)
def net_remove ( net ) :
"""
Remove an existing virtual network NET from the cluster ; NET can be either a VNI or description .
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 .
"""
zk_conn = pvc_common . startZKConnection ( zk_host )
retcode , retmsg = pvc_network . remove_network ( zk_conn , net )
cleanup ( retcode , retmsg , zk_conn )
###############################################################################
# pvc network info
###############################################################################
@click.command ( name = ' info ' , short_help = ' Show details of a network. ' )
@click.argument (
' vni '
)
2018-09-25 01:32:03 -04:00
@click.option (
' -l ' , ' --long ' , ' long_output ' , is_flag = True , default = False ,
help = ' Display more detailed information. '
)
def net_info ( vni , long_output ) :
2018-09-21 23:43:30 -04:00
"""
Show information about virtual network VNI .
"""
# Open a Zookeeper connection
zk_conn = pvc_common . startZKConnection ( zk_host )
2018-09-25 01:32:03 -04:00
retcode , retmsg = pvc_network . get_info ( zk_conn , vni , long_output )
2018-09-21 23:43:30 -04:00
cleanup ( retcode , retmsg , zk_conn )
###############################################################################
# pvc network list
###############################################################################
@click.command ( name = ' list ' , short_help = ' List all VM objects. ' )
@click.argument (
' limit ' , default = None , required = False
)
def net_list ( limit ) :
"""
List all virtual networks in the cluster ; optionally only match VNIs or Descriptions matching regex LIMIT .
"""
zk_conn = pvc_common . startZKConnection ( zk_host )
2018-09-23 15:26:20 -04:00
retcode , retmsg = pvc_network . get_list ( zk_conn , limit )
2018-09-21 23:43:30 -04:00
cleanup ( retcode , retmsg , zk_conn )
2018-09-28 20:31:56 -04:00
###############################################################################
# pvc network dhcp
###############################################################################
2018-11-13 01:22:15 -05: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
"""
pass
2018-10-03 19:23:46 -04:00
###############################################################################
# pvc network dhcp list
###############################################################################
@click.command ( name = ' list ' , short_help = ' List active DHCP leases. ' )
@click.argument (
' net '
)
@click.argument (
' limit ' , default = None , required = False
)
def net_dhcp_list ( net , limit ) :
"""
List all DHCP leases in virtual network NET ; optionally only match elements matching regex LIMIT ; NET can be either a VNI or description .
"""
zk_conn = pvc_common . startZKConnection ( zk_host )
retcode , retmsg = pvc_network . get_list_dhcp ( zk_conn , net , limit , only_static = False )
cleanup ( retcode , retmsg , zk_conn )
2018-09-28 20:31:56 -04:00
###############################################################################
2018-10-03 19:23:46 -04:00
# pvc network dhcp static
###############################################################################
@click.group ( name = ' static ' , short_help = ' Manage DHCP static reservations in a PVC virtual network. ' , context_settings = CONTEXT_SETTINGS )
def net_dhcp_static ( ) :
"""
Manage host DHCP static reservations of a VXLAN network in the PVC cluster .
"""
pass
2018-09-28 20:31:56 -04:00
###############################################################################
2018-10-03 19:23:46 -04:00
# pvc network dhcp static add
###############################################################################
@click.command ( name = ' add ' , short_help = ' Add a DHCP static reservation. ' )
2018-09-28 20:31:56 -04:00
@click.argument (
' net '
)
@click.argument (
' ipaddr '
)
@click.argument (
2018-10-02 00:08:45 -04:00
' hostname '
2018-09-28 20:31:56 -04:00
)
2018-09-30 12:43:56 -04:00
@click.argument (
2018-10-02 00:08:45 -04:00
' macaddr '
2018-09-30 12:43:56 -04:00
)
2018-10-03 19:23:46 -04:00
def net_dhcp_static_add ( net , ipaddr , macaddr , hostname ) :
2018-09-28 20:31:56 -04:00
"""
2018-10-03 19:23:46 -04:00
Add a new DHCP static reservation of IP address IPADDR with hostname HOSTNAME for MAC address MACADDR to virtual network NET ; NET can be either a VNI or description .
2018-09-28 20:31:56 -04:00
"""
zk_conn = pvc_common . startZKConnection ( zk_host )
2018-09-30 12:43:56 -04:00
retcode , retmsg = pvc_network . add_dhcp_reservation ( zk_conn , net , ipaddr , macaddr , hostname )
2018-09-28 20:31:56 -04:00
cleanup ( retcode , retmsg , zk_conn )
###############################################################################
2018-10-03 19:23:46 -04:00
# pvc network dhcp static remove
2018-09-28 20:31:56 -04:00
###############################################################################
2018-10-03 19:23:46 -04:00
@click.command ( name = ' remove ' , short_help = ' Remove a DHCP static reservation. ' )
2018-09-28 20:31:56 -04:00
@click.argument (
' net '
)
@click.argument (
2018-10-03 19:23:46 -04:00
' reservation '
2018-09-28 20:31:56 -04:00
)
2018-10-03 19:23:46 -04:00
def net_dhcp_static_remove ( net , reservation ) :
2018-09-28 20:31:56 -04:00
"""
2018-10-03 19:23:46 -04:00
Remove a DHCP static reservation RESERVATION from virtual network NET ; RESERVATION can be either a MAC address , an IP address , or a hostname ; NET can be either a VNI or description .
2018-09-28 20:31:56 -04:00
"""
zk_conn = pvc_common . startZKConnection ( zk_host )
2018-10-03 19:23:46 -04:00
retcode , retmsg = pvc_network . remove_dhcp_reservation ( zk_conn , net , reservation )
2018-09-28 20:31:56 -04:00
cleanup ( retcode , retmsg , zk_conn )
###############################################################################
2018-10-03 19:23:46 -04:00
# pvc network dhcp static list
2018-09-28 20:31:56 -04:00
###############################################################################
2018-10-03 19:23:46 -04:00
@click.command ( name = ' list ' , short_help = ' List DHCP static reservations. ' )
2018-09-28 20:31:56 -04:00
@click.argument (
' net '
)
@click.argument (
' limit ' , default = None , required = False
)
2018-10-03 19:23:46 -04:00
def net_dhcp_static_list ( net , limit ) :
2018-09-28 20:31:56 -04:00
"""
2018-10-03 19:23:46 -04:00
List all DHCP static reservations in virtual network NET ; optionally only match elements matching regex LIMIT ; NET can be either a VNI or description .
2018-09-28 20:31:56 -04:00
"""
zk_conn = pvc_common . startZKConnection ( zk_host )
2018-10-03 19:23:46 -04:00
retcode , retmsg = pvc_network . get_list_dhcp ( zk_conn , net , limit , only_static = True )
2018-09-28 20:31:56 -04:00
cleanup ( retcode , retmsg , zk_conn )
###############################################################################
# pvc network acl
###############################################################################
@click.group ( name = ' acl ' , short_help = ' Manage a PVC virtual network firewall ACL rule. ' , context_settings = CONTEXT_SETTINGS )
def net_acl ( ) :
"""
Manage firewall ACLs of a VXLAN network in the PVC cluster .
"""
pass
2018-09-21 23:43:30 -04:00
2018-10-17 00:23:27 -04:00
###############################################################################
# pvc network acl add
###############################################################################
@click.command ( name = ' add ' , short_help = ' Add firewall ACL. ' )
@click.option (
' --in/--out ' , ' direction ' ,
is_flag = True ,
required = True ,
default = None ,
help = ' Inbound or outbound ruleset. '
)
@click.option (
' -d ' , ' --description ' , ' description ' ,
required = True ,
help = ' Description of the ACL; must be unique and not contain whitespace. '
)
@click.option (
' -r ' , ' --rule ' , ' rule ' ,
required = True ,
help = ' NFT firewall rule. '
)
@click.option (
' -o ' , ' --order ' , ' order ' ,
default = None ,
help = ' Order of rule in the chain (see " list " ); defaults to last. '
)
@click.argument (
' net '
)
def net_acl_add ( net , direction , description , rule , order ) :
"""
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 can be either a VNI or description .
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 .
Example :
pvc network acl add 1001 - - in - - rule " tcp dport 22 ct state new accept " - - description " ssh-in " - - order 3
"""
zk_conn = pvc_common . startZKConnection ( zk_host )
retcode , retmsg = pvc_network . add_acl ( zk_conn , net , direction , description , rule , order )
cleanup ( retcode , retmsg , zk_conn )
###############################################################################
# pvc network acl remove
###############################################################################
@click.command ( name = ' remove ' , short_help = ' Remove firewall ACL. ' )
@click.option (
' --in/--out ' , ' direction ' ,
is_flag = True ,
required = True ,
default = None ,
help = ' Inbound or outbound rule set. '
)
@click.argument (
' net '
)
@click.argument (
' rule ' ,
)
def net_acl_remove ( net , rule , direction ) :
"""
Remove an NFT firewall rule RULE from network NET ; RULE can be either a sequence order identifier or description ; NET can be either a VNI or description . "
"""
zk_conn = pvc_common . startZKConnection ( zk_host )
retcode , retmsg = pvc_network . remove_acl ( zk_conn , net , rule , direction )
cleanup ( retcode , retmsg , zk_conn )
###############################################################################
# pvc network acl list
###############################################################################
@click.command ( name = ' list ' , short_help = ' List firewall ACLs. ' )
@click.option (
' --in/--out ' , ' direction ' ,
is_flag = True ,
2018-10-17 20:05:22 -04:00
required = False ,
2018-10-17 00:23:27 -04:00
default = None ,
2018-10-17 20:05:22 -04:00
help = ' Inbound or outbound rule set only. '
2018-10-17 00:23:27 -04:00
)
@click.argument (
' net '
)
@click.argument (
' limit ' , default = None , required = False
)
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 .
"""
2018-09-21 23:43:30 -04:00
2018-10-17 00:23:27 -04:00
zk_conn = pvc_common . startZKConnection ( zk_host )
retcode , retmsg = pvc_network . get_list_acl ( zk_conn , net , limit , direction )
cleanup ( retcode , retmsg , zk_conn )
2018-09-21 23:43:30 -04:00
2018-10-27 18:11:58 -04:00
###############################################################################
# pvc ceph
###############################################################################
@click.group ( name = ' ceph ' , short_help = ' Manage the PVC Ceph storage cluster. ' , context_settings = CONTEXT_SETTINGS )
def cli_ceph ( ) :
"""
Manage the Ceph storage of the PVC cluster .
2018-10-31 23:38:17 -04:00
NOTE : The PVC Ceph interface is limited to the most common tasks . Any other administrative tasks must be performed on a node directly .
2018-10-27 18:11:58 -04:00
"""
pass
###############################################################################
# pvc ceph status
###############################################################################
@click.command ( name = ' status ' , short_help = ' Show storage cluster status. ' )
def ceph_status ( ) :
"""
Show detailed status of the storage cluster .
"""
zk_conn = pvc_common . startZKConnection ( zk_host )
retcode , retmsg = pvc_ceph . get_status ( zk_conn )
cleanup ( retcode , retmsg , zk_conn )
###############################################################################
# pvc ceph osd
###############################################################################
@click.group ( name = ' osd ' , short_help = ' Manage OSDs in the PVC storage cluster. ' , context_settings = CONTEXT_SETTINGS )
def ceph_osd ( ) :
"""
Manage the Ceph OSDs of the PVC cluster .
"""
pass
2018-10-28 22:15:25 -04:00
###############################################################################
# pvc ceph osd add
###############################################################################
@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 (
' -w ' , ' --weight ' , ' weight ' ,
default = 1.0 , show_default = True ,
help = ' Weight of the OSD within the CRUSH map. '
)
def ceph_osd_add ( node , device , weight ) :
2018-10-28 22:15:25 -04:00
"""
Add a new Ceph OSD on node NODE with block device DEVICE to the cluster .
"""
zk_conn = pvc_common . startZKConnection ( zk_host )
2018-11-01 23:03:27 -04:00
retcode , retmsg = pvc_ceph . add_osd ( zk_conn , node , device , weight )
2018-10-28 22:15:25 -04:00
cleanup ( retcode , retmsg , zk_conn )
###############################################################################
# pvc ceph osd remove
###############################################################################
@click.command ( name = ' remove ' , short_help = ' Remove OSD. ' )
@click.argument (
' osdid '
)
2018-10-29 17:51:08 -04:00
def ceph_osd_remove ( osdid ) :
2018-10-28 22:15:25 -04:00
"""
Remove a Ceph OSD with ID OSDID from the cluster .
"""
zk_conn = pvc_common . startZKConnection ( zk_host )
retcode , retmsg = pvc_ceph . remove_osd ( zk_conn , osdid )
cleanup ( retcode , retmsg , zk_conn )
2018-11-01 22:00:59 -04:00
###############################################################################
# pvc ceph osd in
###############################################################################
@click.command ( name = ' in ' , short_help = ' Online OSD. ' )
@click.argument (
' osdid '
)
def ceph_osd_in ( osdid ) :
"""
Set a Ceph OSD with ID OSDID online in the cluster .
"""
zk_conn = pvc_common . startZKConnection ( zk_host )
retcode , retmsg = pvc_ceph . in_osd ( zk_conn , osdid )
cleanup ( retcode , retmsg , zk_conn )
###############################################################################
# pvc ceph osd out
###############################################################################
@click.command ( name = ' out ' , short_help = ' Offline OSD. ' )
@click.argument (
' osdid '
)
def ceph_osd_out ( osdid ) :
"""
Set a Ceph OSD with ID OSDID offline in the cluster .
"""
zk_conn = pvc_common . startZKConnection ( zk_host )
retcode , retmsg = pvc_ceph . out_osd ( zk_conn , osdid )
cleanup ( retcode , retmsg , zk_conn )
###############################################################################
# pvc ceph osd set
###############################################################################
@click.command ( name = ' set ' , short_help = ' Set property. ' )
@click.argument (
' osd_property '
)
def ceph_osd_set ( osd_property ) :
"""
Set a Ceph OSD property OSD_PROPERTY on the cluster .
Valid properties are :
full | pause | noup | nodown | noout | noin | nobackfill | norebalance | norecover | noscrub | nodeep - scrub | notieragent | sortbitwise | recovery_deletes | require_jewel_osds | require_kraken_osds
"""
zk_conn = pvc_common . startZKConnection ( zk_host )
retcode , retmsg = pvc_ceph . set_osd ( zk_conn , osd_property )
cleanup ( retcode , retmsg , zk_conn )
###############################################################################
# pvc ceph osd unset
###############################################################################
@click.command ( name = ' unset ' , short_help = ' Unset property. ' )
@click.argument (
' osd_property '
)
def ceph_osd_unset ( osd_property ) :
"""
Unset a Ceph OSD property OSD_PROPERTY on the cluster .
Valid properties are :
full | pause | noup | nodown | noout | noin | nobackfill | norebalance | norecover | noscrub | nodeep - scrub | notieragent | sortbitwise | recovery_deletes | require_jewel_osds | require_kraken_osds
"""
zk_conn = pvc_common . startZKConnection ( zk_host )
retcode , retmsg = pvc_ceph . unset_osd ( zk_conn , osd_property )
cleanup ( retcode , retmsg , zk_conn )
2018-10-30 09:17:32 -04:00
###############################################################################
# pvc ceph osd list
###############################################################################
@click.command ( name = ' list ' , short_help = ' List cluster OSDs. ' )
@click.argument (
' limit ' , default = None , required = False
)
def ceph_osd_list ( limit ) :
"""
List all Ceph OSDs in the cluster ; optinally only match elements matching ID regex LIMIT .
"""
zk_conn = pvc_common . startZKConnection ( zk_host )
retcode , retmsg = pvc_ceph . get_list_osd ( zk_conn , limit )
cleanup ( retcode , retmsg , zk_conn )
2018-10-27 18:11:58 -04:00
###############################################################################
# pvc ceph pool
###############################################################################
@click.group ( name = ' pool ' , short_help = ' Manage RBD pools in the PVC storage cluster. ' , context_settings = CONTEXT_SETTINGS )
def ceph_pool ( ) :
"""
Manage the Ceph RBD pools of the PVC cluster .
"""
pass
2018-09-21 23:43:30 -04:00
2018-10-31 23:38:17 -04:00
###############################################################################
# pvc ceph pool add
###############################################################################
@click.command ( name = ' add ' , short_help = ' Add new RBD pool. ' )
@click.argument (
' name '
)
@click.argument (
' pgs '
)
def ceph_pool_add ( name , pgs ) :
"""
Add a new Ceph RBD pool with name NAME and PGS placement groups .
"""
zk_conn = pvc_common . startZKConnection ( zk_host )
retcode , retmsg = pvc_ceph . add_pool ( zk_conn , name , pgs )
cleanup ( retcode , retmsg , zk_conn )
###############################################################################
# pvc ceph pool remove
###############################################################################
@click.command ( name = ' remove ' , short_help = ' Remove RBD pool. ' )
@click.argument (
' name '
)
@click.option ( ' --yes ' , is_flag = True ,
expose_value = False ,
prompt = ' DANGER: This command will destroy this pool and all volumes. Do you want to continue? '
)
def ceph_pool_remove ( name ) :
"""
Remove a Ceph RBD pool with name NAME and all volumes on it .
"""
zk_conn = pvc_common . startZKConnection ( zk_host )
retcode , retmsg = pvc_ceph . remove_pool ( zk_conn , name )
cleanup ( retcode , retmsg , zk_conn )
###############################################################################
# pvc ceph pool list
###############################################################################
@click.command ( name = ' list ' , short_help = ' List cluster RBD pools. ' )
@click.argument (
' limit ' , default = None , required = False
)
def ceph_pool_list ( limit ) :
"""
List all Ceph RBD pools in the cluster ; optinally only match elements matching name regex LIMIT .
"""
zk_conn = pvc_common . startZKConnection ( zk_host )
retcode , retmsg = pvc_ceph . get_list_pool ( zk_conn , limit )
cleanup ( retcode , retmsg , zk_conn )
2018-09-21 23:43:30 -04:00
2018-06-05 22:06:08 -04:00
###############################################################################
2018-06-06 01:07:59 -04:00
# pvc init
2018-06-05 22:06:08 -04:00
###############################################################################
2019-03-10 20:40:03 -04:00
2018-07-18 22:28:49 -04:00
@click.command ( name = ' init ' , short_help = ' Initialize a new cluster. ' )
2018-06-06 01:07:59 -04:00
def init_cluster ( ) :
"""
2019-03-10 20:40:03 -04:00
Perform initialization of a new PVC cluster .
2018-06-06 01:07:59 -04:00
"""
2019-03-10 20:40:03 -04:00
import pvc_init
2019-03-11 01:49:11 -04:00
# pvc_init.run()
pvc_init . init_zookeeper ( zk_host )
2018-06-06 01:29:11 -04:00
2018-06-05 01:39:59 -04: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 (
2018-10-25 11:54:05 -04:00
' -z ' , ' --zookeeper ' , ' _zk_host ' , envvar = ' PVC_ZOOKEEPER ' , default = None ,
2018-06-06 01:07:59 -04:00
help = ' Zookeeper connection string. '
)
def cli ( _zk_host ) :
"""
Parallel Virtual Cluster CLI management tool
2018-06-20 14:33:40 -04:00
2018-07-18 22:30:23 -04:00
Environment variables :
" PVC_ZOOKEEPER " : Set the cluster Zookeeper address instead of using " --zookeeper " .
2018-10-25 11:54:05 -04:00
2019-03-12 22:55:29 -04:00
If no PVC_ZOOKEEPER / - - zookeeper is specified , attempts to load coordinators list from / etc / pvc / pvcd . yaml .
2018-06-06 01:07:59 -04:00
"""
2019-03-12 22:55:29 -04:00
# If no zk_host was passed, try to read from /etc/pvc/pvcd.yaml; otherwise fail
2018-10-25 11:54:05 -04:00
if _zk_host is None :
try :
2019-03-12 22:55:29 -04:00
cfgfile = ' /etc/pvc/pvcd.yaml '
2019-03-12 23:11:10 -04:00
with open ( cfgfile ) as cfgf :
o_config = yaml . load ( cfgf )
2019-03-12 22:55:29 -04:00
_zk_host = o_config [ ' pvc ' ] [ ' cluster ' ] [ ' coordinators ' ]
2018-10-25 11:54:05 -04:00
except :
_zk_host = None
if _zk_host is None :
2019-03-12 22:55:29 -04:00
print ( ' ERROR: Must specify a PVC_ZOOKEEPER value or have a coordinator set configured in /etc/pvc/pvcd.yaml. ' )
2018-10-25 11:54:05 -04:00
exit ( 1 )
2018-06-06 01:20:09 -04:00
global zk_host
2018-06-06 01:07:59 -04:00
zk_host = _zk_host
2018-06-05 01:39:59 -04:00
#
# Click command tree
#
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 )
cli_node . add_command ( node_info )
cli_node . add_command ( node_list )
2019-03-10 20:40:03 -04:00
cli_vm . add_command ( vm_add )
2018-09-20 03:25:58 -04:00
cli_vm . add_command ( vm_define )
cli_vm . add_command ( vm_modify )
cli_vm . add_command ( vm_undefine )
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 )
cli_vm . add_command ( vm_move )
cli_vm . add_command ( vm_migrate )
cli_vm . add_command ( vm_unmigrate )
cli_vm . add_command ( vm_info )
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 )
net_dhcp . add_command ( net_dhcp_list )
2018-10-03 19:23:46 -04:00
net_dhcp . add_command ( net_dhcp_static )
net_dhcp_static . add_command ( net_dhcp_static_add )
net_dhcp_static . add_command ( net_dhcp_static_remove )
net_dhcp_static . add_command ( net_dhcp_static_list )
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 )
2018-10-28 22:15:25 -04:00
ceph_osd . add_command ( ceph_osd_add )
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 )
ceph_pool . add_command ( ceph_pool_list )
2018-10-27 18:11:58 -04:00
cli_ceph . add_command ( ceph_status )
cli_ceph . add_command ( ceph_osd )
cli_ceph . add_command ( ceph_pool )
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 )
2018-10-27 18:11:58 -04:00
cli . add_command ( cli_ceph )
2018-06-06 01:20:09 -04:00
cli . add_command ( init_cluster )
2018-06-05 01:39:59 -04:00
#
# Main entry point
#
def main ( ) :
return cli ( obj = { } )
if __name__ == ' __main__ ' :
main ( )
2018-06-14 11:57:36 -04:00