charm-glusterfs/src/reactive/actions.py

234 lines
7.2 KiB
Python
Executable File

#!/usr/bin/python3
# Copyright 2017 Canonical Ltd
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import os
import sys
from charmhelpers.core import hookenv
from charmhelpers.core.hookenv import action_get, action_fail, action_set
from lib.gluster.volume import (quota_list,
BitrotOption, ScrubAggression, ScrubSchedule,
ScrubControl, GlusterOption,
volume_add_quota,
volume_disable_bitrot, volume_enable_bitrot,
volume_enable_quotas, volume_quotas_enabled,
volume_rebalance, volume_remove_quota,
volume_set_bitrot_option, volume_set_options)
def rebalance_volume():
"""
Start a rebalance volume operation
"""
vol = action_get("volume")
if not vol:
action_fail("volume not specified")
output = volume_rebalance(vol)
if output.is_err():
action_fail(
"volume rebalance failed with error: {}".format(output.value))
def enable_bitrot_scan():
"""
Enable bitrot scan
"""
vol = action_get("volume")
if not vol:
action_fail("volume not specified")
output = volume_enable_bitrot(vol)
if output.is_err():
action_fail("enable bitrot failed with error: {}".format(output.value))
def disable_bitrot_scan():
"""
Disable bitrot scan
"""
vol = action_get("volume")
if not vol:
action_fail("volume not specified")
output = volume_disable_bitrot(vol)
if output.is_err():
action_fail("enable disable failed with error: {}".format(
output.value))
def pause_bitrot_scan():
"""
Pause bitrot scan
"""
vol = action_get("volume")
option = BitrotOption.Scrub(ScrubControl.Pause)
output = volume_set_bitrot_option(vol, option)
if output.is_err():
action_fail(
"pause bitrot scan failed with error: {}".format(output.value))
def resume_bitrot_scan():
"""
Resume bitrot scan
"""
vol = action_get("volume")
option = BitrotOption.Scrub(ScrubControl.Resume)
output = volume_set_bitrot_option(vol, option)
if output.is_err():
action_fail(
"resume bitrot scan failed with error: {}".format(option.value))
def set_bitrot_scan_frequency():
"""
Set the bitrot scan frequency
"""
vol = action_get("volume")
frequency = action_get("frequency")
option = ScrubSchedule.from_str(frequency)
output = volume_set_bitrot_option(vol, BitrotOption.ScrubFrequency(option))
if output.is_err():
action_fail("set bitrot scan frequency failed with error: {}".format(
output.value))
def set_bitrot_throttle():
"""
Set how aggressive bitrot scanning should be
"""
vol = action_get("volume")
throttle = action_get("throttle")
option = ScrubAggression.from_str(throttle)
output = volume_set_bitrot_option(vol, BitrotOption.ScrubThrottle(option))
if output.is_err():
action_fail(
"set bitrot throttle failed with error: {}".format(output.value))
def enable_volume_quota():
"""
Enable quotas on the volume
"""
# Gather our action parameters
volume = action_get("volume")
usage_limit = action_get("usage-limit")
parsed_usage_limit = int(usage_limit)
path = action_get("path")
# Turn quotas on if not already enabled
quotas_enabled = volume_quotas_enabled(volume)
if quotas_enabled.is_err():
action_fail("Enable quota failed: {}".format(quotas_enabled.value))
if not quotas_enabled.value:
output = volume_enable_quotas(volume)
if output.is_err():
action_fail("Enable quotas failed: {}".format(output.value))
output = volume_add_quota(volume, path, parsed_usage_limit)
if output.is_err():
action_fail("Add quota failed: {}".format(output.value))
def disable_volume_quota():
"""
Disable quotas on the volume
"""
volume = action_get("volume")
path = action_get("path")
quotas_enabled = volume_quotas_enabled(volume)
if quotas_enabled.is_err():
action_fail("Disable quota failed: {}".format(quotas_enabled.value))
if quotas_enabled.value:
output = volume_remove_quota(volume, path)
if output.is_err():
# Notify the user of the failure and then return the error
# up the stack
action_fail(
"remove quota failed with error: {}".format(output.value))
def list_volume_quotas():
"""
List quotas on the volume
"""
volume = action_get("volume")
quotas_enabled = volume_quotas_enabled(volume)
if quotas_enabled.is_err():
action_fail("List quota failed: {}".format(quotas_enabled.value))
if quotas_enabled.value:
quotas = quota_list(volume)
if quotas.is_err():
action_fail(
"Failed to get volume quotas: {}".format(quotas.value))
quota_strings = []
for quota in quotas.value:
quota_string = "path:{} limit:{} used:{}".format(
quota.path,
quota.hard_limit,
quota.used)
quota_strings.append(quota_string)
action_set({"quotas": "\n".join(quota_strings)})
def set_volume_options():
"""
Set one or more options on the volume at once
"""
volume = action_get("volume")
# Gather all of the action parameters up at once. We don't know what
# the user wants to change.
options = action_get()
settings = []
for (key, value) in options:
if key != "volume":
settings.append(GlusterOption(key, value))
else:
volume = value
volume_set_options(volume, settings)
# Actions to function mapping, to allow for illegal python action names that
# can map to a python function.
ACTIONS = {
"create-volume-quota": enable_volume_quota,
"delete-volume-quota": disable_volume_quota,
"disable-bitrot-scan": disable_bitrot_scan,
"enable-bitrot-scan": enable_bitrot_scan,
"list-volume-quotas": list_volume_quotas,
"pause-bitrot-scan": pause_bitrot_scan,
"rebalance-volume": rebalance_volume,
"resume-bitrot-scan": resume_bitrot_scan,
"set-bitrot-scan-frequency": set_bitrot_scan_frequency,
"set-bitrot-throttle": set_bitrot_throttle,
"set-volume-options": set_volume_options,
}
def main(args):
action_name = os.path.basename(args[0])
try:
action = ACTIONS[action_name]
except KeyError:
return "Action %s undefined" % action_name
else:
try:
action(args)
except Exception as e:
hookenv.action_fail(str(e))
if __name__ == "__main__":
sys.exit(main(sys.argv))