@ -38,27 +38,33 @@ options:
use started / stopped to control it ' s availability.
cluster :
required : false
default : null
description :
- List of hosts to use for probing and brick setup
host :
required : false
default : null
description :
- Override local hostname ( for peer probing purposes )
replicas :
required : false
default : null
description :
- Replica count for volume
stripes :
required : false
default : null
description :
- Stripe count for volume
transport :
required : false
choices : [ ' tcp ' , ' rdma ' , ' tcp,rdma ' ]
default : ' tcp '
description :
- Transport type for volume
brick :
required : false
default : null
description :
- Brick path on servers
start_on_create :
@ -69,22 +75,27 @@ options:
rebalance :
choices : [ ' yes ' , ' no ' ]
required : false
default : ' no '
description :
- Controls whether the cluster is rebalanced after changes
directory :
required : false
default : null
description :
- Directory for limit - usage
options :
required : false
default : null
description :
- A dictionary / hash with options / settings for the volume
quota :
required : false
default : null
description :
- Quota value for limit - usage ( be sure to use 10.0 MB instead of 10 MB , see quota list )
force :
required : false
default : null
description :
- If brick is being created in the root partition , module will fail .
Set force to true to override this behaviour
@ -119,165 +130,167 @@ import shutil
import time
import socket
def main ( ) :
def run_gluster ( gargs , * * kwargs ) :
args = [ glusterbin ]
args . extend ( gargs )
def run_gluster ( gargs , * * kwargs ) :
args = [ glusterbin ]
args . extend ( gargs )
try :
rc , out , err = module . run_command ( args , * * kwargs )
if rc != 0 :
module . fail_json ( msg = ' error running gluster ( %s ) command (rc= %d ): %s ' % ( ' ' . join ( args ) , rc , out if out != ' ' else err ) )
return out
def run_gluster_nofail ( gargs , * * kwargs ) :
args = [ glusterbin ]
args . extend ( gargs )
rc , out , err = module . run_command ( args , * * kwargs )
if rc != 0 :
return None
return out
def run_gluster_yes ( gargs ) :
args = [ glusterbin ]
args . extend ( gargs )
rc , out , err = module . run_command ( args , data = ' y \n ' )
if rc != 0 :
module . fail_json ( msg = ' error running gluster ( %s ) command (rc= %d ): %s ' % ( ' ' . join ( args ) , rc , out if out != ' ' else err ) )
return out
def get_peers ( ) :
out = run_gluster ( [ ' peer ' , ' status ' ] )
i = 0
peers = { }
hostname = None
uuid = None
state = None
for row in out . split ( ' \n ' ) :
if ' : ' in row :
key , value = row . split ( ' : ' )
if key . lower ( ) == ' hostname ' :
hostname = value
if key . lower ( ) == ' uuid ' :
uuid = value
if key . lower ( ) == ' state ' :
state = value
peers [ hostname ] = [ uuid , state ]
return peers
def get_volumes ( ) :
out = run_gluster ( [ ' volume ' , ' info ' ] )
volumes = { }
volume = { }
for row in out . split ( ' \n ' ) :
if ' : ' in row :
key , value = row . split ( ' : ' )
if key . lower ( ) == ' volume name ' :
volume [ ' name ' ] = value
except Exception , e :
module . fail_json ( msg = ' error running gluster ( %s ) command: %s ' % ( ' ' . join ( args ) , str ( e ) )
return out
def run_gluster_nofail ( gargs , * * kwargs ) :
args = [ glusterbin ]
args . extend ( gargs )
rc , out , err = module . run_command ( args , * * kwargs )
if rc != 0 :
return None
return out
def run_gluster_yes ( gargs ) :
args = [ glusterbin ]
args . extend ( gargs )
rc , out , err = module . run_command ( args , data = ' y \n ' )
if rc != 0 :
module . fail_json ( msg = ' error running gluster ( %s ) command (rc= %d ): %s ' % ( ' ' . join ( args ) , rc , out if out != ' ' else err ) )
return out
def get_peers ( ) :
out = run_gluster ( [ ' peer ' , ' status ' ] )
i = 0
peers = { }
hostname = None
uuid = None
state = None
for row in out . split ( ' \n ' ) :
if ' : ' in row :
key , value = row . split ( ' : ' )
if key . lower ( ) == ' hostname ' :
hostname = value
if key . lower ( ) == ' uuid ' :
uuid = value
if key . lower ( ) == ' state ' :
state = value
peers [ hostname ] = [ uuid , state ]
return peers
def get_volumes ( ) :
out = run_gluster ( [ ' volume ' , ' info ' ] )
volumes = { }
volume = { }
for row in out . split ( ' \n ' ) :
if ' : ' in row :
key , value = row . split ( ' : ' )
if key . lower ( ) == ' volume name ' :
volume [ ' name ' ] = value
volume [ ' options ' ] = { }
volume [ ' quota ' ] = False
if key . lower ( ) == ' volume id ' :
volume [ ' id ' ] = value
if key . lower ( ) == ' status ' :
volume [ ' status ' ] = value
if key . lower ( ) == ' transport-type ' :
volume [ ' transport ' ] = value
if key . lower ( ) != ' bricks ' and key . lower ( ) [ : 5 ] == ' brick ' :
if not ' bricks ' in volume :
volume [ ' bricks ' ] = [ ]
volume [ ' bricks ' ] . append ( value )
# Volume options
if ' . ' in key :
if not ' options ' in volume :
volume [ ' options ' ] = { }
volume [ ' quota ' ] = False
if key . lower ( ) == ' volume id ' :
volume [ ' id ' ] = value
if key . lower ( ) == ' status ' :
volume [ ' status ' ] = value
if key . lower ( ) == ' transport-type ' :
volume [ ' transport ' ] = value
if key . lower ( ) != ' bricks ' and key . lower ( ) [ : 5 ] == ' brick ' :
if not ' bricks ' in volume :
volume [ ' bricks ' ] = [ ]
volume [ ' bricks ' ] . append ( value )
# Volume options
if ' . ' in key :
if not ' options ' in volume :
volume [ ' options ' ] = { }
volume [ ' options ' ] [ key ] = value
if key == ' features.quota ' and value == ' on ' :
volume [ ' quota ' ] = True
else :
if row . lower ( ) != ' bricks: ' and row . lower ( ) != ' options reconfigured: ' :
if len ( volume ) > 0 :
volumes [ volume [ ' name ' ] ] = volume
volume = { }
return volumes
def get_quotas ( name , nofail ) :
quotas = { }
if nofail :
out = run_gluster_nofail ( [ ' volume ' , ' quota ' , name , ' list ' ] )
if not out :
return quotas
volume [ ' options ' ] [ key ] = value
if key == ' features.quota ' and value == ' on ' :
volume [ ' quota ' ] = True
else :
out = run_gluster ( [ ' volume ' , ' quota ' , name , ' list ' ] )
for row in out . split ( ' \n ' ) :
if row [ : 1 ] == ' / ' :
q = re . split ( ' \ s+ ' , row )
quotas [ q [ 0 ] ] = q [ 1 ]
return quotas
def wait_for_peer ( host ) :
for x in range ( 0 , 4 ) :
peers = get_peers ( )
if host in peers and peers [ host ] [ 1 ] . lower ( ) . find ( ' peer in cluster ' ) != - 1 :
return True
time . sleep ( 1 )
return False
def probe ( host ) :
run_gluster ( [ ' peer ' , ' probe ' , host ] )
if not wait_for_peer ( host ) :
module . fail_json ( msg = ' failed to probe peer %s ' % host )
changed = True
def probe_all_peers ( hosts , peers , myhostname ) :
for host in hosts :
if host not in peers :
# dont probe ourselves
if myhostname != host :
probe ( host )
def create_volume ( name , stripe , replica , transport , hosts , brick , force ) :
args = [ ' volume ' , ' create ' ]
args . append ( name )
if stripe :
args . append ( ' stripe ' )
args . append ( str ( stripe ) )
if replica :
args . append ( ' replica ' )
args . append ( str ( replica ) )
args . append ( ' transport ' )
args . append ( transport )
for host in hosts :
args . append ( ( ' %s : %s ' % ( host , brick ) ) )
if force :
args . append ( ' force ' )
run_gluster ( args )
def start_volume ( name ) :
run_gluster ( [ ' volume ' , ' start ' , name ] )
def stop_volume ( name ) :
run_gluster_yes ( [ ' volume ' , ' stop ' , name ] )
def set_volume_option ( name , option , parameter ) :
run_gluster ( [ ' volume ' , ' set ' , name , option , parameter ] )
def add_brick ( name , brick , force ) :
args = [ ' volume ' , ' add-brick ' , name , brick ]
if force :
args . append ( ' force ' )
run_gluster ( args )
def rebalance ( name ) :
run_gluster ( [ ' volume ' , ' rebalance ' , name , ' start ' ] )
def enable_quota ( name ) :
run_gluster ( [ ' volume ' , ' quota ' , name , ' enable ' ] )
def set_quota ( name , directory , value ) :
run_gluster ( [ ' volume ' , ' quota ' , name , ' limit-usage ' , directory , value ] )
if row . lower ( ) != ' bricks: ' and row . lower ( ) != ' options reconfigured: ' :
if len ( volume ) > 0 :
volumes [ volume [ ' name ' ] ] = volume
volume = { }
return volumes
def get_quotas ( name , nofail ) :
quotas = { }
if nofail :
out = run_gluster_nofail ( [ ' volume ' , ' quota ' , name , ' list ' ] )
if not out :
return quotas
else :
out = run_gluster ( [ ' volume ' , ' quota ' , name , ' list ' ] )
for row in out . split ( ' \n ' ) :
if row [ : 1 ] == ' / ' :
q = re . split ( ' \ s+ ' , row )
quotas [ q [ 0 ] ] = q [ 1 ]
return quotas
def wait_for_peer ( host ) :
for x in range ( 0 , 4 ) :
peers = get_peers ( )
if host in peers and peers [ host ] [ 1 ] . lower ( ) . find ( ' peer in cluster ' ) != - 1 :
return True
time . sleep ( 1 )
return False
def probe ( host ) :
run_gluster ( [ ' peer ' , ' probe ' , host ] )
if not wait_for_peer ( host ) :
module . fail_json ( msg = ' failed to probe peer %s ' % host )
changed = True
def probe_all_peers ( hosts , peers , myhostname ) :
for host in hosts :
if host not in peers :
# dont probe ourselves
if myhostname != host :
probe ( host )
def create_volume ( name , stripe , replica , transport , hosts , brick , force ) :
args = [ ' volume ' , ' create ' ]
args . append ( name )
if stripe :
args . append ( ' stripe ' )
args . append ( str ( stripe ) )
if replica :
args . append ( ' replica ' )
args . append ( str ( replica ) )
args . append ( ' transport ' )
args . append ( transport )
for host in hosts :
args . append ( ( ' %s : %s ' % ( host , brick ) ) )
if force :
args . append ( ' force ' )
run_gluster ( args )
def start_volume ( name ) :
run_gluster ( [ ' volume ' , ' start ' , name ] )
def stop_volume ( name ) :
run_gluster_yes ( [ ' volume ' , ' stop ' , name ] )
def set_volume_option ( name , option , parameter ) :
run_gluster ( [ ' volume ' , ' set ' , name , option , parameter ] )
def add_brick ( name , brick , force ) :
args = [ ' volume ' , ' add-brick ' , name , brick ]
if force :
args . append ( ' force ' )
run_gluster ( args )
def do_rebalance ( name ) :
run_gluster ( [ ' volume ' , ' rebalance ' , name , ' start ' ] )
def enable_quota ( name ) :
run_gluster ( [ ' volume ' , ' quota ' , name , ' enable ' ] )
def set_quota ( name , directory , value ) :
run_gluster ( [ ' volume ' , ' quota ' , name , ' limit-usage ' , directory , value ] )
def main ( ) :
### MAIN ###
module = AnsibleModule (
@ -403,7 +416,7 @@ def main():
if changed :
volumes = get_volumes ( )
if rebalance :
rebalance( volume_name )
do_ rebalance( volume_name )
facts = { }
facts [ ' glusterfs ' ] = { ' peers ' : peers , ' volumes ' : volumes , ' quotas ' : quotas }