Lint: E302 expected 2 blank lines, found X

This commit is contained in:
Joshua Boniface 2020-11-07 14:45:24 -05:00
parent e9643651f7
commit 260b39ebf2
36 changed files with 694 additions and 19 deletions

View File

@ -30,6 +30,7 @@ import daemon_lib.ceph as pvc_ceph
config = None # Set in this namespace by flaskapi
def strtobool(stringv):
if stringv is None:
return False
@ -40,6 +41,7 @@ def strtobool(stringv):
except Exception:
return False
#
# Exceptions (used by Celery tasks)
#
@ -66,6 +68,7 @@ class BenchmarkError(Exception):
# Common functions
#
# Database connections
def open_database(config):
conn = psycopg2.connect(
@ -78,12 +81,14 @@ def open_database(config):
cur = conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor)
return conn, cur
def close_database(conn, cur, failed=False):
if not failed:
conn.commit()
cur.close()
conn.close()
def list_benchmarks(job=None):
if job is not None:
query = "SELECT * FROM {} WHERE job = %s;".format('storage_benchmarks')
@ -109,6 +114,7 @@ def list_benchmarks(job=None):
else:
return {'message': 'No benchmark found.'}, 404
def run_benchmark(self, pool):
# Runtime imports
import time

View File

@ -38,6 +38,7 @@ from flask_sqlalchemy import SQLAlchemy
API_VERSION = 1.0
def strtobool(stringv):
if stringv is None:
return False
@ -137,6 +138,7 @@ app.register_blueprint(blueprint)
celery = Celery(app.name, broker=app.config['CELERY_BROKER_URL'])
celery.conf.update(app.config)
#
# Custom decorators
#
@ -168,6 +170,7 @@ class RequestParser(object):
return function(*args, **kwargs)
return wrapped_function
# Authentication decorator function
def Authenticator(function):
@wraps(function)
@ -196,6 +199,7 @@ def Authenticator(function):
def create_vm(self, vm_name, profile_name, define_vm=True, start_vm=True, script_run_args=[]):
return api_provisioner.create_vm(self, vm_name, profile_name, define_vm=define_vm, start_vm=start_vm, script_run_args=script_run_args)
@celery.task(bind=True)
def run_benchmark(self, pool):
return api_benchmark.run_benchmark(self, pool)
@ -230,6 +234,7 @@ class API_Root(Resource):
api.add_resource(API_Root, '/')
# /doc - NOTE: Until flask_swagger is packaged for Debian this must be disabled
# class API_Doc(Resource):
# def get(self):
@ -251,6 +256,7 @@ api.add_resource(API_Root, '/')
#
# api.add_resource(API_Doc, '/doc')
# /login
class API_Login(Resource):
def post(self):
@ -294,6 +300,7 @@ class API_Login(Resource):
api.add_resource(API_Login, '/login')
# /logout
class API_Logout(Resource):
def post(self):
@ -320,6 +327,7 @@ class API_Logout(Resource):
api.add_resource(API_Logout, '/logout')
# /initialize
class API_Initialize(Resource):
@Authenticator
@ -351,6 +359,7 @@ class API_Initialize(Resource):
api.add_resource(API_Initialize, '/initialize')
# /status
class API_Status(Resource):
@Authenticator
@ -588,6 +597,7 @@ class API_Node_Root(Resource):
api.add_resource(API_Node_Root, '/node')
# /node/<node>
class API_Node_Element(Resource):
@Authenticator
@ -613,6 +623,7 @@ class API_Node_Element(Resource):
api.add_resource(API_Node_Element, '/node/<node>')
# /node/<node>/daemon-state
class API_Node_DaemonState(Resource):
@Authenticator
@ -646,6 +657,7 @@ class API_Node_DaemonState(Resource):
api.add_resource(API_Node_DaemonState, '/node/<node>/daemon-state')
# /node/<node>/coordinator-state
class API_Node_CoordinatorState(Resource):
@Authenticator
@ -716,6 +728,7 @@ class API_Node_CoordinatorState(Resource):
api.add_resource(API_Node_CoordinatorState, '/node/<node>/coordinator-state')
# /node/<node>/domain-state
class API_Node_DomainState(Resource):
@Authenticator
@ -1128,6 +1141,7 @@ class API_VM_Root(Resource):
api.add_resource(API_VM_Root, '/vm')
# /vm/<vm>
class API_VM_Element(Resource):
@Authenticator
@ -1310,6 +1324,7 @@ class API_VM_Element(Resource):
api.add_resource(API_VM_Element, '/vm/<vm>')
# /vm/<vm>/meta
class API_VM_Metadata(Resource):
@Authenticator
@ -1425,6 +1440,7 @@ class API_VM_Metadata(Resource):
api.add_resource(API_VM_Metadata, '/vm/<vm>/meta')
# /vm/<vm</state
class API_VM_State(Resource):
@Authenticator
@ -1512,6 +1528,7 @@ class API_VM_State(Resource):
api.add_resource(API_VM_State, '/vm/<vm>/state')
# /vm/<vm>/node
class API_VM_Node(Resource):
@Authenticator
@ -1614,6 +1631,7 @@ class API_VM_Node(Resource):
api.add_resource(API_VM_Node, '/vm/<vm>/node')
# /vm/<vm>/locks
class API_VM_Locks(Resource):
@Authenticator
@ -1640,6 +1658,7 @@ class API_VM_Locks(Resource):
api.add_resource(API_VM_Locks, '/vm/<vm>/locks')
# /vm/<vm</console
class API_VM_Console(Resource):
@RequestParser([
@ -1885,6 +1904,7 @@ class API_Network_Root(Resource):
api.add_resource(API_Network_Root, '/network')
# /network/<vni>
class API_Network_Element(Resource):
@Authenticator
@ -2133,6 +2153,7 @@ class API_Network_Element(Resource):
api.add_resource(API_Network_Element, '/network/<vni>')
# /network/<vni>/lease
class API_Network_Lease_Root(Resource):
@RequestParser([
@ -2254,6 +2275,7 @@ class API_Network_Lease_Root(Resource):
api.add_resource(API_Network_Lease_Root, '/network/<vni>/lease')
# /network/<vni>/lease/{mac}
class API_Network_Lease_Element(Resource):
@Authenticator
@ -2382,6 +2404,7 @@ class API_Network_Lease_Element(Resource):
api.add_resource(API_Network_Lease_Element, '/network/<vni>/lease/<mac>')
# /network/<vni>/acl
class API_Network_ACL_Root(Resource):
@RequestParser([
@ -2506,6 +2529,7 @@ class API_Network_ACL_Root(Resource):
api.add_resource(API_Network_ACL_Root, '/network/<vni>/acl')
# /network/<vni>/acl/<description>
class API_Network_ACL_Element(Resource):
@Authenticator
@ -2633,6 +2657,7 @@ class API_Storage_Root(Resource):
api.add_resource(API_Storage_Root, '/storage')
# /storage/ceph
class API_Storage_Ceph_Root(Resource):
@Authenticator
@ -2642,6 +2667,7 @@ class API_Storage_Ceph_Root(Resource):
api.add_resource(API_Storage_Ceph_Root, '/storage/ceph')
# /storage/ceph/status
class API_Storage_Ceph_Status(Resource):
@Authenticator
@ -2672,6 +2698,7 @@ class API_Storage_Ceph_Status(Resource):
api.add_resource(API_Storage_Ceph_Status, '/storage/ceph/status')
# /storage/ceph/utilization
class API_Storage_Ceph_Utilization(Resource):
@Authenticator
@ -2702,6 +2729,7 @@ class API_Storage_Ceph_Utilization(Resource):
api.add_resource(API_Storage_Ceph_Utilization, '/storage/ceph/utilization')
# /storage/ceph/benchmark
class API_Storage_Ceph_Benchmark(Resource):
@RequestParser([
@ -2862,6 +2890,7 @@ class API_Storage_Ceph_Benchmark(Resource):
api.add_resource(API_Storage_Ceph_Benchmark, '/storage/ceph/benchmark')
# /storage/ceph/option
class API_Storage_Ceph_Option(Resource):
@RequestParser([
@ -2910,6 +2939,7 @@ class API_Storage_Ceph_Option(Resource):
api.add_resource(API_Storage_Ceph_Option, '/storage/ceph/option')
# /storage/ceph/osd
class API_Storage_Ceph_OSD_Root(Resource):
@RequestParser([
@ -3055,6 +3085,7 @@ class API_Storage_Ceph_OSD_Root(Resource):
api.add_resource(API_Storage_Ceph_OSD_Root, '/storage/ceph/osd')
# /storage/ceph/osd/<osdid>
class API_Storage_Ceph_OSD_Element(Resource):
@Authenticator
@ -3116,6 +3147,7 @@ class API_Storage_Ceph_OSD_Element(Resource):
api.add_resource(API_Storage_Ceph_OSD_Element, '/storage/ceph/osd/<osdid>')
# /storage/ceph/osd/<osdid>/state
class API_Storage_Ceph_OSD_State(Resource):
@Authenticator
@ -3175,6 +3207,7 @@ class API_Storage_Ceph_OSD_State(Resource):
api.add_resource(API_Storage_Ceph_OSD_State, '/storage/ceph/osd/<osdid>/state')
# /storage/ceph/pool
class API_Storage_Ceph_Pool_Root(Resource):
@RequestParser([
@ -3307,6 +3340,7 @@ class API_Storage_Ceph_Pool_Root(Resource):
api.add_resource(API_Storage_Ceph_Pool_Root, '/storage/ceph/pool')
# /storage/ceph/pool/<pool>
class API_Storage_Ceph_Pool_Element(Resource):
@Authenticator
@ -3418,6 +3452,7 @@ class API_Storage_Ceph_Pool_Element(Resource):
api.add_resource(API_Storage_Ceph_Pool_Element, '/storage/ceph/pool/<pool>')
# /storage/ceph/volume
class API_Storage_Ceph_Volume_Root(Resource):
@RequestParser([
@ -3569,6 +3604,7 @@ class API_Storage_Ceph_Volume_Root(Resource):
api.add_resource(API_Storage_Ceph_Volume_Root, '/storage/ceph/volume')
# /storage/ceph/volume/<pool>/<volume>
class API_Storage_Ceph_Volume_Element(Resource):
@Authenticator
@ -3718,6 +3754,7 @@ class API_Storage_Ceph_Volume_Element(Resource):
api.add_resource(API_Storage_Ceph_Volume_Element, '/storage/ceph/volume/<pool>/<volume>')
# /storage/ceph/volume/<pool>/<volume>/clone
class API_Storage_Ceph_Volume_Element_Clone(Resource):
@RequestParser([
@ -3762,6 +3799,7 @@ class API_Storage_Ceph_Volume_Element_Clone(Resource):
api.add_resource(API_Storage_Ceph_Volume_Element_Clone, '/storage/ceph/volume/<pool>/<volume>/clone')
# /storage/ceph/volume/<pool>/<volume>/upload
class API_Storage_Ceph_Volume_Element_Upload(Resource):
@RequestParser([
@ -3815,6 +3853,7 @@ class API_Storage_Ceph_Volume_Element_Upload(Resource):
api.add_resource(API_Storage_Ceph_Volume_Element_Upload, '/storage/ceph/volume/<pool>/<volume>/upload')
# /storage/ceph/snapshot
class API_Storage_Ceph_Snapshot_Root(Resource):
@RequestParser([
@ -3922,6 +3961,7 @@ class API_Storage_Ceph_Snapshot_Root(Resource):
api.add_resource(API_Storage_Ceph_Snapshot_Root, '/storage/ceph/snapshot')
# /storage/ceph/snapshot/<pool>/<volume>/<snapshot>
class API_Storage_Ceph_Snapshot_Element(Resource):
@Authenticator
@ -4081,6 +4121,7 @@ class API_Provisioner_Root(Resource):
api.add_resource(API_Provisioner_Root, '/provisioner')
# /provisioner/template
class API_Provisioner_Template_Root(Resource):
@RequestParser([
@ -4129,6 +4170,7 @@ class API_Provisioner_Template_Root(Resource):
api.add_resource(API_Provisioner_Template_Root, '/provisioner/template')
# /provisioner/template/system
class API_Provisioner_Template_System_Root(Resource):
@RequestParser([
@ -4320,6 +4362,7 @@ class API_Provisioner_Template_System_Root(Resource):
api.add_resource(API_Provisioner_Template_System_Root, '/provisioner/template/system')
# /provisioner/template/system/<template>
class API_Provisioner_Template_System_Element(Resource):
@Authenticator
@ -4565,6 +4608,7 @@ class API_Provisioner_Template_System_Element(Resource):
api.add_resource(API_Provisioner_Template_System_Element, '/provisioner/template/system/<template>')
# /provisioner/template/network
class API_Provisioner_Template_Network_Root(Resource):
@RequestParser([
@ -4668,6 +4712,7 @@ class API_Provisioner_Template_Network_Root(Resource):
api.add_resource(API_Provisioner_Template_Network_Root, '/provisioner/template/network')
# /provisioner/template/network/<template>
class API_Provisioner_Template_Network_Element(Resource):
@Authenticator
@ -4752,6 +4797,7 @@ class API_Provisioner_Template_Network_Element(Resource):
api.add_resource(API_Provisioner_Template_Network_Element, '/provisioner/template/network/<template>')
# /provisioner/template/network/<template>/net
class API_Provisioner_Template_Network_Net_Root(Resource):
@Authenticator
@ -4819,6 +4865,7 @@ class API_Provisioner_Template_Network_Net_Root(Resource):
api.add_resource(API_Provisioner_Template_Network_Net_Root, '/provisioner/template/network/<template>/net')
# /provisioner/template/network/<template>/net/<vni>
class API_Provisioner_Template_Network_Net_Element(Resource):
@Authenticator
@ -4899,6 +4946,7 @@ class API_Provisioner_Template_Network_Net_Element(Resource):
api.add_resource(API_Provisioner_Template_Network_Net_Element, '/provisioner/template/network/<template>/net/<vni>')
# /provisioner/template/storage
class API_Provisioner_Template_Storage_Root(Resource):
@RequestParser([
@ -5009,6 +5057,7 @@ class API_Provisioner_Template_Storage_Root(Resource):
api.add_resource(API_Provisioner_Template_Storage_Root, '/provisioner/template/storage')
# /provisioner/template/storage/<template>
class API_Provisioner_Template_Storage_Element(Resource):
@Authenticator
@ -5083,6 +5132,7 @@ class API_Provisioner_Template_Storage_Element(Resource):
api.add_resource(API_Provisioner_Template_Storage_Element, '/provisioner/template/storage/<template>')
# /provisioner/template/storage/<template>/disk
class API_Provisioner_Template_Storage_Disk_Root(Resource):
@RequestParser([
@ -5195,6 +5245,7 @@ class API_Provisioner_Template_Storage_Disk_Root(Resource):
api.add_resource(API_Provisioner_Template_Storage_Disk_Root, '/provisioner/template/storage/<template>/disk')
# /provisioner/template/storage/<template>/disk/<disk_id>
class API_Provisioner_Template_Storage_Disk_Element(Resource):
@Authenticator
@ -5321,6 +5372,7 @@ class API_Provisioner_Template_Storage_Disk_Element(Resource):
api.add_resource(API_Provisioner_Template_Storage_Disk_Element, '/provisioner/template/storage/<template>/disk/<disk_id>')
# /provisioner/userdata
class API_Provisioner_Userdata_Root(Resource):
@RequestParser([
@ -5407,6 +5459,7 @@ class API_Provisioner_Userdata_Root(Resource):
api.add_resource(API_Provisioner_Userdata_Root, '/provisioner/userdata')
# /provisioner/userdata/<userdata>
class API_Provisioner_Userdata_Element(Resource):
@Authenticator
@ -5524,6 +5577,7 @@ class API_Provisioner_Userdata_Element(Resource):
api.add_resource(API_Provisioner_Userdata_Element, '/provisioner/userdata/<userdata>')
# /provisioner/script
class API_Provisioner_Script_Root(Resource):
@RequestParser([
@ -5610,6 +5664,7 @@ class API_Provisioner_Script_Root(Resource):
api.add_resource(API_Provisioner_Script_Root, '/provisioner/script')
# /provisioner/script/<script>
class API_Provisioner_Script_Element(Resource):
@Authenticator
@ -5727,6 +5782,7 @@ class API_Provisioner_Script_Element(Resource):
api.add_resource(API_Provisioner_Script_Element, '/provisioner/script/<script>')
# /provisioner/profile
class API_Provisioner_OVA_Root(Resource):
@RequestParser([
@ -5840,6 +5896,7 @@ class API_Provisioner_OVA_Root(Resource):
api.add_resource(API_Provisioner_OVA_Root, '/provisioner/ova')
# /provisioner/ova/<ova>
class API_Provisioner_OVA_Element(Resource):
@Authenticator
@ -5933,6 +5990,7 @@ class API_Provisioner_OVA_Element(Resource):
api.add_resource(API_Provisioner_OVA_Element, '/provisioner/ova/<ova>')
# /provisioner/profile
class API_Provisioner_Profile_Root(Resource):
@RequestParser([
@ -6087,6 +6145,7 @@ class API_Provisioner_Profile_Root(Resource):
api.add_resource(API_Provisioner_Profile_Root, '/provisioner/profile')
# /provisioner/profile/<profile>
class API_Provisioner_Profile_Element(Resource):
@Authenticator
@ -6291,6 +6350,7 @@ class API_Provisioner_Profile_Element(Resource):
api.add_resource(API_Provisioner_Profile_Element, '/provisioner/profile/<profile>')
# /provisioner/create
class API_Provisioner_Create_Root(Resource):
@RequestParser([
@ -6375,6 +6435,7 @@ class API_Provisioner_Create_Root(Resource):
api.add_resource(API_Provisioner_Create_Root, '/provisioner/create')
# /provisioner/status
class API_Provisioner_Status_Root(Resource):
@Authenticator
@ -6411,6 +6472,7 @@ class API_Provisioner_Status_Root(Resource):
api.add_resource(API_Provisioner_Status_Root, '/provisioner/status')
# /provisioner/status/<task_id>
class API_Provisioner_Status_Element(Resource):
@Authenticator

View File

@ -36,6 +36,7 @@ import daemon_lib.ceph as pvc_ceph
config = None # Set in this namespace by flaskapi
def strtobool(stringv):
if stringv is None:
return False
@ -46,6 +47,7 @@ def strtobool(stringv):
except Exception:
return False
#
# Initialization function
#
@ -83,6 +85,7 @@ def initialize_cluster():
return True
#
# Cluster functions
#
@ -96,6 +99,7 @@ def cluster_status():
return retdata, 200
def cluster_maintenance(maint_state='false'):
"""
Set the cluster in or out of maintenance state
@ -114,6 +118,7 @@ def cluster_maintenance(maint_state='false'):
return retdata, retcode
#
# Node functions
#
@ -145,6 +150,7 @@ def node_list(limit=None, daemon_state=None, coordinator_state=None, domain_stat
return retdata, retcode
def node_daemon_state(node):
"""
Return the daemon state of node NODE.
@ -173,6 +179,7 @@ def node_daemon_state(node):
return retdata, retcode
def node_coordinator_state(node):
"""
Return the coordinator state of node NODE.
@ -201,6 +208,7 @@ def node_coordinator_state(node):
return retdata, retcode
def node_domain_state(node):
"""
Return the domain state of node NODE.
@ -226,6 +234,7 @@ def node_domain_state(node):
return retdata, retcode
def node_secondary(node):
"""
Take NODE out of primary router mode.
@ -244,6 +253,7 @@ def node_secondary(node):
}
return output, retcode
def node_primary(node):
"""
Set NODE to primary router mode.
@ -262,6 +272,7 @@ def node_primary(node):
}
return output, retcode
def node_flush(node, wait):
"""
Flush NODE of running VMs.
@ -280,6 +291,7 @@ def node_flush(node, wait):
}
return output, retcode
def node_ready(node, wait):
"""
Restore NODE to active service.
@ -298,6 +310,7 @@ def node_ready(node, wait):
}
return output, retcode
#
# VM functions
#
@ -311,6 +324,7 @@ def vm_is_migrated(vm):
return retdata
def vm_state(vm):
"""
Return the state of virtual machine VM.
@ -343,6 +357,7 @@ def vm_state(vm):
return retdata, retcode
def vm_node(vm):
"""
Return the current node of virtual machine VM.
@ -376,6 +391,7 @@ def vm_node(vm):
return retdata, retcode
def vm_console(vm, lines=None):
"""
Return the current console log for VM.
@ -404,6 +420,7 @@ def vm_console(vm, lines=None):
return retdata, retcode
def vm_list(node=None, state=None, limit=None, is_fuzzy=True):
"""
Return a list of VMs with limit LIMIT.
@ -432,6 +449,7 @@ def vm_list(node=None, state=None, limit=None, is_fuzzy=True):
return retdata, retcode
def vm_define(xml, node, limit, selector, autostart, migration_method):
"""
Define a VM from Libvirt XML in the PVC cluster.
@ -457,6 +475,7 @@ def vm_define(xml, node, limit, selector, autostart, migration_method):
}
return output, retcode
def get_vm_meta(vm):
"""
Get metadata of a VM.
@ -492,6 +511,7 @@ def get_vm_meta(vm):
return retdata, retcode
def update_vm_meta(vm, limit, selector, autostart, provisioner_profile, migration_method):
"""
Update metadata of a VM.
@ -515,6 +535,7 @@ def update_vm_meta(vm, limit, selector, autostart, provisioner_profile, migratio
}
return output, retcode
def vm_modify(name, restart, xml):
"""
Modify a VM Libvirt XML in the PVC cluster.
@ -539,6 +560,7 @@ def vm_modify(name, restart, xml):
}
return output, retcode
def vm_undefine(name):
"""
Undefine a VM from the PVC cluster.
@ -557,6 +579,7 @@ def vm_undefine(name):
}
return output, retcode
def vm_remove(name):
"""
Remove a VM from the PVC cluster.
@ -575,6 +598,7 @@ def vm_remove(name):
}
return output, retcode
def vm_start(name):
"""
Start a VM in the PVC cluster.
@ -593,6 +617,7 @@ def vm_start(name):
}
return output, retcode
def vm_restart(name, wait):
"""
Restart a VM in the PVC cluster.
@ -611,6 +636,7 @@ def vm_restart(name, wait):
}
return output, retcode
def vm_shutdown(name, wait):
"""
Shutdown a VM in the PVC cluster.
@ -629,6 +655,7 @@ def vm_shutdown(name, wait):
}
return output, retcode
def vm_stop(name):
"""
Forcibly stop a VM in the PVC cluster.
@ -647,6 +674,7 @@ def vm_stop(name):
}
return output, retcode
def vm_disable(name):
"""
Disable a (stopped) VM in the PVC cluster.
@ -665,6 +693,7 @@ def vm_disable(name):
}
return output, retcode
def vm_move(name, node, wait, force_live):
"""
Move a VM to another node.
@ -683,6 +712,7 @@ def vm_move(name, node, wait, force_live):
}
return output, retcode
def vm_migrate(name, node, flag_force, wait, force_live):
"""
Temporarily migrate a VM to another node.
@ -701,6 +731,7 @@ def vm_migrate(name, node, flag_force, wait, force_live):
}
return output, retcode
def vm_unmigrate(name, wait, force_live):
"""
Unmigrate a migrated VM.
@ -719,6 +750,7 @@ def vm_unmigrate(name, wait, force_live):
}
return output, retcode
def vm_flush_locks(vm):
"""
Flush locks of a (stopped) VM.
@ -748,6 +780,7 @@ def vm_flush_locks(vm):
}
return output, retcode
#
# Network functions
#
@ -779,6 +812,7 @@ def net_list(limit=None, is_fuzzy=True):
return retdata, retcode
def net_add(vni, description, nettype, domain, name_servers,
ip4_network, ip4_gateway, ip6_network, ip6_gateway,
dhcp4_flag, dhcp4_start, dhcp4_end):
@ -803,6 +837,7 @@ def net_add(vni, description, nettype, domain, name_servers,
}
return output, retcode
def net_modify(vni, description, domain, name_servers,
ip4_network, ip4_gateway,
ip6_network, ip6_gateway,
@ -828,6 +863,7 @@ def net_modify(vni, description, domain, name_servers,
}
return output, retcode
def net_remove(network):
"""
Remove a virtual client network from the PVC cluster.
@ -846,6 +882,7 @@ def net_remove(network):
}
return output, retcode
def net_dhcp_list(network, limit=None, static=False):
"""
Return a list of DHCP leases in network NETWORK with limit LIMIT.
@ -870,6 +907,7 @@ def net_dhcp_list(network, limit=None, static=False):
return retdata, retcode
def net_dhcp_add(network, ipaddress, macaddress, hostname):
"""
Add a static DHCP lease to a virtual client network.
@ -888,6 +926,7 @@ def net_dhcp_add(network, ipaddress, macaddress, hostname):
}
return output, retcode
def net_dhcp_remove(network, macaddress):
"""
Remove a static DHCP lease from a virtual client network.
@ -906,6 +945,7 @@ def net_dhcp_remove(network, macaddress):
}
return output, retcode
def net_acl_list(network, limit=None, direction=None, is_fuzzy=True):
"""
Return a list of network ACLs in network NETWORK with limit LIMIT.
@ -934,6 +974,7 @@ def net_acl_list(network, limit=None, direction=None, is_fuzzy=True):
return retdata, retcode
def net_acl_add(network, direction, description, rule, order):
"""
Add an ACL to a virtual client network.
@ -952,6 +993,7 @@ def net_acl_add(network, direction, description, rule, order):
}
return output, retcode
def net_acl_remove(network, description):
"""
Remove an ACL from a virtual client network.
@ -970,6 +1012,7 @@ def net_acl_remove(network, description):
}
return output, retcode
#
# Ceph functions
#
@ -988,6 +1031,7 @@ def ceph_status():
return retdata, retcode
def ceph_util():
"""
Get the current Ceph cluster utilization.
@ -1003,6 +1047,7 @@ def ceph_util():
return retdata, retcode
def ceph_osd_list(limit=None):
"""
Get the list of OSDs in the Ceph storage cluster.
@ -1027,6 +1072,7 @@ def ceph_osd_list(limit=None):
return retdata, retcode
def ceph_osd_state(osd):
zk_conn = pvc_common.startZKConnection(config['coordinators'])
retflag, retdata = pvc_ceph.get_list_osd(zk_conn, osd)
@ -1051,6 +1097,7 @@ def ceph_osd_state(osd):
return {"id": osd, "in": in_state, "up": up_state}, retcode
def ceph_osd_add(node, device, weight):
"""
Add a Ceph OSD to the PVC Ceph storage cluster.
@ -1069,6 +1116,7 @@ def ceph_osd_add(node, device, weight):
}
return output, retcode
def ceph_osd_remove(osd_id):
"""
Remove a Ceph OSD from the PVC Ceph storage cluster.
@ -1087,6 +1135,7 @@ def ceph_osd_remove(osd_id):
}
return output, retcode
def ceph_osd_in(osd_id):
"""
Set in a Ceph OSD in the PVC Ceph storage cluster.
@ -1105,6 +1154,7 @@ def ceph_osd_in(osd_id):
}
return output, retcode
def ceph_osd_out(osd_id):
"""
Set out a Ceph OSD in the PVC Ceph storage cluster.
@ -1123,6 +1173,7 @@ def ceph_osd_out(osd_id):
}
return output, retcode
def ceph_osd_set(option):
"""
Set options on a Ceph OSD in the PVC Ceph storage cluster.
@ -1141,6 +1192,7 @@ def ceph_osd_set(option):
}
return output, retcode
def ceph_osd_unset(option):
"""
Unset options on a Ceph OSD in the PVC Ceph storage cluster.
@ -1159,6 +1211,7 @@ def ceph_osd_unset(option):
}
return output, retcode
def ceph_pool_list(limit=None, is_fuzzy=True):
"""
Get the list of RBD pools in the Ceph storage cluster.
@ -1187,6 +1240,7 @@ def ceph_pool_list(limit=None, is_fuzzy=True):
return retdata, retcode
def ceph_pool_add(name, pgs, replcfg):
"""
Add a Ceph RBD pool to the PVC Ceph storage cluster.
@ -1205,6 +1259,7 @@ def ceph_pool_add(name, pgs, replcfg):
}
return output, retcode
def ceph_pool_remove(name):
"""
Remove a Ceph RBD pool to the PVC Ceph storage cluster.
@ -1223,6 +1278,7 @@ def ceph_pool_remove(name):
}
return output, retcode
def ceph_volume_list(pool=None, limit=None, is_fuzzy=True):
"""
Get the list of RBD volumes in the Ceph storage cluster.
@ -1251,6 +1307,7 @@ def ceph_volume_list(pool=None, limit=None, is_fuzzy=True):
return retdata, retcode
def ceph_volume_add(pool, name, size):
"""
Add a Ceph RBD volume to the PVC Ceph storage cluster.
@ -1269,6 +1326,7 @@ def ceph_volume_add(pool, name, size):
}
return output, retcode
def ceph_volume_clone(pool, name, source_volume):
"""
Clone a Ceph RBD volume to a new volume on the PVC Ceph storage cluster.
@ -1287,6 +1345,7 @@ def ceph_volume_clone(pool, name, source_volume):
}
return output, retcode
def ceph_volume_resize(pool, name, size):
"""
Resize an existing Ceph RBD volume in the PVC Ceph storage cluster.
@ -1305,6 +1364,7 @@ def ceph_volume_resize(pool, name, size):
}
return output, retcode
def ceph_volume_rename(pool, name, new_name):
"""
Rename a Ceph RBD volume in the PVC Ceph storage cluster.
@ -1323,6 +1383,7 @@ def ceph_volume_rename(pool, name, new_name):
}
return output, retcode
def ceph_volume_remove(pool, name):
"""
Remove a Ceph RBD volume to the PVC Ceph storage cluster.
@ -1341,6 +1402,7 @@ def ceph_volume_remove(pool, name):
}
return output, retcode
def ceph_volume_upload(pool, volume, img_type):
"""
Upload a raw file via HTTP post to a PVC Ceph volume
@ -1491,6 +1553,7 @@ def ceph_volume_upload(pool, volume, img_type):
cleanup_maps_and_volumes()
return output, retcode
def ceph_volume_snapshot_list(pool=None, volume=None, limit=None, is_fuzzy=True):
"""
Get the list of RBD volume snapshots in the Ceph storage cluster.
@ -1519,6 +1582,7 @@ def ceph_volume_snapshot_list(pool=None, volume=None, limit=None, is_fuzzy=True)
return retdata, retcode
def ceph_volume_snapshot_add(pool, volume, name):
"""
Add a Ceph RBD volume snapshot to the PVC Ceph storage cluster.
@ -1537,6 +1601,7 @@ def ceph_volume_snapshot_add(pool, volume, name):
}
return output, retcode
def ceph_volume_snapshot_rename(pool, volume, name, new_name):
"""
Rename a Ceph RBD volume snapshot in the PVC Ceph storage cluster.
@ -1555,6 +1620,7 @@ def ceph_volume_snapshot_rename(pool, volume, name, new_name):
}
return output, retcode
def ceph_volume_snapshot_remove(pool, volume, name):
"""
Remove a Ceph RBD volume snapshot from the PVC Ceph storage cluster.

View File

@ -22,6 +22,7 @@
from pvcapid.flaskapi import db
class DBSystemTemplate(db.Model):
__tablename__ = 'system_template'
@ -54,6 +55,7 @@ class DBSystemTemplate(db.Model):
def __repr__(self):
return '<id {}>'.format(self.id)
class DBNetworkTemplate(db.Model):
__tablename__ = 'network_template'
@ -70,6 +72,7 @@ class DBNetworkTemplate(db.Model):
def __repr__(self):
return '<id {}>'.format(self.id)
class DBNetworkElement(db.Model):
__tablename__ = 'network'
@ -84,6 +87,7 @@ class DBNetworkElement(db.Model):
def __repr__(self):
return '<id {}>'.format(self.id)
class DBStorageTemplate(db.Model):
__tablename__ = 'storage_template'
@ -98,6 +102,7 @@ class DBStorageTemplate(db.Model):
def __repr__(self):
return '<id {}>'.format(self.id)
class DBStorageElement(db.Model):
__tablename__ = 'storage'
@ -124,6 +129,7 @@ class DBStorageElement(db.Model):
def __repr__(self):
return '<id {}>'.format(self.id)
class DBUserdata(db.Model):
__tablename__ = 'userdata'
@ -138,6 +144,7 @@ class DBUserdata(db.Model):
def __repr__(self):
return '<id {}>'.format(self.id)
class DBScript(db.Model):
__tablename__ = 'script'
@ -152,6 +159,7 @@ class DBScript(db.Model):
def __repr__(self):
return '<id {}>'.format(self.id)
class DBOva(db.Model):
__tablename__ = 'ova'
@ -166,6 +174,7 @@ class DBOva(db.Model):
def __repr__(self):
return '<id {}>'.format(self.id)
class DBOvaVolume(db.Model):
__tablename__ = 'ova_volume'
@ -188,6 +197,7 @@ class DBOvaVolume(db.Model):
def __repr__(self):
return '<id {}>'.format(self.id)
class DBProfile(db.Model):
__tablename__ = 'profile'
@ -216,6 +226,7 @@ class DBProfile(db.Model):
def __repr__(self):
return '<id {}>'.format(self.id)
class DBStorageBenchmarks(db.Model):
__tablename__ = 'storage_benchmarks'

View File

@ -38,6 +38,7 @@ import pvcapid.provisioner as provisioner
config = None # Set in this namespace by flaskapi
#
# Common functions
#
@ -54,12 +55,14 @@ def open_database(config):
cur = conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor)
return conn, cur
def close_database(conn, cur, failed=False):
if not failed:
conn.commit()
cur.close()
conn.close()
#
# OVA functions
#
@ -107,6 +110,7 @@ def list_ova(limit, is_fuzzy=True):
else:
return {'message': 'No OVAs found.'}, 404
def delete_ova(name):
ova_data, retcode = list_ova(name, is_fuzzy=False)
if retcode != 200:
@ -156,6 +160,7 @@ def delete_ova(name):
close_database(conn, cur)
return retmsg, retcode
def upload_ova(pool, name, ova_size):
ova_archive = None
@ -407,6 +412,7 @@ def upload_ova(pool, name, ova_size):
retcode = 200
return output, retcode
#
# OVF parser
#

View File

@ -39,6 +39,7 @@ from pvcapid.ova import list_ova
config = None # Set in this namespace by flaskapi
def strtobool(stringv):
if stringv is None:
return False
@ -49,6 +50,7 @@ def strtobool(stringv):
except Exception:
return False
#
# Exceptions (used by Celery tasks)
#
@ -58,18 +60,21 @@ class ValidationError(Exception):
"""
pass
class ClusterError(Exception):
"""
An exception that results from the PVC cluster being out of alignment with the action.
"""
pass
class ProvisioningError(Exception):
"""
An exception that results from a failure of a provisioning command.
"""
pass
#
# Common functions
#
@ -86,12 +91,14 @@ def open_database(config):
cur = conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor)
return conn, cur
def close_database(conn, cur, failed=False):
if not failed:
conn.commit()
cur.close()
conn.close()
#
# Template List functions
#
@ -143,6 +150,7 @@ def list_template(limit, table, is_fuzzy=True):
return data
def list_template_system(limit, is_fuzzy=True):
"""
Obtain a list of system templates.
@ -153,6 +161,7 @@ def list_template_system(limit, is_fuzzy=True):
else:
return {'message': 'No system templates found.'}, 404
def list_template_network(limit, is_fuzzy=True):
"""
Obtain a list of network templates.
@ -163,6 +172,7 @@ def list_template_network(limit, is_fuzzy=True):
else:
return {'message': 'No network templates found.'}, 404
def list_template_network_vnis(name):
"""
Obtain a list of network template VNIs.
@ -174,6 +184,7 @@ def list_template_network_vnis(name):
else:
return {'message': 'No network template networks found.'}, 404
def list_template_storage(limit, is_fuzzy=True):
"""
Obtain a list of storage templates.
@ -184,6 +195,7 @@ def list_template_storage(limit, is_fuzzy=True):
else:
return {'message': 'No storage templates found.'}, 404
def list_template_storage_disks(name):
"""
Obtain a list of storage template disks.
@ -195,6 +207,7 @@ def list_template_storage_disks(name):
else:
return {'message': 'No storage template disks found.'}, 404
def template_list(limit):
system_templates, code = list_template_system(limit)
if code != 200:
@ -208,6 +221,7 @@ def template_list(limit):
return {"system_templates": system_templates, "network_templates": network_templates, "storage_templates": storage_templates}
#
# Template Create functions
#
@ -231,6 +245,7 @@ def create_template_system(name, vcpu_count, vram_mb, serial=False, vnc=False, v
close_database(conn, cur)
return retmsg, retcode
def create_template_network(name, mac_template=None):
if list_template_network(name, is_fuzzy=False)[-1] != 404:
retmsg = {'message': 'The network template "{}" already exists.'.format(name)}
@ -250,6 +265,7 @@ def create_template_network(name, mac_template=None):
close_database(conn, cur)
return retmsg, retcode
def create_template_network_element(name, vni):
if list_template_network(name, is_fuzzy=False)[-1] != 200:
retmsg = {'message': 'The network template "{}" does not exist.'.format(name)}
@ -285,6 +301,7 @@ def create_template_network_element(name, vni):
close_database(conn, cur)
return retmsg, retcode
def create_template_storage(name):
if list_template_storage(name, is_fuzzy=False)[-1] != 404:
retmsg = {'message': 'The storage template "{}" already exists.'.format(name)}
@ -304,6 +321,7 @@ def create_template_storage(name):
close_database(conn, cur)
return retmsg, retcode
def create_template_storage_element(name, disk_id, pool, source_volume=None, disk_size_gb=None, filesystem=None, filesystem_args=[], mountpoint=None):
if list_template_storage(name, is_fuzzy=False)[-1] != 200:
retmsg = {'message': 'The storage template "{}" does not exist.'.format(name)}
@ -353,6 +371,7 @@ def create_template_storage_element(name, disk_id, pool, source_volume=None, dis
close_database(conn, cur)
return retmsg, retcode
#
# Template Modify functions
#
@ -434,6 +453,7 @@ def modify_template_system(name, vcpu_count=None, vram_mb=None, serial=None, vnc
close_database(conn, cur)
return retmsg, retcode
#
# Template Delete functions
#
@ -456,6 +476,7 @@ def delete_template_system(name):
close_database(conn, cur)
return retmsg, retcode
def delete_template_network(name):
if list_template_network(name, is_fuzzy=False)[-1] != 200:
retmsg = {'message': 'The network template "{}" does not exist.'.format(name)}
@ -482,6 +503,7 @@ def delete_template_network(name):
close_database(conn, cur)
return retmsg, retcode
def delete_template_network_element(name, vni):
if list_template_network(name, is_fuzzy=False)[-1] != 200:
retmsg = {'message': 'The network template "{}" does not exist.'.format(name)}
@ -515,6 +537,7 @@ def delete_template_network_element(name, vni):
close_database(conn, cur)
return retmsg, retcode
def delete_template_storage(name):
if list_template_storage(name, is_fuzzy=False)[-1] != 200:
retmsg = {'message': 'The storage template "{}" does not exist.'.format(name)}
@ -541,6 +564,7 @@ def delete_template_storage(name):
close_database(conn, cur)
return retmsg, retcode
def delete_template_storage_element(name, disk_id):
if list_template_storage(name, is_fuzzy=False)[-1] != 200:
retmsg = {'message': 'The storage template "{}" does not exist.'.format(name)}
@ -574,6 +598,7 @@ def delete_template_storage_element(name, disk_id):
close_database(conn, cur)
return retmsg, retcode
#
# Userdata functions
#
@ -605,6 +630,7 @@ def list_userdata(limit, is_fuzzy=True):
else:
return {'message': 'No userdata documents found.'}, 404
def create_userdata(name, userdata):
if list_userdata(name, is_fuzzy=False)[-1] != 404:
retmsg = {'message': 'The userdata document "{}" already exists.'.format(name)}
@ -624,6 +650,7 @@ def create_userdata(name, userdata):
close_database(conn, cur)
return retmsg, retcode
def update_userdata(name, userdata):
if list_userdata(name, is_fuzzy=False)[-1] != 200:
retmsg = {'message': 'The userdata "{}" does not exist.'.format(name)}
@ -646,6 +673,7 @@ def update_userdata(name, userdata):
close_database(conn, cur)
return retmsg, retcode
def delete_userdata(name):
if list_userdata(name, is_fuzzy=False)[-1] != 200:
retmsg = {'message': 'The userdata "{}" does not exist.'.format(name)}
@ -665,6 +693,7 @@ def delete_userdata(name):
close_database(conn, cur)
return retmsg, retcode
#
# Script functions
#
@ -696,6 +725,7 @@ def list_script(limit, is_fuzzy=True):
else:
return {'message': 'No scripts found.'}, 404
def create_script(name, script):
if list_script(name, is_fuzzy=False)[-1] != 404:
retmsg = {'message': 'The script "{}" already exists.'.format(name)}
@ -715,6 +745,7 @@ def create_script(name, script):
close_database(conn, cur)
return retmsg, retcode
def update_script(name, script):
if list_script(name, is_fuzzy=False)[-1] != 200:
retmsg = {'message': 'The script "{}" does not exist.'.format(name)}
@ -737,6 +768,7 @@ def update_script(name, script):
close_database(conn, cur)
return retmsg, retcode
def delete_script(name):
if list_script(name, is_fuzzy=False)[-1] != 200:
retmsg = {'message': 'The script "{}" does not exist.'.format(name)}
@ -756,6 +788,7 @@ def delete_script(name):
close_database(conn, cur)
return retmsg, retcode
#
# Profile functions
#
@ -807,6 +840,7 @@ def list_profile(limit, is_fuzzy=True):
else:
return {'message': 'No profiles found.'}, 404
def create_profile(name, profile_type, system_template, network_template, storage_template, userdata=None, script=None, ova=None, arguments=None):
if list_profile(name, is_fuzzy=False)[-1] != 404:
retmsg = {'message': 'The profile "{}" already exists.'.format(name)}
@ -896,6 +930,7 @@ def create_profile(name, profile_type, system_template, network_template, storag
close_database(conn, cur)
return retmsg, retcode
def modify_profile(name, profile_type, system_template, network_template, storage_template, userdata, script, ova, arguments=None):
if list_profile(name, is_fuzzy=False)[-1] != 200:
retmsg = {'message': 'The profile "{}" does not exist.'.format(name)}
@ -1004,6 +1039,7 @@ def modify_profile(name, profile_type, system_template, network_template, storag
close_database(conn, cur)
return retmsg, retcode
def delete_profile(name):
if list_profile(name, is_fuzzy=False)[-1] != 200:
retmsg = {'message': 'The profile "{}" does not exist.'.format(name)}
@ -1023,6 +1059,7 @@ def delete_profile(name):
close_database(conn, cur)
return retmsg, retcode
#
# Main VM provisioning function - executed by the Celery worker
#

View File

@ -22,24 +22,40 @@
import datetime
# ANSII colours for output
def red():
return '\033[91m'
def blue():
return '\033[94m'
def cyan():
return '\033[96m'
def green():
return '\033[92m'
def yellow():
return '\033[93m'
def purple():
return '\033[95m'
def bold():
return '\033[1m'
def end():
return '\033[0m'
# Print function
def echo(message, prefix, state):
# Get the date

View File

@ -32,7 +32,7 @@ from cli_lib.common import UploadProgressBar, call_api
# Supplemental functions
#
# Format byte sizes to/from human-readable units
# Matrix of human-to-byte values
byte_unit_matrix = {
'B': 1,
'K': 1024,
@ -41,6 +41,19 @@ byte_unit_matrix = {
'T': 1024*1024*1024*1024,
'P': 1024*1024*1024*1024*1024
}
# Matrix of human-to-metric values
ops_unit_matrix = {
'': 1,
'K': 1000,
'M': 1000*1000,
'G': 1000*1000*1000,
'T': 1000*1000*1000*1000,
'P': 1000*1000*1000*1000*1000
}
# Format byte sizes to/from human-readable units
def format_bytes_tohuman(databytes):
datahuman = ''
for unit in sorted(byte_unit_matrix, key=byte_unit_matrix.get, reverse=True):
@ -55,6 +68,7 @@ def format_bytes_tohuman(databytes):
return datahuman
def format_bytes_fromhuman(datahuman):
# Trim off human-readable character
dataunit = datahuman[-1]
@ -64,14 +78,6 @@ def format_bytes_fromhuman(datahuman):
# Format ops sizes to/from human-readable units
ops_unit_matrix = {
'': 1,
'K': 1000,
'M': 1000*1000,
'G': 1000*1000*1000,
'T': 1000*1000*1000*1000,
'P': 1000*1000*1000*1000*1000
}
def format_ops_tohuman(dataops):
datahuman = ''
for unit in sorted(ops_unit_matrix, key=ops_unit_matrix.get, reverse=True):
@ -86,6 +92,7 @@ def format_ops_tohuman(dataops):
return datahuman
def format_ops_fromhuman(datahuman):
# Trim off human-readable character
dataunit = datahuman[-1]
@ -93,10 +100,12 @@ def format_ops_fromhuman(datahuman):
dataops = datasize * ops_unit_matrix[dataunit]
return '{}'.format(dataops)
def format_pct_tohuman(datapct):
datahuman = "{0:.1f}".format(float(datapct * 100.0))
return datahuman
#
# Status functions
#
@ -115,6 +124,7 @@ def ceph_status(config):
else:
return False, response.json().get('message', '')
def ceph_util(config):
"""
Get utilization of the Ceph cluster
@ -130,6 +140,7 @@ def ceph_util(config):
else:
return False, response.json().get('message', '')
def format_raw_output(status_data):
ainformation = list()
ainformation.append('{bold}Ceph cluster {stype} (primary node {end}{blue}{primary}{end}{bold}){end}\n'.format(bold=ansiprint.bold(), end=ansiprint.end(), blue=ansiprint.blue(), stype=status_data['type'], primary=status_data['primary_node']))
@ -138,6 +149,7 @@ def format_raw_output(status_data):
return '\n'.join(ainformation)
#
# OSD functions
#
@ -156,6 +168,7 @@ def ceph_osd_info(config, osd):
else:
return False, response.json().get('message', '')
def ceph_osd_list(config, limit):
"""
Get list information about Ceph OSDs (limited by {limit})
@ -175,6 +188,7 @@ def ceph_osd_list(config, limit):
else:
return False, response.json().get('message', '')
def ceph_osd_add(config, node, device, weight):
"""
Add new Ceph OSD
@ -197,6 +211,7 @@ def ceph_osd_add(config, node, device, weight):
return retstatus, response.json().get('message', '')
def ceph_osd_remove(config, osdid):
"""
Remove Ceph OSD
@ -217,6 +232,7 @@ def ceph_osd_remove(config, osdid):
return retstatus, response.json().get('message', '')
def ceph_osd_state(config, osdid, state):
"""
Set state of Ceph OSD
@ -237,6 +253,7 @@ def ceph_osd_state(config, osdid, state):
return retstatus, response.json().get('message', '')
def ceph_osd_option(config, option, action):
"""
Set cluster option of Ceph OSDs
@ -258,6 +275,7 @@ def ceph_osd_option(config, option, action):
return retstatus, response.json().get('message', '')
def getOutputColoursOSD(osd_information):
# Set the UP status
if osd_information['stats']['up'] == 1:
@ -277,6 +295,7 @@ def getOutputColoursOSD(osd_information):
return osd_up_flag, osd_up_colour, osd_in_flag, osd_in_colour
def format_list_osd(osd_list):
# Handle empty list
if not osd_list:
@ -542,6 +561,7 @@ def ceph_pool_info(config, pool):
else:
return False, response.json().get('message', '')
def ceph_pool_list(config, limit):
"""
Get list information about Ceph OSDs (limited by {limit})
@ -561,6 +581,7 @@ def ceph_pool_list(config, limit):
else:
return False, response.json().get('message', '')
def ceph_pool_add(config, pool, pgs, replcfg):
"""
Add new Ceph OSD
@ -583,6 +604,7 @@ def ceph_pool_add(config, pool, pgs, replcfg):
return retstatus, response.json().get('message', '')
def ceph_pool_remove(config, pool):
"""
Remove Ceph OSD
@ -603,6 +625,7 @@ def ceph_pool_remove(config, pool):
return retstatus, response.json().get('message', '')
def format_list_pool(pool_list):
# Handle empty list
if not pool_list:
@ -820,6 +843,7 @@ def ceph_volume_info(config, pool, volume):
else:
return False, response.json().get('message', '')
def ceph_volume_list(config, limit, pool):
"""
Get list information about Ceph volumes (limited by {limit} and by {pool})
@ -841,6 +865,7 @@ def ceph_volume_list(config, limit, pool):
else:
return False, response.json().get('message', '')
def ceph_volume_add(config, pool, volume, size):
"""
Add new Ceph volume
@ -863,6 +888,7 @@ def ceph_volume_add(config, pool, volume, size):
return retstatus, response.json().get('message', '')
def ceph_volume_upload(config, pool, volume, image_format, image_file):
"""
Upload a disk image to a Ceph volume
@ -898,6 +924,7 @@ def ceph_volume_upload(config, pool, volume, image_format, image_file):
return retstatus, response.json().get('message', '')
def ceph_volume_remove(config, pool, volume):
"""
Remove Ceph volume
@ -915,6 +942,7 @@ def ceph_volume_remove(config, pool, volume):
return retstatus, response.json().get('message', '')
def ceph_volume_modify(config, pool, volume, new_name=None, new_size=None):
"""
Modify Ceph volume
@ -939,6 +967,7 @@ def ceph_volume_modify(config, pool, volume, new_name=None, new_size=None):
return retstatus, response.json().get('message', '')
def ceph_volume_clone(config, pool, volume, new_volume):
"""
Clone Ceph volume
@ -959,6 +988,7 @@ def ceph_volume_clone(config, pool, volume, new_volume):
return retstatus, response.json().get('message', '')
def format_list_volume(volume_list):
# Handle empty list
if not volume_list:
@ -1092,6 +1122,7 @@ def ceph_snapshot_info(config, pool, volume, snapshot):
else:
return False, response.json().get('message', '')
def ceph_snapshot_list(config, limit, volume, pool):
"""
Get list information about Ceph snapshots (limited by {limit}, by {pool}, or by {volume})
@ -1115,6 +1146,7 @@ def ceph_snapshot_list(config, limit, volume, pool):
else:
return False, response.json().get('message', '')
def ceph_snapshot_add(config, pool, volume, snapshot):
"""
Add new Ceph snapshot
@ -1137,6 +1169,7 @@ def ceph_snapshot_add(config, pool, volume, snapshot):
return retstatus, response.json().get('message', '')
def ceph_snapshot_remove(config, pool, volume, snapshot):
"""
Remove Ceph snapshot
@ -1154,6 +1187,7 @@ def ceph_snapshot_remove(config, pool, volume, snapshot):
return retstatus, response.json().get('message', '')
def ceph_snapshot_modify(config, pool, volume, snapshot, new_name=None):
"""
Modify Ceph snapshot
@ -1176,6 +1210,7 @@ def ceph_snapshot_modify(config, pool, volume, snapshot, new_name=None):
return retstatus, response.json().get('message', '')
def format_list_snapshot(snapshot_list):
# Handle empty list
if not snapshot_list:
@ -1249,6 +1284,7 @@ def format_list_snapshot(snapshot_list):
return '\n'.join(sorted(snapshot_list_output))
#
# Benchmark functions
#
@ -1274,6 +1310,7 @@ def ceph_benchmark_run(config, pool):
return retvalue, retdata
def ceph_benchmark_list(config, job):
"""
View results of one or more previous benchmark runs
@ -1300,6 +1337,7 @@ def ceph_benchmark_list(config, job):
return retvalue, retdata
def format_list_benchmark(config, benchmark_information):
benchmark_list_output = []
@ -1420,6 +1458,7 @@ def format_list_benchmark(config, benchmark_information):
return '\n'.join(benchmark_list_output)
def format_info_benchmark(config, benchmark_information):
if benchmark_information[0]['benchmark_result'] == "Running":
return "Benchmark test is still running."

View File

@ -25,6 +25,7 @@ import json
import cli_lib.ansiprint as ansiprint
from cli_lib.common import call_api
def initialize(config):
"""
Initialize the PVC cluster
@ -42,6 +43,7 @@ def initialize(config):
return retstatus, response.json().get('message', '')
def maintenance_mode(config, state):
"""
Enable or disable PVC cluster maintenance mode
@ -62,6 +64,7 @@ def maintenance_mode(config, state):
return retstatus, response.json().get('message', '')
def get_info(config):
"""
Get status of the PVC cluster
@ -77,6 +80,7 @@ def get_info(config):
else:
return False, response.json().get('message', '')
def format_info(cluster_information, oformat):
if oformat == 'json':
return json.dumps(cluster_information)

View File

@ -27,6 +27,7 @@ import requests
import click
from urllib3 import disable_warnings
def format_bytes(size_bytes):
byte_unit_matrix = {
'B': 1,
@ -44,6 +45,7 @@ def format_bytes(size_bytes):
break
return human_bytes
def format_metric(integer):
integer_unit_matrix = {
'': 1,
@ -61,6 +63,7 @@ def format_metric(integer):
break
return human_integer
class UploadProgressBar(object):
def __init__(self, filename, end_message='', end_nl=True):
file_size = os.path.getsize(filename)
@ -103,6 +106,7 @@ class UploadProgressBar(object):
if self.end_message:
click.echo(self.end_message + self.end_suffix, nl=self.end_nl)
class ErrorResponse(requests.Response):
def __init__(self, json_data, status_code):
self.json_data = json_data
@ -111,6 +115,7 @@ class ErrorResponse(requests.Response):
def json(self):
return self.json_data
def call_api(config, operation, request_uri, headers={}, params=None, data=None, files=None):
# Craft the URI
uri = '{}://{}{}{}'.format(

View File

@ -24,6 +24,7 @@ import re
import cli_lib.ansiprint as ansiprint
from cli_lib.common import call_api
def isValidMAC(macaddr):
allowed = re.compile(r"""
(
@ -37,6 +38,7 @@ def isValidMAC(macaddr):
else:
return False
def isValidIP(ipaddr):
ip4_blocks = str(ipaddr).split(".")
if len(ip4_blocks) == 4:
@ -50,6 +52,7 @@ def isValidIP(ipaddr):
return True
return False
#
# Primary functions
#
@ -68,6 +71,7 @@ def net_info(config, net):
else:
return False, response.json().get('message', '')
def net_list(config, limit):
"""
Get list information about networks (limited by {limit})
@ -87,6 +91,7 @@ def net_list(config, limit):
else:
return False, response.json().get('message', '')
def net_add(config, vni, description, nettype, domain, name_servers, ip4_network, ip4_gateway, ip6_network, ip6_gateway, dhcp4_flag, dhcp4_start, dhcp4_end):
"""
Add new network
@ -118,6 +123,7 @@ def net_add(config, vni, description, nettype, domain, name_servers, ip4_network
return retstatus, response.json().get('message', '')
def net_modify(config, net, description, domain, name_servers, ip4_network, ip4_gateway, ip6_network, ip6_gateway, dhcp4_flag, dhcp4_start, dhcp4_end):
"""
Modify a network
@ -157,6 +163,7 @@ def net_modify(config, net, description, domain, name_servers, ip4_network, ip4_
return retstatus, response.json().get('message', '')
def net_remove(config, net):
"""
Remove a network
@ -174,6 +181,7 @@ def net_remove(config, net):
return retstatus, response.json().get('message', '')
#
# DHCP lease functions
#
@ -192,6 +200,7 @@ def net_dhcp_info(config, net, mac):
else:
return False, response.json().get('message', '')
def net_dhcp_list(config, net, limit, only_static=False):
"""
Get list information about leases (limited by {limit})
@ -216,6 +225,7 @@ def net_dhcp_list(config, net, limit, only_static=False):
else:
return False, response.json().get('message', '')
def net_dhcp_add(config, net, ipaddr, macaddr, hostname):
"""
Add new network DHCP lease
@ -238,6 +248,7 @@ def net_dhcp_add(config, net, ipaddr, macaddr, hostname):
return retstatus, response.json().get('message', '')
def net_dhcp_remove(config, net, mac):
"""
Remove a network DHCP lease
@ -255,6 +266,7 @@ def net_dhcp_remove(config, net, mac):
return retstatus, response.json().get('message', '')
#
# ACL functions
#
@ -273,6 +285,7 @@ def net_acl_info(config, net, description):
else:
return False, response.json().get('message', '')
def net_acl_list(config, net, limit, direction):
"""
Get list information about ACLs (limited by {limit})
@ -294,6 +307,7 @@ def net_acl_list(config, net, limit, direction):
else:
return False, response.json().get('message', '')
def net_acl_add(config, net, direction, description, rule, order):
"""
Add new network acl
@ -318,7 +332,9 @@ def net_acl_add(config, net, direction, description, rule, order):
return retstatus, response.json().get('message', '')
def net_acl_remove(config, net, description):
"""
Remove a network ACL
@ -360,6 +376,7 @@ def getOutputColours(network_information):
return v6_flag_colour, v4_flag_colour, dhcp6_flag_colour, dhcp4_flag_colour
def format_info(config, network_information, long_output):
if not network_information:
return "No network found"
@ -418,6 +435,7 @@ def format_info(config, network_information, long_output):
# Join it all together
return '\n'.join(ainformation)
def format_list(config, network_list):
if not network_list:
return "No network found"
@ -534,6 +552,7 @@ def format_list(config, network_list):
return '\n'.join(sorted(network_list_output))
def format_list_dhcp(dhcp_lease_list):
dhcp_lease_list_output = []
@ -598,6 +617,7 @@ def format_list_dhcp(dhcp_lease_list):
return '\n'.join(sorted(dhcp_lease_list_output))
def format_list_acl(acl_list):
# Handle when we get an empty entry
if not acl_list:

View File

@ -23,6 +23,7 @@
import cli_lib.ansiprint as ansiprint
from cli_lib.common import call_api
#
# Primary functions
#
@ -46,6 +47,7 @@ def node_coordinator_state(config, node, action):
return retstatus, response.json().get('message', '')
def node_domain_state(config, node, action, wait):
"""
Set node domain state state (flush/ready)
@ -67,6 +69,7 @@ def node_domain_state(config, node, action, wait):
return retstatus, response.json().get('message', '')
def node_info(config, node):
"""
Get information about node
@ -82,6 +85,7 @@ def node_info(config, node):
else:
return False, response.json().get('message', '')
def node_list(config, limit, target_daemon_state, target_coordinator_state, target_domain_state):
"""
Get list information about nodes (limited by {limit})
@ -107,6 +111,7 @@ def node_list(config, limit, target_daemon_state, target_coordinator_state, targ
else:
return False, response.json().get('message', '')
#
# Output display functions
#
@ -148,6 +153,7 @@ def getOutputColours(node_information):
return daemon_state_colour, coordinator_state_colour, domain_state_colour, mem_allocated_colour, mem_provisioned_colour
def format_info(node_information, long_output):
daemon_state_colour, coordinator_state_colour, domain_state_colour, mem_allocated_colour, mem_provisioned_colour = getOutputColours(node_information)
@ -178,6 +184,7 @@ def format_info(node_information, long_output):
ainformation.append('')
return '\n'.join(ainformation)
def format_list(node_list, raw):
# Handle single-element lists
if not isinstance(node_list, list):

View File

@ -27,6 +27,7 @@ from requests_toolbelt.multipart.encoder import MultipartEncoder, MultipartEncod
import cli_lib.ansiprint as ansiprint
from cli_lib.common import UploadProgressBar, call_api
#
# Primary functions
#
@ -45,6 +46,7 @@ def template_info(config, template, template_type):
else:
return False, response.json().get('message', '')
def template_list(config, limit, template_type=None):
"""
Get list information about templates (limited by {limit})
@ -67,6 +69,7 @@ def template_list(config, limit, template_type=None):
else:
return False, response.json().get('message', '')
def template_add(config, params, template_type=None):
"""
Add a new template of {template_type} with {params}
@ -84,6 +87,7 @@ def template_add(config, params, template_type=None):
return retvalue, response.json().get('message', '')
def template_modify(config, params, name, template_type):
"""
Modify an existing template of {template_type} with {params}
@ -101,6 +105,7 @@ def template_modify(config, params, name, template_type):
return retvalue, response.json().get('message', '')
def template_remove(config, name, template_type):
"""
Remove template {name} of {template_type}
@ -118,6 +123,7 @@ def template_remove(config, name, template_type):
return retvalue, response.json().get('message', '')
def template_element_add(config, name, element_id, params, element_type=None, template_type=None):
"""
Add a new template element of {element_type} with {params} to template {name} of {template_type}
@ -135,6 +141,7 @@ def template_element_add(config, name, element_id, params, element_type=None, te
return retvalue, response.json().get('message', '')
def template_element_remove(config, name, element_id, element_type=None, template_type=None):
"""
Remove template element {element_id} of {element_type} from template {name} of {template_type}
@ -152,6 +159,7 @@ def template_element_remove(config, name, element_id, element_type=None, templat
return retvalue, response.json().get('message', '')
def userdata_info(config, userdata):
"""
Get information about userdata
@ -167,6 +175,7 @@ def userdata_info(config, userdata):
else:
return False, response.json().get('message', '')
def userdata_list(config, limit):
"""
Get list information about userdatas (limited by {limit})
@ -186,6 +195,7 @@ def userdata_list(config, limit):
else:
return False, response.json().get('message', '')
def userdata_show(config, name):
"""
Get information about userdata name
@ -201,6 +211,7 @@ def userdata_show(config, name):
else:
return False, response.json().get('message', '')
def userdata_add(config, params):
"""
Add a new userdata with {params}
@ -227,6 +238,7 @@ def userdata_add(config, params):
return retvalue, response.json().get('message', '')
def userdata_modify(config, name, params):
"""
Modify userdata {name} with {params}
@ -252,6 +264,7 @@ def userdata_modify(config, name, params):
return retvalue, response.json().get('message', '')
def userdata_remove(config, name):
"""
Remove userdata {name}
@ -269,6 +282,7 @@ def userdata_remove(config, name):
return retvalue, response.json().get('message', '')
def script_info(config, script):
"""
Get information about script
@ -284,6 +298,7 @@ def script_info(config, script):
else:
return False, response.json().get('message', '')
def script_list(config, limit):
"""
Get list information about scripts (limited by {limit})
@ -303,6 +318,7 @@ def script_list(config, limit):
else:
return False, response.json().get('message', '')
def script_show(config, name):
"""
Get information about script name
@ -318,6 +334,7 @@ def script_show(config, name):
else:
return False, response.json().get('message', '')
def script_add(config, params):
"""
Add a new script with {params}
@ -344,6 +361,7 @@ def script_add(config, params):
return retvalue, response.json().get('message', '')
def script_modify(config, name, params):
"""
Modify script {name} with {params}
@ -369,6 +387,7 @@ def script_modify(config, name, params):
return retvalue, response.json().get('message', '')
def script_remove(config, name):
"""
Remove script {name}
@ -386,6 +405,7 @@ def script_remove(config, name):
return retvalue, response.json().get('message', '')
def ova_info(config, name):
"""
Get information about OVA image {name}
@ -401,6 +421,7 @@ def ova_info(config, name):
else:
return False, response.json().get('message', '')
def ova_list(config, limit):
"""
Get list information about OVA images (limited by {limit})
@ -420,6 +441,7 @@ def ova_list(config, limit):
else:
return False, response.json().get('message', '')
def ova_upload(config, name, ova_file, params):
"""
Upload an OVA image to the cluster
@ -452,6 +474,7 @@ def ova_upload(config, name, ova_file, params):
return retstatus, response.json().get('message', '')
def ova_remove(config, name):
"""
Remove OVA image {name}
@ -469,6 +492,7 @@ def ova_remove(config, name):
return retvalue, response.json().get('message', '')
def profile_info(config, profile):
"""
Get information about profile
@ -484,6 +508,7 @@ def profile_info(config, profile):
else:
return False, response.json().get('message', '')
def profile_list(config, limit):
"""
Get list information about profiles (limited by {limit})
@ -503,6 +528,7 @@ def profile_list(config, limit):
else:
return False, response.json().get('message', '')
def profile_add(config, params):
"""
Add a new profile with {params}
@ -520,6 +546,7 @@ def profile_add(config, params):
return retvalue, response.json().get('message', '')
def profile_modify(config, name, params):
"""
Modify profile {name} with {params}
@ -537,6 +564,7 @@ def profile_modify(config, name, params):
return retvalue, response.json().get('message', '')
def profile_remove(config, name):
"""
Remove profile {name}
@ -554,6 +582,7 @@ def profile_remove(config, name):
return retvalue, response.json().get('message', '')
def vm_create(config, name, profile, wait_flag, define_flag, start_flag, script_args):
"""
Create a new VM named {name} with profile {profile}
@ -584,6 +613,7 @@ def vm_create(config, name, profile, wait_flag, define_flag, start_flag, script_
return retvalue, retdata
def task_status(config, task_id=None, is_watching=False):
"""
Get information about provisioner job {task_id} or all tasks if None
@ -658,6 +688,7 @@ def task_status(config, task_id=None, is_watching=False):
return retvalue, retdata
#
# Format functions
#
@ -700,6 +731,7 @@ def format_list_template(template_data, template_type=None):
return '\n'.join(ainformation)
def format_list_template_system(template_data):
if isinstance(template_data, dict):
template_data = [template_data]
@ -848,6 +880,7 @@ Meta: {template_node_limit: <{template_node_limit_length}} \
return True, ''
def format_list_template_network(template_template):
if isinstance(template_template, dict):
template_template = [template_template]
@ -922,6 +955,7 @@ def format_list_template_network(template_template):
return '\n'.join([template_list_output_header] + template_list_output)
def format_list_template_storage(template_template):
if isinstance(template_template, dict):
template_template = [template_template]
@ -1057,6 +1091,7 @@ def format_list_template_storage(template_template):
return '\n'.join([template_list_output_header] + template_list_output)
def format_list_userdata(userdata_data, lines=None):
if isinstance(userdata_data, dict):
userdata_data = [userdata_data]
@ -1131,6 +1166,7 @@ def format_list_userdata(userdata_data, lines=None):
return '\n'.join([userdata_list_output_header] + userdata_list_output)
def format_list_script(script_data, lines=None):
if isinstance(script_data, dict):
script_data = [script_data]
@ -1205,6 +1241,7 @@ def format_list_script(script_data, lines=None):
return '\n'.join([script_list_output_header] + script_list_output)
def format_list_ova(ova_data):
if isinstance(ova_data, dict):
ova_data = [ova_data]
@ -1318,6 +1355,7 @@ def format_list_ova(ova_data):
return '\n'.join([ova_list_output_header] + ova_list_output)
def format_list_profile(profile_data):
if isinstance(profile_data, dict):
profile_data = [profile_data]
@ -1442,6 +1480,7 @@ Data: {profile_userdata: <{profile_userdata_length}} \
return '\n'.join([profile_list_output_header] + profile_list_output)
def format_list_task(task_data):
task_list_output = []

View File

@ -26,6 +26,7 @@ import re
import cli_lib.ansiprint as ansiprint
from cli_lib.common import call_api, format_bytes, format_metric
#
# Primary functions
#
@ -53,6 +54,7 @@ def vm_info(config, vm):
else:
return False, response.json().get('message', '')
def vm_list(config, limit, target_node, target_state):
"""
Get list information about VMs (limited by {limit}, {target_node}, or {target_state})
@ -76,6 +78,7 @@ def vm_list(config, limit, target_node, target_state):
else:
return False, response.json().get('message', '')
def vm_define(config, xml, node, node_limit, node_selector, node_autostart, migration_method):
"""
Define a new VM on the cluster
@ -103,6 +106,7 @@ def vm_define(config, xml, node, node_limit, node_selector, node_autostart, migr
return retstatus, response.json().get('message', '')
def vm_modify(config, vm, xml, restart):
"""
Modify the configuration of VM
@ -126,6 +130,7 @@ def vm_modify(config, vm, xml, restart):
return retstatus, response.json().get('message', '')
def vm_metadata(config, vm, node_limit, node_selector, node_autostart, migration_method, provisioner_profile):
"""
Modify PVC metadata of a VM
@ -162,6 +167,7 @@ def vm_metadata(config, vm, node_limit, node_selector, node_autostart, migration
return retstatus, response.json().get('message', '')
def vm_remove(config, vm, delete_disks=False):
"""
Remove a VM
@ -182,6 +188,7 @@ def vm_remove(config, vm, delete_disks=False):
return retstatus, response.json().get('message', '')
def vm_state(config, vm, target_state, wait=False):
"""
Modify the current state of VM
@ -203,6 +210,7 @@ def vm_state(config, vm, target_state, wait=False):
return retstatus, response.json().get('message', '')
def vm_node(config, vm, target_node, action, force=False, wait=False, force_live=False):
"""
Modify the current node of VM via {action}
@ -227,6 +235,7 @@ def vm_node(config, vm, target_node, action, force=False, wait=False, force_live
return retstatus, response.json().get('message', '')
def vm_locks(config, vm):
"""
Flush RBD locks of (stopped) VM
@ -244,6 +253,7 @@ def vm_locks(config, vm):
return retstatus, response.json().get('message', '')
def view_console_log(config, vm, lines=100):
"""
Return console log lines from the API (and display them in a pager in the main CLI)
@ -268,6 +278,7 @@ def view_console_log(config, vm, lines=100):
return True, loglines
def follow_console_log(config, vm, lines=10):
"""
Return and follow console log lines from the API
@ -323,6 +334,7 @@ def follow_console_log(config, vm, lines=10):
return True, ''
#
# Output display functions
#
@ -478,6 +490,7 @@ def format_info(config, domain_information, long_output):
ainformation.append('')
return '\n'.join(ainformation)
def format_list(config, vm_list, raw):
# Handle single-element lists
if not isinstance(vm_list, list):

View File

@ -22,6 +22,7 @@
import uuid
# Exists function
def exists(zk_conn, key):
stat = zk_conn.exists(key)
@ -30,21 +31,25 @@ def exists(zk_conn, key):
else:
return False
# Child list function
def listchildren(zk_conn, key):
children = zk_conn.get_children(key)
return children
# Delete key function
def deletekey(zk_conn, key, recursive=True):
zk_conn.delete(key, recursive=recursive)
# Data read function
def readdata(zk_conn, key):
data_raw = zk_conn.get(key)
data = data_raw[0].decode('utf8')
return data
# Data write function
def writedata(zk_conn, kv):
# Start up a transaction
@ -83,12 +88,14 @@ def writedata(zk_conn, kv):
except Exception:
return False
# Write lock function
def writelock(zk_conn, key):
lock_id = str(uuid.uuid1())
lock = zk_conn.WriteLock('{}'.format(key), lock_id)
return lock
# Read lock function
def readlock(zk_conn, key):
lock_id = str(uuid.uuid1())

View File

@ -50,6 +50,7 @@ default_store_data = {
'cfgfile': '/etc/pvc/pvcapid.yaml' # pvc/api/listen_address, pvc/api/listen_port
}
#
# Data store handling functions
#
@ -69,6 +70,7 @@ def read_from_yaml(cfgfile):
api_key = 'N/A'
return host, port, scheme, api_key
def get_config(store_data, cluster=None):
# This is generally static
prefix = '/api/v1'
@ -110,12 +112,14 @@ def get_config(store_data, cluster=None):
return config
def get_store(store_path):
store_file = '{}/pvc-cli.json'.format(store_path)
with open(store_file, 'r') as fh:
store_data = json.loads(fh.read())
return store_data
def update_store(store_path, store_data):
store_file = '{}/pvc-cli.json'.format(store_path)
if not os.path.exists(store_file):
@ -145,6 +149,7 @@ if not os.path.isfile(store_path + '/pvc-cli.json'):
CONTEXT_SETTINGS = dict(help_option_names=['-h', '--help'], max_content_width=120)
def cleanup(retcode, retmsg):
if retcode is True:
if retmsg != '':
@ -155,6 +160,7 @@ def cleanup(retcode, retmsg):
click.echo(retmsg)
exit(1)
###############################################################################
# pvc cluster
###############################################################################
@ -165,6 +171,7 @@ def cli_cluster():
"""
pass
###############################################################################
# pvc cluster add
###############################################################################
@ -210,6 +217,7 @@ def cluster_add(address, port, ssl, name, api_key):
update_store(store_path, existing_config)
click.echo('Added new cluster "{}" at host "{}" to local database'.format(name, address))
###############################################################################
# pvc cluster remove
###############################################################################
@ -232,6 +240,7 @@ def cluster_remove(name):
update_store(store_path, existing_config)
click.echo('Removed cluster "{}" from local database'.format(name))
###############################################################################
# pvc cluster list
###############################################################################
@ -338,6 +347,7 @@ def cluster_list():
)
)
# Validate that the cluster is set for a given command
def cluster_req(function):
@wraps(function)
@ -357,6 +367,8 @@ def cli_node():
"""
Manage the state of a node in the PVC cluster.
"""
pass
###############################################################################
# pvc node secondary
@ -402,6 +414,7 @@ def node_secondary(node, wait):
time.sleep(0.5)
cleanup(retcode, retmsg)
###############################################################################
# pvc node primary
###############################################################################
@ -446,6 +459,7 @@ def node_primary(node, wait):
time.sleep(0.5)
cleanup(retcode, retmsg)
###############################################################################
# pvc node flush
###############################################################################
@ -466,6 +480,7 @@ def node_flush(node, wait):
retcode, retmsg = pvc_node.node_domain_state(config, node, 'flush', wait)
cleanup(retcode, retmsg)
###############################################################################
# pvc node ready/unflush
###############################################################################
@ -486,6 +501,7 @@ def node_ready(node, wait):
retcode, retmsg = pvc_node.node_domain_state(config, node, 'ready', wait)
cleanup(retcode, retmsg)
@click.command(name='unflush', short_help='Restore node to service.')
@click.argument(
'node', default=myhostname
@ -502,6 +518,7 @@ def node_unflush(node, wait):
retcode, retmsg = pvc_node.node_domain_state(config, node, 'ready', wait)
cleanup(retcode, retmsg)
###############################################################################
# pvc node info
###############################################################################
@ -524,6 +541,7 @@ def node_info(node, long_output):
retdata = pvc_node.format_info(retdata, long_output)
cleanup(retcode, retdata)
###############################################################################
# pvc node list
###############################################################################
@ -561,6 +579,7 @@ def node_list(limit, target_daemon_state, target_coordinator_state, target_domai
retdata = ""
cleanup(retcode, retdata)
###############################################################################
# pvc vm
###############################################################################
@ -569,6 +588,8 @@ def cli_vm():
"""
Manage the state of a virtual machine in the PVC cluster.
"""
pass
###############################################################################
# pvc vm define
@ -619,6 +640,7 @@ def vm_define(vmconfig, target_node, node_limit, node_selector, node_autostart,
retcode, retmsg = pvc_vm.vm_define(config, new_cfg, target_node, node_limit, node_selector, node_autostart, migration_method)
cleanup(retcode, retmsg)
###############################################################################
# pvc vm meta
###############################################################################
@ -660,6 +682,7 @@ def vm_meta(domain, node_limit, node_selector, node_autostart, migration_method,
retcode, retmsg = pvc_vm.vm_metadata(config, domain, node_limit, node_selector, node_autostart, migration_method, provisioner_profile)
cleanup(retcode, retmsg)
###############################################################################
# pvc vm modify
###############################################################################
@ -748,6 +771,7 @@ def vm_modify(domain, cfgfile, editor, restart):
retcode, retmsg = pvc_vm.vm_modify(config, domain, new_cfg, restart)
cleanup(retcode, retmsg)
###############################################################################
# pvc vm undefine
###############################################################################
@ -774,6 +798,7 @@ def vm_undefine(domain, confirm_flag):
retcode, retmsg = pvc_vm.vm_remove(config, domain, delete_disks=False)
cleanup(retcode, retmsg)
###############################################################################
# pvc vm remove
###############################################################################
@ -800,6 +825,7 @@ def vm_remove(domain, confirm_flag):
retcode, retmsg = pvc_vm.vm_remove(config, domain, delete_disks=True)
cleanup(retcode, retmsg)
###############################################################################
# pvc vm start
###############################################################################
@ -816,6 +842,7 @@ def vm_start(domain):
retcode, retmsg = pvc_vm.vm_state(config, domain, 'start')
cleanup(retcode, retmsg)
###############################################################################
# pvc vm restart
###############################################################################
@ -836,6 +863,7 @@ def vm_restart(domain, wait):
retcode, retmsg = pvc_vm.vm_state(config, domain, 'restart', wait=wait)
cleanup(retcode, retmsg)
###############################################################################
# pvc vm shutdown
###############################################################################
@ -856,6 +884,7 @@ def vm_shutdown(domain, wait):
retcode, retmsg = pvc_vm.vm_state(config, domain, 'shutdown', wait=wait)
cleanup(retcode, retmsg)
###############################################################################
# pvc vm stop
###############################################################################
@ -872,6 +901,7 @@ def vm_stop(domain):
retcode, retmsg = pvc_vm.vm_state(config, domain, 'stop')
cleanup(retcode, retmsg)
###############################################################################
# pvc vm disable
###############################################################################
@ -890,6 +920,7 @@ def vm_disable(domain):
retcode, retmsg = pvc_vm.vm_state(config, domain, 'disable')
cleanup(retcode, retmsg)
###############################################################################
# pvc vm move
###############################################################################
@ -918,6 +949,7 @@ def vm_move(domain, target_node, wait, force_live):
retcode, retmsg = pvc_vm.vm_node(config, domain, target_node, 'move', force=False, wait=wait, force_live=force_live)
cleanup(retcode, retmsg)
###############################################################################
# pvc vm migrate
###############################################################################
@ -950,6 +982,7 @@ def vm_migrate(domain, target_node, force_migrate, wait, force_live):
retcode, retmsg = pvc_vm.vm_node(config, domain, target_node, 'migrate', force=force_migrate, wait=wait, force_live=force_live)
cleanup(retcode, retmsg)
###############################################################################
# pvc vm unmigrate
###############################################################################
@ -974,6 +1007,7 @@ def vm_unmigrate(domain, wait, force_live):
retcode, retmsg = pvc_vm.vm_node(config, domain, None, 'unmigrate', force=False, wait=wait, force_live=force_live)
cleanup(retcode, retmsg)
###############################################################################
# pvc vm flush-locks
###############################################################################
@ -990,6 +1024,7 @@ def vm_flush_locks(domain):
retcode, retmsg = pvc_vm.vm_locks(config, domain)
cleanup(retcode, retmsg)
###############################################################################
# pvc vm log
###############################################################################
@ -1026,6 +1061,7 @@ def vm_log(domain, lines, follow):
retmsg = ''
cleanup(retcode, retmsg)
###############################################################################
# pvc vm info
###############################################################################
@ -1048,6 +1084,7 @@ def vm_info(domain, long_output):
retdata = pvc_vm.format_info(config, retdata, long_output)
cleanup(retcode, retdata)
###############################################################################
# pvc vm dump
###############################################################################
@ -1071,6 +1108,7 @@ def vm_dump(domain):
current_vm_cfgfile = etree.tostring(xml_data, pretty_print=True).decode('utf8')
click.echo(current_vm_cfgfile.strip())
###############################################################################
# pvc vm list
###############################################################################
@ -1106,6 +1144,7 @@ def vm_list(target_node, target_state, limit, raw):
retdata = ""
cleanup(retcode, retdata)
###############################################################################
# pvc network
###############################################################################
@ -1114,6 +1153,8 @@ def cli_network():
"""
Manage the state of a VXLAN network in the PVC cluster.
"""
pass
###############################################################################
# pvc network add
@ -1200,6 +1241,7 @@ def net_add(vni, description, nettype, domain, ip_network, ip_gateway, ip6_netwo
retcode, retmsg = pvc_network.net_add(config, vni, description, nettype, domain, name_servers, ip_network, ip_gateway, ip6_network, ip6_gateway, dhcp_flag, dhcp_start, dhcp_end)
cleanup(retcode, retmsg)
###############################################################################
# pvc network modify
###############################################################################
@ -1270,6 +1312,7 @@ def net_modify(vni, description, domain, name_servers, ip6_network, ip6_gateway,
retcode, retmsg = pvc_network.net_modify(config, vni, description, domain, name_servers, ip4_network, ip4_gateway, ip6_network, ip6_gateway, dhcp_flag, dhcp_start, dhcp_end)
cleanup(retcode, retmsg)
###############################################################################
# pvc network remove
###############################################################################
@ -1299,6 +1342,7 @@ def net_remove(net, confirm_flag):
retcode, retmsg = pvc_network.net_remove(config, net)
cleanup(retcode, retmsg)
###############################################################################
# pvc network info
###############################################################################
@ -1321,6 +1365,7 @@ def net_info(vni, long_output):
retdata = pvc_network.format_info(config, retdata, long_output)
cleanup(retcode, retdata)
###############################################################################
# pvc network list
###############################################################################
@ -1339,6 +1384,7 @@ def net_list(limit):
retdata = pvc_network.format_list(config, retdata)
cleanup(retcode, retdata)
###############################################################################
# pvc network dhcp
###############################################################################
@ -1347,6 +1393,8 @@ def net_dhcp():
"""
Manage host IPv4 DHCP leases of a VXLAN network in the PVC cluster.
"""
pass
###############################################################################
# pvc network dhcp add
@ -1373,6 +1421,7 @@ def net_dhcp_add(net, ipaddr, macaddr, hostname):
retcode, retmsg = pvc_network.net_dhcp_add(config, net, ipaddr, macaddr, hostname)
cleanup(retcode, retmsg)
###############################################################################
# pvc network dhcp remove
###############################################################################
@ -1402,6 +1451,7 @@ def net_dhcp_remove(net, macaddr, confirm_flag):
retcode, retmsg = pvc_network.net_dhcp_remove(config, net, macaddr)
cleanup(retcode, retmsg)
###############################################################################
# pvc network dhcp list
###############################################################################
@ -1427,6 +1477,7 @@ def net_dhcp_list(net, limit, only_static):
retdata = pvc_network.format_list_dhcp(retdata)
cleanup(retcode, retdata)
###############################################################################
# pvc network acl
###############################################################################
@ -1435,6 +1486,8 @@ def net_acl():
"""
Manage firewall ACLs of a VXLAN network in the PVC cluster.
"""
pass
###############################################################################
# pvc network acl add
@ -1487,6 +1540,7 @@ def net_acl_add(net, direction, description, rule, order):
retcode, retmsg = pvc_network.net_acl_add(config, net, direction, description, rule, order)
cleanup(retcode, retmsg)
###############################################################################
# pvc network acl remove
###############################################################################
@ -1550,6 +1604,7 @@ def net_acl_list(net, limit, direction):
retdata = pvc_network.format_list_acl(retdata)
cleanup(retcode, retdata)
###############################################################################
# pvc storage
###############################################################################
@ -1563,6 +1618,8 @@ def cli_storage():
"""
Manage the storage of the PVC cluster.
"""
pass
###############################################################################
# pvc storage status
@ -1579,6 +1636,7 @@ def ceph_status():
retdata = pvc_ceph.format_raw_output(retdata)
cleanup(retcode, retdata)
###############################################################################
# pvc storage util
###############################################################################
@ -1594,6 +1652,7 @@ def ceph_util():
retdata = pvc_ceph.format_raw_output(retdata)
cleanup(retcode, retdata)
###############################################################################
# pvc storage benchmark
###############################################################################
@ -1603,6 +1662,8 @@ def ceph_benchmark():
"""
Run or view benchmarks of the storage cluster.
"""
pass
###############################################################################
# pvc storage benchmark run
@ -1624,6 +1685,7 @@ def ceph_benchmark_run(pool):
retcode, retmsg = pvc_ceph.ceph_benchmark_run(config, pool)
cleanup(retcode, retmsg)
###############################################################################
# pvc storage benchmark info
###############################################################################
@ -1642,6 +1704,7 @@ def ceph_benchmark_info(job):
retdata = pvc_ceph.format_info_benchmark(config, retdata)
cleanup(retcode, retdata)
###############################################################################
# pvc storage benchmark list
###############################################################################
@ -1660,6 +1723,7 @@ def ceph_benchmark_list(job):
retdata = pvc_ceph.format_list_benchmark(config, retdata)
cleanup(retcode, retdata)
###############################################################################
# pvc storage osd
###############################################################################
@ -1668,6 +1732,8 @@ def ceph_osd():
"""
Manage the Ceph OSDs of the PVC cluster.
"""
pass
###############################################################################
# pvc storage osd add
@ -1703,6 +1769,7 @@ def ceph_osd_add(node, device, weight, confirm_flag):
retcode, retmsg = pvc_ceph.ceph_osd_add(config, node, device, weight)
cleanup(retcode, retmsg)
###############################################################################
# pvc storage osd remove
###############################################################################
@ -1731,6 +1798,7 @@ def ceph_osd_remove(osdid, confirm_flag):
retcode, retmsg = pvc_ceph.ceph_osd_remove(config, osdid)
cleanup(retcode, retmsg)
###############################################################################
# pvc storage osd in
###############################################################################
@ -1747,6 +1815,7 @@ def ceph_osd_in(osdid):
retcode, retmsg = pvc_ceph.ceph_osd_state(config, osdid, 'in')
cleanup(retcode, retmsg)
###############################################################################
# pvc storage osd out
###############################################################################
@ -1763,6 +1832,7 @@ def ceph_osd_out(osdid):
retcode, retmsg = pvc_ceph.ceph_osd_state(config, osdid, 'out')
cleanup(retcode, retmsg)
###############################################################################
# pvc storage osd set
###############################################################################
@ -1783,6 +1853,7 @@ def ceph_osd_set(osd_property):
retcode, retmsg = pvc_ceph.ceph_osd_option(config, osd_property, 'set')
cleanup(retcode, retmsg)
###############################################################################
# pvc storage osd unset
###############################################################################
@ -1803,6 +1874,7 @@ def ceph_osd_unset(osd_property):
retcode, retmsg = pvc_ceph.ceph_osd_option(config, osd_property, 'unset')
cleanup(retcode, retmsg)
###############################################################################
# pvc storage osd list
###############################################################################
@ -1821,6 +1893,7 @@ def ceph_osd_list(limit):
retdata = pvc_ceph.format_list_osd(retdata)
cleanup(retcode, retdata)
###############################################################################
# pvc storage pool
###############################################################################
@ -1829,6 +1902,8 @@ def ceph_pool():
"""
Manage the Ceph RBD pools of the PVC cluster.
"""
pass
###############################################################################
# pvc storage pool add
@ -1858,6 +1933,7 @@ def ceph_pool_add(name, pgs, replcfg):
retcode, retmsg = pvc_ceph.ceph_pool_add(config, name, pgs, replcfg)
cleanup(retcode, retmsg)
###############################################################################
# pvc storage pool remove
###############################################################################
@ -1886,6 +1962,7 @@ def ceph_pool_remove(name, confirm_flag):
retcode, retmsg = pvc_ceph.ceph_pool_remove(config, name)
cleanup(retcode, retmsg)
###############################################################################
# pvc storage pool list
###############################################################################
@ -1904,6 +1981,7 @@ def ceph_pool_list(limit):
retdata = pvc_ceph.format_list_pool(retdata)
cleanup(retcode, retdata)
###############################################################################
# pvc storage volume
###############################################################################
@ -1912,6 +1990,8 @@ def ceph_volume():
"""
Manage the Ceph RBD volumes of the PVC cluster.
"""
pass
###############################################################################
# pvc storage volume add
@ -1935,6 +2015,7 @@ def ceph_volume_add(pool, name, size):
retcode, retmsg = pvc_ceph.ceph_volume_add(config, pool, name, size)
cleanup(retcode, retmsg)
###############################################################################
# pvc storage volume upload
###############################################################################
@ -1970,6 +2051,7 @@ def ceph_volume_upload(pool, name, image_format, image_file):
retcode, retmsg = pvc_ceph.ceph_volume_upload(config, pool, name, image_format, image_file)
cleanup(retcode, retmsg)
###############################################################################
# pvc storage volume remove
###############################################################################
@ -2001,6 +2083,7 @@ def ceph_volume_remove(pool, name, confirm_flag):
retcode, retmsg = pvc_ceph.ceph_volume_remove(config, pool, name)
cleanup(retcode, retmsg)
###############################################################################
# pvc storage volume resize
###############################################################################
@ -2022,6 +2105,7 @@ def ceph_volume_resize(pool, name, size):
retcode, retmsg = pvc_ceph.ceph_volume_modify(config, pool, name, new_size=size)
cleanup(retcode, retmsg)
###############################################################################
# pvc storage volume rename
###############################################################################
@ -2043,6 +2127,7 @@ def ceph_volume_rename(pool, name, new_name):
retcode, retmsg = pvc_ceph.ceph_volume_modify(config, pool, name, new_name=new_name)
cleanup(retcode, retmsg)
###############################################################################
# pvc storage volume clone
###############################################################################
@ -2064,6 +2149,7 @@ def ceph_volume_clone(pool, name, new_name):
retcode, retmsg = pvc_ceph.ceph_volume_clone(config, pool, name, new_name)
cleanup(retcode, retmsg)
###############################################################################
# pvc storage volume list
###############################################################################
@ -2087,6 +2173,7 @@ def ceph_volume_list(limit, pool):
retdata = pvc_ceph.format_list_volume(retdata)
cleanup(retcode, retdata)
###############################################################################
# pvc storage volume snapshot
###############################################################################
@ -2095,6 +2182,8 @@ def ceph_volume_snapshot():
"""
Manage the Ceph RBD volume snapshots of the PVC cluster.
"""
pass
###############################################################################
# pvc storage volume snapshot add
@ -2118,6 +2207,7 @@ def ceph_volume_snapshot_add(pool, volume, name):
retcode, retmsg = pvc_ceph.ceph_snapshot_add(config, pool, volume, name)
cleanup(retcode, retmsg)
###############################################################################
# pvc storage volume snapshot rename
###############################################################################
@ -2142,6 +2232,7 @@ def ceph_volume_snapshot_rename(pool, volume, name, new_name):
retcode, retmsg = pvc_ceph.ceph_snapshot_modify(config, pool, volume, name, new_name=new_name)
cleanup(retcode, retmsg)
###############################################################################
# pvc storage volume snapshot remove
###############################################################################
@ -2176,6 +2267,7 @@ def ceph_volume_snapshot_remove(pool, volume, name, confirm_flag):
retcode, retmsg = pvc_ceph.ceph_snapshot_remove(config, pool, volume, name)
cleanup(retcode, retmsg)
###############################################################################
# pvc storage volume snapshot list
###############################################################################
@ -2213,6 +2305,8 @@ def cli_provisioner():
"""
Manage the PVC provisioner.
"""
pass
###############################################################################
# pvc provisioner template
@ -2222,6 +2316,7 @@ def provisioner_template():
"""
Manage the PVC provisioner template system.
"""
pass
###############################################################################
@ -2241,6 +2336,7 @@ def provisioner_template_list(limit):
retdata = pvc_provisioner.format_list_template(retdata)
cleanup(retcode, retdata)
###############################################################################
# pvc provisioner template system
###############################################################################
@ -2249,6 +2345,8 @@ def provisioner_template_system():
"""
Manage the PVC provisioner system templates.
"""
pass
###############################################################################
# pvc provisioner template system list
@ -2267,6 +2365,7 @@ def provisioner_template_system_list(limit):
retdata = pvc_provisioner.format_list_template(retdata, template_type='system')
cleanup(retcode, retdata)
###############################################################################
# pvc provisioner template system add
###############################################################################
@ -2346,6 +2445,7 @@ def provisioner_template_system_add(name, vcpus, vram, serial, vnc, vnc_bind, no
retcode, retdata = pvc_provisioner.template_add(config, params, template_type='system')
cleanup(retcode, retdata)
###############################################################################
# pvc provisioner template system modify
###############################################################################
@ -2416,6 +2516,7 @@ def provisioner_template_system_modify(name, vcpus, vram, serial, vnc, vnc_bind,
retcode, retdata = pvc_provisioner.template_modify(config, params, name, template_type='system')
cleanup(retcode, retdata)
###############################################################################
# pvc provisioner template system remove
###############################################################################
@ -2451,6 +2552,8 @@ def provisioner_template_network():
"""
Manage the PVC provisioner network templates.
"""
pass
###############################################################################
# pvc provisioner template network list
@ -2469,6 +2572,7 @@ def provisioner_template_network_list(limit):
retdata = pvc_provisioner.format_list_template(retdata, template_type='network')
cleanup(retcode, retdata)
###############################################################################
# pvc provisioner template network add
###############################################################################
@ -2519,6 +2623,7 @@ def provisioner_template_network_add(name, mac_template):
retcode, retdata = pvc_provisioner.template_add(config, params, template_type='network')
cleanup(retcode, retdata)
###############################################################################
# pvc provisioner template network remove
###############################################################################
@ -2545,6 +2650,7 @@ def provisioner_template_network_remove(name, confirm_flag):
retcode, retdata = pvc_provisioner.template_remove(config, name, template_type='network')
cleanup(retcode, retdata)
###############################################################################
# pvc provisioner template network vni
###############################################################################
@ -2553,6 +2659,8 @@ def provisioner_template_network_vni():
"""
Manage the network VNIs in PVC provisioner network templates.
"""
pass
###############################################################################
# pvc provisioner template network vni add
@ -2576,6 +2684,7 @@ def provisioner_template_network_vni_add(name, vni):
retcode, retdata = pvc_provisioner.template_element_add(config, name, vni, params, element_type='net', template_type='network')
cleanup(retcode, retdata)
###############################################################################
# pvc provisioner template network vni remove
###############################################################################
@ -2614,6 +2723,8 @@ def provisioner_template_storage():
"""
Manage the PVC provisioner storage templates.
"""
pass
###############################################################################
# pvc provisioner template storage list
@ -2632,6 +2743,7 @@ def provisioner_template_storage_list(limit):
retdata = pvc_provisioner.format_list_template(retdata, template_type='storage')
cleanup(retcode, retdata)
###############################################################################
# pvc provisioner template storage add
###############################################################################
@ -2650,6 +2762,7 @@ def provisioner_template_storage_add(name):
retcode, retdata = pvc_provisioner.template_add(config, params, template_type='storage')
cleanup(retcode, retdata)
###############################################################################
# pvc provisioner template storage remove
###############################################################################
@ -2676,6 +2789,7 @@ def provisioner_template_storage_remove(name, confirm_flag):
retcode, retdata = pvc_provisioner.template_remove(config, name, template_type='storage')
cleanup(retcode, retdata)
###############################################################################
# pvc provisioner template storage disk
###############################################################################
@ -2684,6 +2798,8 @@ def provisioner_template_storage_disk():
"""
Manage the disks in PVC provisioner storage templates.
"""
pass
###############################################################################
# pvc provisioner template storage disk add
@ -2760,6 +2876,7 @@ def provisioner_template_storage_disk_add(name, disk, pool, source_volume, size,
retcode, retdata = pvc_provisioner.template_element_add(config, name, disk, params, element_type='disk', template_type='storage')
cleanup(retcode, retdata)
###############################################################################
# pvc provisioner template storage disk remove
###############################################################################
@ -2800,6 +2917,8 @@ def provisioner_userdata():
"""
Manage userdata documents in the PVC provisioner.
"""
pass
###############################################################################
# pvc provisioner userdata list
@ -2827,6 +2946,7 @@ def provisioner_userdata_list(limit, full):
retdata = pvc_provisioner.format_list_userdata(retdata, lines)
cleanup(retcode, retdata)
###############################################################################
# pvc provisioner userdata show
###############################################################################
@ -2842,6 +2962,7 @@ def provisioner_userdata_show(name):
retcode, retdata = pvc_provisioner.userdata_show(config, name)
cleanup(retcode, retdata)
###############################################################################
# pvc provisioner userdata add
###############################################################################
@ -2874,6 +2995,7 @@ def provisioner_userdata_add(name, filename):
retcode, retmsg = pvc_provisioner.userdata_add(config, params)
cleanup(retcode, retmsg)
###############################################################################
# pvc provisioner userdata modify
###############################################################################
@ -2949,6 +3071,7 @@ def provisioner_userdata_modify(name, filename, editor):
retcode, retmsg = pvc_provisioner.userdata_modify(config, name, params)
cleanup(retcode, retmsg)
###############################################################################
# pvc provisioner userdata remove
###############################################################################
@ -2984,6 +3107,8 @@ def provisioner_script():
"""
Manage scripts in the PVC provisioner.
"""
pass
###############################################################################
# pvc provisioner script list
@ -3011,6 +3136,7 @@ def provisioner_script_list(limit, full):
retdata = pvc_provisioner.format_list_script(retdata, lines)
cleanup(retcode, retdata)
###############################################################################
# pvc provisioner script show
###############################################################################
@ -3026,6 +3152,7 @@ def provisioner_script_show(name):
retcode, retdata = pvc_provisioner.script_show(config, name)
cleanup(retcode, retdata)
###############################################################################
# pvc provisioner script add
###############################################################################
@ -3053,6 +3180,7 @@ def provisioner_script_add(name, filename):
retcode, retmsg = pvc_provisioner.script_add(config, params)
cleanup(retcode, retmsg)
###############################################################################
# pvc provisioner script modify
###############################################################################
@ -3122,6 +3250,7 @@ def provisioner_script_modify(name, filename, editor):
retcode, retmsg = pvc_provisioner.script_modify(config, name, params)
cleanup(retcode, retmsg)
###############################################################################
# pvc provisioner script remove
###############################################################################
@ -3157,6 +3286,8 @@ def provisioner_ova():
"""
Manage ovas in the PVC provisioner.
"""
pass
###############################################################################
# pvc provisioner ova list
@ -3175,6 +3306,7 @@ def provisioner_ova_list(limit):
retdata = pvc_provisioner.format_list_ova(retdata)
cleanup(retcode, retdata)
###############################################################################
# pvc provisioner ova upload
###############################################################################
@ -3214,6 +3346,7 @@ def provisioner_ova_upload(name, filename, pool):
retcode, retdata = pvc_provisioner.ova_upload(config, name, filename, params)
cleanup(retcode, retdata)
###############################################################################
# pvc provisioner ova remove
###############################################################################
@ -3249,6 +3382,8 @@ def provisioner_profile():
"""
Manage profiles in the PVC provisioner.
"""
pass
###############################################################################
# pvc provisioner profile list
@ -3267,6 +3402,7 @@ def provisioner_profile_list(limit):
retdata = pvc_provisioner.format_list_profile(retdata)
cleanup(retcode, retdata)
###############################################################################
# pvc provisioner profile add
###############################################################################
@ -3328,6 +3464,7 @@ def provisioner_profile_add(name, profile_type, system_template, network_templat
retcode, retdata = pvc_provisioner.profile_add(config, params)
cleanup(retcode, retdata)
###############################################################################
# pvc provisioner profile modify
###############################################################################
@ -3394,6 +3531,7 @@ def provisioner_profile_modify(name, system_template, network_template, storage_
retcode, retdata = pvc_provisioner.profile_modify(config, name, params)
cleanup(retcode, retdata)
###############################################################################
# pvc provisioner profile remove
###############################################################################
@ -3520,6 +3658,7 @@ def provisioner_create(name, profile, wait_flag, define_flag, start_flag, script
cleanup(retcode, retdata)
###############################################################################
# pvc provisioner status
###############################################################################
@ -3546,6 +3685,8 @@ def cli_maintenance():
"""
Manage the maintenance mode of the PVC cluster.
"""
pass
###############################################################################
# pvc maintenance on
@ -3559,6 +3700,7 @@ def maintenance_on():
retcode, retdata = pvc_cluster.maintenance_mode(config, 'true')
cleanup(retcode, retdata)
###############################################################################
# pvc maintenance off
###############################################################################
@ -3592,6 +3734,7 @@ def status_cluster(oformat):
retdata = pvc_cluster.format_info(retdata, oformat)
cleanup(retcode, retdata)
###############################################################################
# pvc init
###############################################################################
@ -3619,6 +3762,7 @@ def init_cluster(confirm_flag):
retcode, retmsg = pvc_cluster.initialize(config)
cleanup(retcode, retmsg)
###############################################################################
# pvc
###############################################################################

View File

@ -31,6 +31,7 @@ import daemon_lib.ansiprint as ansiprint
import daemon_lib.zkhandler as zkhandler
import daemon_lib.common as common
#
# Supplemental functions
#
@ -42,6 +43,7 @@ def verifyOSD(zk_conn, osd_id):
else:
return False
# Verify Pool is valid in cluster
def verifyPool(zk_conn, name):
if zkhandler.exists(zk_conn, '/ceph/pools/{}'.format(name)):
@ -49,6 +51,7 @@ def verifyPool(zk_conn, name):
else:
return False
# Verify Volume is valid in cluster
def verifyVolume(zk_conn, pool, name):
if zkhandler.exists(zk_conn, '/ceph/volumes/{}/{}'.format(pool, name)):
@ -56,6 +59,7 @@ def verifyVolume(zk_conn, pool, name):
else:
return False
# Verify Snapshot is valid in cluster
def verifySnapshot(zk_conn, pool, volume, name):
if zkhandler.exists(zk_conn, '/ceph/snapshots/{}/{}/{}'.format(pool, volume, name)):
@ -63,6 +67,7 @@ def verifySnapshot(zk_conn, pool, volume, name):
else:
return False
# Verify OSD path is valid in cluster
def verifyOSDBlock(zk_conn, node, device):
for osd in zkhandler.listchildren(zk_conn, '/ceph/osds'):
@ -73,7 +78,7 @@ def verifyOSDBlock(zk_conn, node, device):
return None
# Format byte sizes to/from human-readable units
# Matrix of human-to-byte values
byte_unit_matrix = {
'B': 1,
'K': 1024,
@ -82,6 +87,19 @@ byte_unit_matrix = {
'T': 1024*1024*1024*1024,
'P': 1024*1024*1024*1024*1024
}
# Matrix of human-to-metric values
ops_unit_matrix = {
'': 1,
'K': 1000,
'M': 1000*1000,
'G': 1000*1000*1000,
'T': 1000*1000*1000*1000,
'P': 1000*1000*1000*1000*1000
}
# Format byte sizes to/from human-readable units
def format_bytes_tohuman(databytes):
datahuman = ''
for unit in sorted(byte_unit_matrix, key=byte_unit_matrix.get, reverse=True):
@ -96,6 +114,7 @@ def format_bytes_tohuman(databytes):
return datahuman
def format_bytes_fromhuman(datahuman):
# Trim off human-readable character
dataunit = str(datahuman)[-1]
@ -108,14 +127,6 @@ def format_bytes_fromhuman(datahuman):
# Format ops sizes to/from human-readable units
ops_unit_matrix = {
'': 1,
'K': 1000,
'M': 1000*1000,
'G': 1000*1000*1000,
'T': 1000*1000*1000*1000,
'P': 1000*1000*1000*1000*1000
}
def format_ops_tohuman(dataops):
datahuman = ''
for unit in sorted(ops_unit_matrix, key=ops_unit_matrix.get, reverse=True):
@ -130,6 +141,7 @@ def format_ops_tohuman(dataops):
return datahuman
def format_ops_fromhuman(datahuman):
# Trim off human-readable character
dataunit = datahuman[-1]
@ -137,10 +149,12 @@ def format_ops_fromhuman(datahuman):
dataops = datasize * ops_unit_matrix[dataunit]
return '{}'.format(dataops)
def format_pct_tohuman(datapct):
datahuman = "{0:.1f}".format(float(datapct * 100.0))
return datahuman
#
# Status functions
#
@ -156,6 +170,7 @@ def get_status(zk_conn):
}
return True, status_data
def get_util(zk_conn):
primary_node = zkhandler.readdata(zk_conn, '/primary_node')
ceph_df = zkhandler.readdata(zk_conn, '/ceph/util').rstrip()
@ -177,6 +192,7 @@ def getClusterOSDList(zk_conn):
osd_list = zkhandler.listchildren(zk_conn, '/ceph/osds')
return osd_list
def getOSDInformation(zk_conn, osd_id):
# Parse the stats data
osd_stats_raw = zkhandler.readdata(zk_conn, '/ceph/osds/{}/stats'.format(osd_id))
@ -188,6 +204,7 @@ def getOSDInformation(zk_conn, osd_id):
}
return osd_information
def getOutputColoursOSD(osd_information):
# Set the UP status
if osd_information['stats']['up'] == 1:
@ -207,6 +224,7 @@ def getOutputColoursOSD(osd_information):
return osd_up_flag, osd_up_colour, osd_in_flag, osd_in_colour
# OSD addition and removal uses the /cmd/ceph pipe
# These actions must occur on the specific node they reference
def add_osd(zk_conn, node, device, weight):
@ -247,6 +265,7 @@ def add_osd(zk_conn, node, device, weight):
return success, message
def remove_osd(zk_conn, osd_id):
if not verifyOSD(zk_conn, osd_id):
return False, 'ERROR: No OSD with ID "{}" is present in the cluster.'.format(osd_id)
@ -279,6 +298,7 @@ def remove_osd(zk_conn, osd_id):
return success, message
def in_osd(zk_conn, osd_id):
if not verifyOSD(zk_conn, osd_id):
return False, 'ERROR: No OSD with ID "{}" is present in the cluster.'.format(osd_id)
@ -289,6 +309,7 @@ def in_osd(zk_conn, osd_id):
return True, 'Set OSD {} online.'.format(osd_id)
def out_osd(zk_conn, osd_id):
if not verifyOSD(zk_conn, osd_id):
return False, 'ERROR: No OSD with ID "{}" is present in the cluster.'.format(osd_id)
@ -299,6 +320,7 @@ def out_osd(zk_conn, osd_id):
return True, 'Set OSD {} offline.'.format(osd_id)
def set_osd(zk_conn, option):
retcode, stdout, stderr = common.run_os_command('ceph osd set {}'.format(option))
if retcode:
@ -306,6 +328,7 @@ def set_osd(zk_conn, option):
return True, 'Set OSD property "{}".'.format(option)
def unset_osd(zk_conn, option):
retcode, stdout, stderr = common.run_os_command('ceph osd unset {}'.format(option))
if retcode:
@ -313,6 +336,7 @@ def unset_osd(zk_conn, option):
return True, 'Unset OSD property "{}".'.format(option)
def get_list_osd(zk_conn, limit, is_fuzzy=True):
osd_list = []
full_osd_list = zkhandler.listchildren(zk_conn, '/ceph/osds')
@ -351,6 +375,7 @@ def getPoolInformation(zk_conn, pool):
}
return pool_information
def add_pool(zk_conn, name, pgs, replcfg):
# Prepare the copies/mincopies variables
try:
@ -393,6 +418,7 @@ def add_pool(zk_conn, name, pgs, replcfg):
return True, 'Created RBD pool "{}" with {} PGs'.format(name, pgs)
def remove_pool(zk_conn, name):
if not verifyPool(zk_conn, name):
return False, 'ERROR: No pool with name "{}" is present in the cluster.'.format(name)
@ -413,6 +439,7 @@ def remove_pool(zk_conn, name):
return True, 'Removed RBD pool "{}" and all volumes.'.format(name)
def get_list_pool(zk_conn, limit, is_fuzzy=True):
pool_list = []
full_pool_list = zkhandler.listchildren(zk_conn, '/ceph/pools')
@ -450,6 +477,7 @@ def getCephVolumes(zk_conn, pool):
return volume_list
def getVolumeInformation(zk_conn, pool, volume):
# Parse the stats data
volume_stats_raw = zkhandler.readdata(zk_conn, '/ceph/volumes/{}/{}/stats'.format(pool, volume))
@ -464,6 +492,7 @@ def getVolumeInformation(zk_conn, pool, volume):
}
return volume_information
def add_volume(zk_conn, pool, name, size):
# 1. Create the volume
retcode, stdout, stderr = common.run_os_command('rbd create --size {} --image-feature layering,exclusive-lock {}/{}'.format(size, pool, name))
@ -483,6 +512,7 @@ def add_volume(zk_conn, pool, name, size):
return True, 'Created RBD volume "{}/{}" ({}).'.format(pool, name, size)
def clone_volume(zk_conn, pool, name_src, name_new):
if not verifyVolume(zk_conn, pool, name_src):
return False, 'ERROR: No volume with name "{}" is present in pool "{}".'.format(name_src, pool)
@ -505,6 +535,7 @@ def clone_volume(zk_conn, pool, name_src, name_new):
return True, 'Cloned RBD volume "{}" to "{}" in pool "{}"'.format(name_src, name_new, pool)
def resize_volume(zk_conn, pool, name, size):
if not verifyVolume(zk_conn, pool, name):
return False, 'ERROR: No volume with name "{}" is present in pool "{}".'.format(name, pool)
@ -551,6 +582,7 @@ def resize_volume(zk_conn, pool, name, size):
return True, 'Resized RBD volume "{}" to size "{}" in pool "{}".'.format(name, size, pool)
def rename_volume(zk_conn, pool, name, new_name):
if not verifyVolume(zk_conn, pool, name):
return False, 'ERROR: No volume with name "{}" is present in pool "{}".'.format(name, pool)
@ -577,6 +609,7 @@ def rename_volume(zk_conn, pool, name, new_name):
return True, 'Renamed RBD volume "{}" to "{}" in pool "{}".'.format(name, new_name, pool)
def remove_volume(zk_conn, pool, name):
if not verifyVolume(zk_conn, pool, name):
return False, 'ERROR: No volume with name "{}" is present in pool "{}".'.format(name, pool)
@ -596,6 +629,7 @@ def remove_volume(zk_conn, pool, name):
return True, 'Removed RBD volume "{}" in pool "{}".'.format(name, pool)
def map_volume(zk_conn, pool, name):
if not verifyVolume(zk_conn, pool, name):
return False, 'ERROR: No volume with name "{}" is present in pool "{}".'.format(name, pool)
@ -614,6 +648,7 @@ def map_volume(zk_conn, pool, name):
return True, mapped_volume
def unmap_volume(zk_conn, pool, name):
if not verifyVolume(zk_conn, pool, name):
return False, 'ERROR: No volume with name "{}" is present in pool "{}".'.format(name, pool)
@ -631,6 +666,7 @@ def unmap_volume(zk_conn, pool, name):
return True, 'Unmapped RBD volume at "{}".'.format(mapped_volume)
def get_list_volume(zk_conn, pool, limit, is_fuzzy=True):
volume_list = []
if pool and not verifyPool(zk_conn, pool):
@ -665,7 +701,6 @@ def get_list_volume(zk_conn, pool, limit, is_fuzzy=True):
#
# Snapshot functions
#
def getCephSnapshots(zk_conn, pool, volume):
snapshot_list = list()
volume_list = list()
@ -683,6 +718,7 @@ def getCephSnapshots(zk_conn, pool, volume):
return snapshot_list
def add_snapshot(zk_conn, pool, volume, name):
if not verifyVolume(zk_conn, pool, volume):
return False, 'ERROR: No volume with name "{}" is present in pool "{}".'.format(volume, pool)
@ -700,6 +736,7 @@ def add_snapshot(zk_conn, pool, volume, name):
return True, 'Created RBD snapshot "{}" of volume "{}" in pool "{}".'.format(name, volume, pool)
def rename_snapshot(zk_conn, pool, volume, name, new_name):
if not verifyVolume(zk_conn, pool, volume):
return False, 'ERROR: No volume with name "{}" is present in pool "{}".'.format(volume, pool)
@ -718,6 +755,7 @@ def rename_snapshot(zk_conn, pool, volume, name, new_name):
return True, 'Renamed RBD snapshot "{}" to "{}" for volume "{}" in pool "{}".'.format(name, new_name, volume, pool)
def remove_snapshot(zk_conn, pool, volume, name):
if not verifyVolume(zk_conn, pool, volume):
return False, 'ERROR: No volume with name "{}" is present in pool "{}".'.format(volume, pool)
@ -734,6 +772,7 @@ def remove_snapshot(zk_conn, pool, volume, name):
return True, 'Removed RBD snapshot "{}" of volume "{}" in pool "{}".'.format(name, volume, pool)
def get_list_snapshot(zk_conn, pool, volume, limit, is_fuzzy=True):
snapshot_list = []
if pool and not verifyPool(zk_conn, pool):

View File

@ -29,6 +29,7 @@ import daemon_lib.node as pvc_node
import daemon_lib.network as pvc_network
import daemon_lib.ceph as pvc_ceph
def set_maintenance(zk_conn, maint_state):
try:
if maint_state == 'true':
@ -40,6 +41,7 @@ def set_maintenance(zk_conn, maint_state):
except Exception:
return False, 'Failed to set cluster maintenance state'
def getClusterInformation(zk_conn):
# Get cluster maintenance state
try:
@ -246,6 +248,7 @@ def getClusterInformation(zk_conn):
return cluster_information
def get_info(zk_conn):
# This is a thin wrapper function for naming purposes
cluster_information = getClusterInformation(zk_conn)

View File

@ -36,6 +36,7 @@ import daemon_lib.zkhandler as zkhandler
# Supplemental functions
###############################################################################
#
# Run a local OS command via shell
#
@ -64,6 +65,7 @@ def run_os_command(command_string, background=False, environment=None, timeout=N
stderr = ''
return retcode, stdout, stderr
#
# Validate a UUID
#
@ -74,6 +76,7 @@ def validateUUID(dom_uuid):
except Exception:
return False
#
# Connect and disconnect from Zookeeper
#
@ -89,10 +92,13 @@ def startZKConnection(zk_host):
exit(1)
return zk_conn
def stopZKConnection(zk_conn):
zk_conn.stop()
zk_conn.close()
return 0
#
# Parse a Domain XML object
#
@ -106,6 +112,7 @@ def getDomainXML(zk_conn, dom_uuid):
parsed_xml = lxml.objectify.fromstring(xml)
return parsed_xml
#
# Get the main details for a VM object from XML
#
@ -131,6 +138,7 @@ def getDomainMainDetails(parsed_xml):
return duuid, dname, ddescription, dmemory, dvcpu, dvcputopo
#
# Get long-format details
#
@ -143,6 +151,7 @@ def getDomainExtraDetails(parsed_xml):
return dtype, darch, dmachine, dconsole, demulator
#
# Get CPU features
#
@ -156,6 +165,7 @@ def getDomainCPUFeatures(parsed_xml):
return dfeatures
#
# Get disk devices
#
@ -200,6 +210,7 @@ def getDomainDisks(parsed_xml, stats_data):
return ddisks
#
# Get a list of disk devices
#
@ -211,6 +222,7 @@ def getDomainDiskList(zk_conn, dom_uuid):
return disk_list
#
# Get domain information from XML
#
@ -308,6 +320,7 @@ def getInformationFromXML(zk_conn, uuid):
return domain_information
#
# Get network devices
#
@ -362,6 +375,7 @@ def getDomainNetworks(parsed_xml, stats_data):
return dnets
#
# Get controller devices
#
@ -379,6 +393,7 @@ def getDomainControllers(parsed_xml):
return dcontrollers
#
# Verify node is valid in cluster
#
@ -388,6 +403,7 @@ def verifyNode(zk_conn, node):
else:
return False
#
# Get the primary coordinator node
#
@ -412,6 +428,7 @@ def getPrimaryNode(zk_conn):
return primary_node
#
# Find a migration target
#
@ -443,6 +460,7 @@ def findTargetNode(zk_conn, dom_uuid):
# Nothing was found
return None
# Get the list of valid target nodes
def getNodes(zk_conn, node_limit, dom_uuid):
valid_node_list = []
@ -469,6 +487,7 @@ def getNodes(zk_conn, node_limit, dom_uuid):
return valid_node_list
# via free memory (relative to allocated memory)
def findTargetNodeMem(zk_conn, node_limit, dom_uuid):
most_provfree = 0
@ -488,6 +507,7 @@ def findTargetNodeMem(zk_conn, node_limit, dom_uuid):
return target_node
# via load average
def findTargetNodeLoad(zk_conn, node_limit, dom_uuid):
least_load = 9999.0
@ -503,6 +523,7 @@ def findTargetNodeLoad(zk_conn, node_limit, dom_uuid):
return target_node
# via total vCPUs
def findTargetNodeVCPUs(zk_conn, node_limit, dom_uuid):
least_vcpus = 9999
@ -518,6 +539,7 @@ def findTargetNodeVCPUs(zk_conn, node_limit, dom_uuid):
return target_node
# via total VMs
def findTargetNodeVMs(zk_conn, node_limit, dom_uuid):
least_vms = 9999
@ -533,6 +555,7 @@ def findTargetNodeVMs(zk_conn, node_limit, dom_uuid):
return target_node
# Connect to the primary host and run a command
def runRemoteCommand(node, command, become=False):
import paramiko

View File

@ -26,6 +26,7 @@ from kazoo.exceptions import NoNodeError
import daemon_lib.zkhandler as zkhandler
#
# Cluster search functions
#
@ -38,6 +39,7 @@ def getClusterNetworkList(zk_conn):
description_list.append(zkhandler.readdata(zk_conn, '/networks/{}'.format(vni)))
return vni_list, description_list
def searchClusterByVNI(zk_conn, vni):
try:
# Get the lists
@ -52,6 +54,7 @@ def searchClusterByVNI(zk_conn, vni):
return description
def searchClusterByDescription(zk_conn, description):
try:
# Get the lists
@ -66,6 +69,7 @@ def searchClusterByDescription(zk_conn, description):
return vni
def getNetworkVNI(zk_conn, network):
# Validate and obtain alternate passed value
if network.isdigit():
@ -77,6 +81,7 @@ def getNetworkVNI(zk_conn, network):
return net_vni
def getNetworkDescription(zk_conn, network):
# Validate and obtain alternate passed value
if network.isdigit():
@ -88,16 +93,19 @@ def getNetworkDescription(zk_conn, network):
return net_description
def getNetworkDHCPLeases(zk_conn, vni):
# Get a list of DHCP leases by listing the children of /networks/<vni>/dhcp4_leases
dhcp4_leases = zkhandler.listchildren(zk_conn, '/networks/{}/dhcp4_leases'.format(vni))
return sorted(dhcp4_leases)
def getNetworkDHCPReservations(zk_conn, vni):
# Get a list of DHCP reservations by listing the children of /networks/<vni>/dhcp4_reservations
dhcp4_reservations = zkhandler.listchildren(zk_conn, '/networks/{}/dhcp4_reservations'.format(vni))
return sorted(dhcp4_reservations)
def getNetworkACLs(zk_conn, vni, _direction):
# Get the (sorted) list of active ACLs
if _direction == 'both':
@ -119,6 +127,7 @@ def getNetworkACLs(zk_conn, vni, _direction):
return full_acl_list
def getNetworkInformation(zk_conn, vni):
description = zkhandler.readdata(zk_conn, '/networks/{}'.format(vni))
nettype = zkhandler.readdata(zk_conn, '/networks/{}/nettype'.format(vni))
@ -155,6 +164,7 @@ def getNetworkInformation(zk_conn, vni):
}
return network_information
def getDHCPLeaseInformation(zk_conn, vni, mac_address):
# Check whether this is a dynamic or static lease
try:
@ -180,6 +190,7 @@ def getDHCPLeaseInformation(zk_conn, vni, mac_address):
}
return lease_information
def getACLInformation(zk_conn, vni, direction, description):
order = zkhandler.readdata(zk_conn, '/networks/{}/firewall_rules/{}/{}/order'.format(vni, direction, description))
rule = zkhandler.readdata(zk_conn, '/networks/{}/firewall_rules/{}/{}/rule'.format(vni, direction, description))
@ -193,6 +204,7 @@ def getACLInformation(zk_conn, vni, direction, description):
}
return acl_information
def isValidMAC(macaddr):
allowed = re.compile(r"""
(
@ -206,6 +218,7 @@ def isValidMAC(macaddr):
else:
return False
def isValidIP(ipaddr):
ip4_blocks = str(ipaddr).split(".")
if len(ip4_blocks) == 4:
@ -219,6 +232,7 @@ def isValidIP(ipaddr):
return True
return False
#
# Direct functions
#
@ -272,6 +286,7 @@ def add_network(zk_conn, vni, description, nettype,
return True, 'Network "{}" added successfully!'.format(description)
def modify_network(zk_conn, vni, description=None, domain=None, name_servers=None,
ip4_network=None, ip4_gateway=None, ip6_network=None, ip6_gateway=None,
dhcp4_flag=None, dhcp4_start=None, dhcp4_end=None):
@ -313,6 +328,7 @@ def modify_network(zk_conn, vni, description=None, domain=None, name_servers=Non
return True, 'Network "{}" modified successfully!'.format(vni)
def remove_network(zk_conn, network):
# Validate and obtain alternate passed value
vni = getNetworkVNI(zk_conn, network)
@ -356,6 +372,7 @@ def add_dhcp_reservation(zk_conn, network, ipaddress, macaddress, hostname):
return True, 'DHCP reservation "{}" added successfully!'.format(macaddress)
def remove_dhcp_reservation(zk_conn, network, reservation):
# Validate and obtain standard passed value
net_vni = getNetworkVNI(zk_conn, network)
@ -395,6 +412,7 @@ def remove_dhcp_reservation(zk_conn, network, reservation):
return True, 'DHCP {} "{}" removed successfully!'.format(lease_type_human, match_description)
def add_acl(zk_conn, network, direction, description, rule, order):
# Validate and obtain standard passed value
net_vni = getNetworkVNI(zk_conn, network)
@ -458,6 +476,7 @@ def add_acl(zk_conn, network, direction, description, rule, order):
return True, 'Firewall rule "{}" added successfully!'.format(description)
def remove_acl(zk_conn, network, description):
# Validate and obtain standard passed value
net_vni = getNetworkVNI(zk_conn, network)
@ -498,6 +517,7 @@ def remove_acl(zk_conn, network, description):
return True, 'Firewall rule "{}" removed successfully!'.format(match_description)
def get_info(zk_conn, network):
# Validate and obtain alternate passed value
net_vni = getNetworkVNI(zk_conn, network)
@ -510,6 +530,7 @@ def get_info(zk_conn, network):
return True, network_information
def get_list(zk_conn, limit, is_fuzzy=True):
net_list = []
full_net_list = zkhandler.listchildren(zk_conn, '/networks')
@ -532,6 +553,7 @@ def get_list(zk_conn, limit, is_fuzzy=True):
return True, net_list
def get_list_dhcp(zk_conn, network, limit, only_static=False, is_fuzzy=True):
# Validate and obtain alternate passed value
net_vni = getNetworkVNI(zk_conn, network)
@ -574,6 +596,7 @@ def get_list_dhcp(zk_conn, network, limit, only_static=False, is_fuzzy=True):
return True, dhcp_list
def get_list_acl(zk_conn, network, limit, direction, is_fuzzy=True):
# Validate and obtain alternate passed value
net_vni = getNetworkVNI(zk_conn, network)

View File

@ -26,6 +26,7 @@ import re
import daemon_lib.zkhandler as zkhandler
import daemon_lib.common as common
def getNodeInformation(zk_conn, node_name):
"""
Gather information about a node from the Zookeeper database and return a dict() containing it.
@ -75,6 +76,7 @@ def getNodeInformation(zk_conn, node_name):
}
return node_information
#
# Direct Functions
#
@ -105,6 +107,7 @@ def secondary_node(zk_conn, node):
return True, retmsg
def primary_node(zk_conn, node):
# Verify node is valid
if not common.verifyNode(zk_conn, node):
@ -132,6 +135,7 @@ def primary_node(zk_conn, node):
return True, retmsg
def flush_node(zk_conn, node, wait=False):
# Verify node is valid
if not common.verifyNode(zk_conn, node):
@ -151,6 +155,7 @@ def flush_node(zk_conn, node, wait=False):
return True, retmsg
def ready_node(zk_conn, node, wait=False):
# Verify node is valid
if not common.verifyNode(zk_conn, node):
@ -170,6 +175,7 @@ def ready_node(zk_conn, node, wait=False):
return True, retmsg
def get_info(zk_conn, node):
# Verify node is valid
if not common.verifyNode(zk_conn, node):
@ -182,6 +188,7 @@ def get_info(zk_conn, node):
return True, node_information
def get_list(zk_conn, limit, daemon_state=None, coordinator_state=None, domain_state=None, is_fuzzy=True):
node_list = []
full_node_list = zkhandler.listchildren(zk_conn, '/nodes')

View File

@ -29,6 +29,7 @@ import daemon_lib.common as common
import daemon_lib.ceph as ceph
#
# Cluster search functions
#
@ -41,6 +42,7 @@ def getClusterDomainList(zk_conn):
name_list.append(zkhandler.readdata(zk_conn, '/domains/%s' % uuid))
return uuid_list, name_list
def searchClusterByUUID(zk_conn, uuid):
try:
# Get the lists
@ -55,6 +57,7 @@ def searchClusterByUUID(zk_conn, uuid):
return name
def searchClusterByName(zk_conn, name):
try:
# Get the lists
@ -69,6 +72,7 @@ def searchClusterByName(zk_conn, name):
return uuid
def getDomainUUID(zk_conn, domain):
# Validate that VM exists in cluster
if common.validateUUID(domain):
@ -80,6 +84,7 @@ def getDomainUUID(zk_conn, domain):
return dom_uuid
def getDomainName(zk_conn, domain):
# Validate that VM exists in cluster
if common.validateUUID(domain):
@ -91,6 +96,7 @@ def getDomainName(zk_conn, domain):
return dom_name
#
# Direct functions
#
@ -106,6 +112,7 @@ def is_migrated(zk_conn, domain):
else:
return False
def flush_locks(zk_conn, domain):
# Validate that VM exists in cluster
dom_uuid = getDomainUUID(zk_conn, domain)
@ -145,6 +152,7 @@ def flush_locks(zk_conn, domain):
return success, message
def define_vm(zk_conn, config_data, target_node, node_limit, node_selector, node_autostart, migration_method=None, profile=None, initial_state='stop'):
# Parse the XML data
try:
@ -204,6 +212,7 @@ def define_vm(zk_conn, config_data, target_node, node_limit, node_selector, node
return True, 'Added new VM with Name "{}" and UUID "{}" to database.'.format(dom_name, dom_uuid)
def modify_vm_metadata(zk_conn, domain, node_limit, node_selector, node_autostart, provisioner_profile, migration_method):
dom_uuid = getDomainUUID(zk_conn, domain)
if not dom_uuid:
@ -236,6 +245,7 @@ def modify_vm_metadata(zk_conn, domain, node_limit, node_selector, node_autostar
return True, 'Successfully modified PVC metadata of VM "{}".'.format(domain)
def modify_vm(zk_conn, domain, restart, new_vm_config):
dom_uuid = getDomainUUID(zk_conn, domain)
if not dom_uuid:
@ -277,6 +287,7 @@ def modify_vm(zk_conn, domain, restart, new_vm_config):
return True, ''
def dump_vm(zk_conn, domain):
dom_uuid = getDomainUUID(zk_conn, domain)
if not dom_uuid:
@ -287,6 +298,7 @@ def dump_vm(zk_conn, domain):
return True, vm_xml
def undefine_vm(zk_conn, domain):
# Validate that VM exists in cluster
dom_uuid = getDomainUUID(zk_conn, domain)
@ -314,6 +326,7 @@ def undefine_vm(zk_conn, domain):
return True, 'Undefined VM "{}" from the cluster.'.format(domain)
def remove_vm(zk_conn, domain):
# Validate that VM exists in cluster
dom_uuid = getDomainUUID(zk_conn, domain)
@ -353,6 +366,7 @@ def remove_vm(zk_conn, domain):
return True, 'Removed VM "{}" and disks from the cluster.'.format(domain)
def start_vm(zk_conn, domain):
# Validate that VM exists in cluster
dom_uuid = getDomainUUID(zk_conn, domain)
@ -367,6 +381,7 @@ def start_vm(zk_conn, domain):
return True, 'Starting VM "{}".'.format(domain)
def restart_vm(zk_conn, domain, wait=False):
# Validate that VM exists in cluster
dom_uuid = getDomainUUID(zk_conn, domain)
@ -393,6 +408,7 @@ def restart_vm(zk_conn, domain, wait=False):
return True, retmsg
def shutdown_vm(zk_conn, domain, wait=False):
# Validate that VM exists in cluster
dom_uuid = getDomainUUID(zk_conn, domain)
@ -419,6 +435,7 @@ def shutdown_vm(zk_conn, domain, wait=False):
return True, retmsg
def stop_vm(zk_conn, domain):
# Validate that VM exists in cluster
dom_uuid = getDomainUUID(zk_conn, domain)
@ -433,6 +450,7 @@ def stop_vm(zk_conn, domain):
return True, 'Forcibly stopping VM "{}".'.format(domain)
def disable_vm(zk_conn, domain):
# Validate that VM exists in cluster
dom_uuid = getDomainUUID(zk_conn, domain)
@ -452,6 +470,7 @@ def disable_vm(zk_conn, domain):
return True, 'Marked VM "{}" as disable.'.format(domain)
def move_vm(zk_conn, domain, target_node, wait=False, force_live=False):
# Validate that VM exists in cluster
dom_uuid = getDomainUUID(zk_conn, domain)
@ -514,6 +533,7 @@ def move_vm(zk_conn, domain, target_node, wait=False, force_live=False):
return True, retmsg
def migrate_vm(zk_conn, domain, target_node, force_migrate, wait=False, force_live=False):
# Validate that VM exists in cluster
dom_uuid = getDomainUUID(zk_conn, domain)
@ -579,6 +599,7 @@ def migrate_vm(zk_conn, domain, target_node, force_migrate, wait=False, force_li
return True, retmsg
def unmigrate_vm(zk_conn, domain, wait=False, force_live=False):
# Validate that VM exists in cluster
dom_uuid = getDomainUUID(zk_conn, domain)
@ -619,6 +640,7 @@ def unmigrate_vm(zk_conn, domain, wait=False, force_live=False):
return True, retmsg
def get_console_log(zk_conn, domain, lines=1000):
# Validate that VM exists in cluster
dom_uuid = getDomainUUID(zk_conn, domain)
@ -634,6 +656,7 @@ def get_console_log(zk_conn, domain, lines=1000):
return True, loglines
def get_info(zk_conn, domain):
# Validate that VM exists in cluster
dom_uuid = getDomainUUID(zk_conn, domain)
@ -647,6 +670,7 @@ def get_info(zk_conn, domain):
return True, domain_information
def get_list(zk_conn, node, state, limit, is_fuzzy=True):
if node:
# Verify node is valid

View File

@ -23,6 +23,7 @@
import time
import uuid
# Exists function
def exists(zk_conn, key):
stat = zk_conn.exists(key)
@ -31,15 +32,18 @@ def exists(zk_conn, key):
else:
return False
# Child list function
def listchildren(zk_conn, key):
children = zk_conn.get_children(key)
return children
# Delete key function
def deletekey(zk_conn, key, recursive=True):
zk_conn.delete(key, recursive=recursive)
# Rename key recursive function
def rename_key_element(zk_conn, zk_transaction, source_key, destination_key):
data_raw = zk_conn.get(source_key)
@ -54,6 +58,7 @@ def rename_key_element(zk_conn, zk_transaction, source_key, destination_key):
zk_transaction.delete(source_key)
# Rename key function
def renamekey(zk_conn, kv):
# Start up a transaction
@ -79,12 +84,14 @@ def renamekey(zk_conn, kv):
except Exception:
return False
# Data read function
def readdata(zk_conn, key):
data_raw = zk_conn.get(key)
data = data_raw[0].decode('utf8')
return data
# Data write function
def writedata(zk_conn, kv):
# Start up a transaction
@ -123,6 +130,7 @@ def writedata(zk_conn, kv):
except Exception:
return False
# Write lock function
def writelock(zk_conn, key):
count = 1
@ -140,6 +148,7 @@ def writelock(zk_conn, key):
continue
return lock
# Read lock function
def readlock(zk_conn, key):
count = 1
@ -157,6 +166,7 @@ def readlock(zk_conn, key):
continue
return lock
# Exclusive lock function
def exclusivelock(zk_conn, key):
count = 1

View File

@ -27,6 +27,7 @@ import psutil
import pvcnoded.zkhandler as zkhandler
import pvcnoded.common as common
class CephOSDInstance(object):
def __init__(self, zk_conn, this_node, osd_id):
self.zk_conn = zk_conn
@ -66,6 +67,7 @@ class CephOSDInstance(object):
if data and data != self.stats:
self.stats = json.loads(data)
def add_osd(zk_conn, logger, node, device, weight):
# We are ready to create a new OSD on this node
logger.out('Creating new OSD disk on block device {}'.format(device), state='i')
@ -188,6 +190,7 @@ def add_osd(zk_conn, logger, node, device, weight):
logger.out('Failed to create new OSD disk: {}'.format(e), state='e')
return False
def remove_osd(zk_conn, logger, osd_id, osd_obj):
logger.out('Removing OSD disk {}'.format(osd_id), state='i')
try:
@ -281,6 +284,7 @@ def remove_osd(zk_conn, logger, osd_id, osd_obj):
logger.out('Failed to purge OSD disk with ID {}: {}'.format(osd_id, e), state='e')
return False
class CephPoolInstance(object):
def __init__(self, zk_conn, this_node, name):
self.zk_conn = zk_conn
@ -319,6 +323,7 @@ class CephPoolInstance(object):
if data and data != self.stats:
self.stats = json.loads(data)
class CephVolumeInstance(object):
def __init__(self, zk_conn, this_node, pool, name):
self.zk_conn = zk_conn
@ -342,6 +347,7 @@ class CephVolumeInstance(object):
if data and data != self.stats:
self.stats = json.loads(data)
class CephSnapshotInstance(object):
def __init__(self, zk_conn, this_node, pool, volume, name):
self.zk_conn = zk_conn
@ -366,6 +372,7 @@ class CephSnapshotInstance(object):
if data and data != self.stats:
self.stats = json.loads(data)
# Primary command function
# This command pipe is only used for OSD adds and removes
def run_command(zk_conn, logger, this_node, data, d_osd):

View File

@ -29,6 +29,7 @@ from threading import Thread, Event
import pvcnoded.common as common
class DNSAggregatorInstance(object):
# Initialization function
def __init__(self, zk_conn, config, logger):
@ -65,6 +66,7 @@ class DNSAggregatorInstance(object):
del self.dns_networks[network]
self.dns_axfr_daemon.update_networks(self.dns_networks)
class PowerDNSInstance(object):
# Initialization function
def __init__(self, aggregator):
@ -138,6 +140,7 @@ class PowerDNSInstance(object):
state='o'
)
class DNSNetworkInstance(object):
# Initialization function
def __init__(self, aggregator, network):

View File

@ -74,6 +74,7 @@ version = '0.9.1'
# Daemon functions
###############################################################################
# Create timer to update this node in Zookeeper
def startKeepaliveTimer():
# Create our timer object
@ -85,6 +86,7 @@ def startKeepaliveTimer():
node_keepalive()
return update_timer
def stopKeepaliveTimer():
global update_timer
try:
@ -125,6 +127,7 @@ staticdata.append(subprocess.run(['uname', '-r'], stdout=subprocess.PIPE).stdout
staticdata.append(subprocess.run(['uname', '-o'], stdout=subprocess.PIPE).stdout.decode('ascii').strip())
staticdata.append(subprocess.run(['uname', '-m'], stdout=subprocess.PIPE).stdout.decode('ascii').strip())
# Read and parse the config file
def readConfig(pvcnoded_config_file, myhostname):
print('Loading configuration from file "{}"'.format(pvcnoded_config_file))
@ -512,6 +515,7 @@ except Exception as e:
logger.out('ERROR: Failed to connect to Zookeeper cluster: {}'.format(e), state='e')
exit(1)
# Handle zookeeper failures
def zk_listener(state):
global zk_conn, update_timer
@ -551,6 +555,7 @@ zk_conn.add_listener(zk_listener)
# PHASE 5 - Gracefully handle termination
###############################################################################
# Cleanup function
def cleanup():
global zk_conn, update_timer, d_domain
@ -615,10 +620,12 @@ def cleanup():
logger.out('Terminated pvc daemon', state='s')
sys.exit(0)
# Termination function
def term(signum='', frame=''):
cleanup()
# Hangup (logrotate) function
def hup(signum='', frame=''):
if config['file_logging']:
@ -796,6 +803,7 @@ else:
dns_aggregator = None
metadata_api = None
# Node objects
@zk_conn.ChildrenWatch('/nodes')
def update_nodes(new_node_list):
@ -824,6 +832,7 @@ def update_nodes(new_node_list):
# Alias for our local node (passed to network and domain objects)
this_node = d_node[myhostname]
# Maintenance mode
@zk_conn.DataWatch('/maintenance')
def set_maintenance(_maintenance, stat, event=''):
@ -833,6 +842,7 @@ def set_maintenance(_maintenance, stat, event=''):
except Exception:
maintenance = False
# Primary node
@zk_conn.DataWatch('/primary_node')
def update_primary(new_primary, stat, event=''):
@ -1023,6 +1033,7 @@ if enable_storage:
volume_list[pool] = new_volume_list
logger.out('{}Volume list [{pool}]:{} {plist}'.format(fmt_blue, fmt_end, pool=pool, plist=' '.join(volume_list[pool])), state='i')
###############################################################################
# PHASE 9 - Run the daemon
###############################################################################
@ -1311,6 +1322,7 @@ libvirt_vm_states = {
7: "PMSUSPENDED"
}
# VM stats update function
def collect_vm_stats(queue):
if debug:
@ -1454,6 +1466,7 @@ def collect_vm_stats(queue):
if debug:
logger.out("Thread finished", state='d', prefix='vm-thread')
# Keepalive update function
def node_keepalive():
if debug:

View File

@ -32,6 +32,7 @@ from psycopg2.extras import RealDictCursor
import daemon_lib.vm as pvc_vm
import daemon_lib.network as pvc_network
class MetadataAPIInstance(object):
mdapi = flask.Flask(__name__)

View File

@ -27,6 +27,7 @@ from threading import Thread
import pvcnoded.zkhandler as zkhandler
import pvcnoded.common as common
class NodeInstance(object):
# Initialization function
def __init__(self, name, this_node, zk_conn, config, logger, d_node, d_network, d_domain, dns_aggregator, metadata_api):

View File

@ -28,6 +28,7 @@ from collections import deque
import pvcnoded.zkhandler as zkhandler
class VMConsoleWatcherInstance(object):
# Initialization function
def __init__(self, domuuid, domname, zk_conn, config, logger, this_node):

View File

@ -34,6 +34,7 @@ import pvcnoded.VMConsoleWatcherInstance as VMConsoleWatcherInstance
import daemon_lib.common as daemon_common
def flush_locks(zk_conn, logger, dom_uuid):
logger.out('Flushing RBD locks for VM "{}"'.format(dom_uuid), state='i')
# Get the list of RBD images
@ -64,6 +65,7 @@ def flush_locks(zk_conn, logger, dom_uuid):
return True
# Primary command function
def run_command(zk_conn, logger, this_node, data):
# Get the command and args
@ -92,6 +94,7 @@ def run_command(zk_conn, logger, this_node, data):
# Wait 1 seconds before we free the lock, to ensure the client hits the lock
time.sleep(1)
class VMInstance(object):
# Initialization function
def __init__(self, domuuid, zk_conn, config, logger, this_node):

View File

@ -28,6 +28,7 @@ from textwrap import dedent
import pvcnoded.zkhandler as zkhandler
import pvcnoded.common as common
class VXNetworkInstance(object):
# Initialization function
def __init__(self, vni, zk_conn, config, logger, this_node, dns_aggregator):

View File

@ -28,6 +28,7 @@ from shlex import split as shlex_split
import pvcnoded.zkhandler as zkhandler
class OSDaemon(object):
def __init__(self, command_string, environment, logfile):
command = shlex_split(command_string)
@ -55,10 +56,12 @@ class OSDaemon(object):
}
self.proc.send_signal(signal_map[sent_signal])
def run_os_daemon(command_string, environment=None, logfile=None):
daemon = OSDaemon(command_string, environment, logfile)
return daemon
# Run a oneshot command, optionally without blocking
def run_os_command(command_string, background=False, environment=None, timeout=None):
command = shlex_split(command_string)
@ -100,6 +103,7 @@ def run_os_command(command_string, background=False, environment=None, timeout=N
stderr = ''
return retcode, stdout, stderr
# Reload the firewall rules of the system
def reload_firewall_rules(logger, rules_file):
logger.out('Reloading firewall configuration', state='o')
@ -107,6 +111,7 @@ def reload_firewall_rules(logger, rules_file):
if retcode != 0:
logger.out('Failed to reload configuration: {}'.format(stderr), state='e')
# Create IP address
def createIPAddress(ipaddr, cidrnetmask, dev):
run_os_command(
@ -123,6 +128,7 @@ def createIPAddress(ipaddr, cidrnetmask, dev):
)
)
# Remove IP address
def removeIPAddress(ipaddr, cidrnetmask, dev):
run_os_command(
@ -133,6 +139,7 @@ def removeIPAddress(ipaddr, cidrnetmask, dev):
)
)
#
# Find a migration target
#
@ -173,6 +180,7 @@ def findTargetNode(zk_conn, config, logger, dom_uuid):
# Nothing was found
return None
# Get the list of valid target nodes
def getNodes(zk_conn, node_limit, dom_uuid):
valid_node_list = []
@ -196,6 +204,7 @@ def getNodes(zk_conn, node_limit, dom_uuid):
return valid_node_list
# via free memory (relative to allocated memory)
def findTargetNodeMem(zk_conn, config, logger, node_limit, dom_uuid):
most_provfree = 0
@ -222,6 +231,7 @@ def findTargetNodeMem(zk_conn, config, logger, node_limit, dom_uuid):
logger.out('Selected node {}'.format(target_node), state='d', prefix='node-flush')
return target_node
# via load average
def findTargetNodeLoad(zk_conn, config, logger, node_limit, dom_uuid):
least_load = 9999.0
@ -244,6 +254,7 @@ def findTargetNodeLoad(zk_conn, config, logger, node_limit, dom_uuid):
logger.out('Selected node {}'.format(target_node), state='d', prefix='node-flush')
return target_node
# via total vCPUs
def findTargetNodeVCPUs(zk_conn, config, logger, node_limit, dom_uuid):
least_vcpus = 9999
@ -266,6 +277,7 @@ def findTargetNodeVCPUs(zk_conn, config, logger, node_limit, dom_uuid):
logger.out('Selected node {}'.format(target_node), state='d', prefix='node-flush')
return target_node
# via total VMs
def findTargetNodeVMs(zk_conn, config, logger, node_limit, dom_uuid):
least_vms = 9999

View File

@ -26,6 +26,7 @@ import kazoo.client
import re
import yaml
#
# Variables
#
@ -45,6 +46,7 @@ def get_zookeeper_key():
zookeeper_key = '/networks/{}/dhcp4_leases'.format(network_vni)
return zookeeper_key
def get_lease_expiry():
try:
expiry = os.environ['DNSMASQ_LEASE_EXPIRES']
@ -52,6 +54,7 @@ def get_lease_expiry():
expiry = '0'
return expiry
def get_client_id():
try:
client_id = os.environ['DNSMASQ_CLIENT_ID']
@ -59,6 +62,7 @@ def get_client_id():
client_id = '*'
return client_id
def connect_zookeeper():
# We expect the environ to contain the config file
try:
@ -83,9 +87,11 @@ def connect_zookeeper():
return zk_conn
def read_data(zk_conn, key):
return zk_conn.get(key)[0].decode('ascii')
def get_lease(zk_conn, zk_leases_key, macaddr):
expiry = read_data(zk_conn, '{}/{}/expiry'.format(zk_leases_key, macaddr))
ipaddr = read_data(zk_conn, '{}/{}/ipaddr'.format(zk_leases_key, macaddr))
@ -93,6 +99,7 @@ def get_lease(zk_conn, zk_leases_key, macaddr):
clientid = read_data(zk_conn, '{}/{}/clientid'.format(zk_leases_key, macaddr))
return expiry, ipaddr, hostname, clientid
#
# Command Functions
#
@ -108,6 +115,7 @@ def read_lease_database(zk_conn, zk_leases_key):
# Output list
print('\n'.join(output_list))
def add_lease(zk_conn, zk_leases_key, expiry, macaddr, ipaddr, hostname, clientid):
if not hostname:
hostname = ''
@ -119,6 +127,7 @@ def add_lease(zk_conn, zk_leases_key, expiry, macaddr, ipaddr, hostname, clienti
transaction.create('{}/{}/clientid'.format(zk_leases_key, macaddr), clientid.encode('ascii'))
transaction.commit()
def del_lease(zk_conn, zk_leases_key, macaddr, expiry):
zk_conn.delete('{}/{}'.format(zk_leases_key, macaddr), recursive=True)

View File

@ -26,6 +26,7 @@ import pvcnoded.zkhandler as zkhandler
import pvcnoded.common as common
import pvcnoded.VMInstance as VMInstance
#
# Fence thread entry function
#
@ -74,6 +75,7 @@ def fenceNode(node_name, zk_conn, config, logger):
if not fence_status and config['failed_fence'] == 'migrate' and config['suicide_intervals'] != '0':
migrateFromFencedNode(zk_conn, node_name, config, logger)
# Migrate hosts away from a fenced node
def migrateFromFencedNode(zk_conn, node_name, config, logger):
logger.out('Migrating VMs from dead node "{}" to new hosts'.format(node_name), state='i')
@ -111,6 +113,7 @@ def migrateFromFencedNode(zk_conn, node_name, config, logger):
# Set node in flushed state for easy remigrating when it comes back
zkhandler.writedata(zk_conn, {'/nodes/{}/domainstate'.format(node_name): 'flushed'})
#
# Perform an IPMI fence
#
@ -145,6 +148,7 @@ def rebootViaIPMI(ipmi_hostname, ipmi_user, ipmi_password, logger):
print(ipmi_reset_stderr)
return False
#
# Verify that IPMI connectivity to this host exists (used during node init)
#

View File

@ -22,6 +22,7 @@
import datetime
class Logger(object):
# Define a logger class for a daemon instance
# Keeps record of where to log, and is passed messages which are

View File

@ -22,6 +22,7 @@
import uuid
# Child list function
def listchildren(zk_conn, key):
try:
@ -30,6 +31,7 @@ def listchildren(zk_conn, key):
except Exception:
return None
# Key deletion function
def deletekey(zk_conn, key, recursive=True):
try:
@ -38,6 +40,7 @@ def deletekey(zk_conn, key, recursive=True):
except Exception:
return False
# Data read function
def readdata(zk_conn, key):
try:
@ -47,6 +50,7 @@ def readdata(zk_conn, key):
except Exception:
return None
# Data write function
def writedata(zk_conn, kv):
# Commit the transaction
@ -87,6 +91,7 @@ def writedata(zk_conn, kv):
except Exception:
return False
# Key rename function
def renamekey(zk_conn, kv):
# This one is not transactional because, inexplicably, transactions don't
@ -133,6 +138,7 @@ def renamekey(zk_conn, kv):
except Exception:
return False
# Write lock function
def writelock(zk_conn, key):
count = 1
@ -149,6 +155,7 @@ def writelock(zk_conn, key):
continue
return lock
# Read lock function
def readlock(zk_conn, key):
count = 1
@ -165,6 +172,7 @@ def readlock(zk_conn, key):
continue
return lock
# Exclusive lock function
def exclusivelock(zk_conn, key):
count = 1