Lint: E302 expected 2 blank lines, found X
This commit is contained in:
parent
e9643651f7
commit
260b39ebf2
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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'
|
||||
|
||||
|
|
|
@ -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
|
||||
#
|
||||
|
|
|
@ -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
|
||||
#
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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."
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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 = []
|
||||
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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
|
||||
###############################################################################
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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')
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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__)
|
||||
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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)
|
||||
#
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue