Revision 376631d1
b/Makefile.am | ||
---|---|---|
1297 | 1297 |
echo "SSH_CONSOLE_USER = '$(SSH_CONSOLE_USER)'"; \ |
1298 | 1298 |
echo "EXPORT_DIR = '$(EXPORT_DIR)'"; \ |
1299 | 1299 |
echo "OS_SEARCH_PATH = [$(OS_SEARCH_PATH)]"; \ |
1300 |
echo "ES_SEARCH_PATH = [$(ES_SEARCH_PATH)]"; \ |
|
1300 | 1301 |
echo "XEN_BOOTLOADER = '$(XEN_BOOTLOADER)'"; \ |
1301 | 1302 |
echo "XEN_KERNEL = '$(XEN_KERNEL)'"; \ |
1302 | 1303 |
echo "XEN_INITRD = '$(XEN_INITRD)'"; \ |
b/configure.ac | ||
---|---|---|
60 | 60 |
[os_search_path="'/srv/ganeti/os'"]) |
61 | 61 |
AC_SUBST(OS_SEARCH_PATH, $os_search_path) |
62 | 62 |
|
63 |
# --with-extstorage-search-path=... |
|
64 |
# same black sed magic for quoting of the strings in the list |
|
65 |
AC_ARG_WITH([extstorage-search-path], |
|
66 |
[AS_HELP_STRING([--with-extstorage-search-path=LIST], |
|
67 |
[comma separated list of directories to] |
|
68 |
[ search for External Storage Providers] |
|
69 |
[ (default is /srv/ganeti/extstorage)] |
|
70 |
)], |
|
71 |
[es_search_path=`echo -n "$withval" | sed -e "s/\([[^,]]*\)/'\1'/g"`], |
|
72 |
[es_search_path="'/srv/ganeti/extstorage'"]) |
|
73 |
AC_SUBST(ES_SEARCH_PATH, $es_search_path) |
|
74 |
|
|
63 | 75 |
# --with-iallocator-search-path=... |
64 | 76 |
# do a bit of black sed magic to for quoting of the strings in the list |
65 | 77 |
AC_ARG_WITH([iallocator-search-path], |
b/lib/bdev.py | ||
---|---|---|
2786 | 2786 |
result.fail_reason, result.output) |
2787 | 2787 |
|
2788 | 2788 |
|
2789 |
class ExtStorageDevice(BlockDev): |
|
2790 |
"""A block device provided by an ExtStorage Provider. |
|
2791 |
|
|
2792 |
This class implements the External Storage Interface, which means |
|
2793 |
handling of the externally provided block devices. |
|
2794 |
|
|
2795 |
""" |
|
2796 |
def __init__(self, unique_id, children, size, params): |
|
2797 |
"""Attaches to an extstorage block device. |
|
2798 |
|
|
2799 |
""" |
|
2800 |
super(ExtStorageDevice, self).__init__(unique_id, children, size, params) |
|
2801 |
if not isinstance(unique_id, (tuple, list)) or len(unique_id) != 2: |
|
2802 |
raise ValueError("Invalid configuration data %s" % str(unique_id)) |
|
2803 |
|
|
2804 |
self.driver, self.vol_name = unique_id |
|
2805 |
|
|
2806 |
self.major = self.minor = None |
|
2807 |
self.Attach() |
|
2808 |
|
|
2809 |
@classmethod |
|
2810 |
def Create(cls, unique_id, children, size, params): |
|
2811 |
"""Create a new extstorage device. |
|
2812 |
|
|
2813 |
Provision a new volume using an extstorage provider, which will |
|
2814 |
then be mapped to a block device. |
|
2815 |
|
|
2816 |
""" |
|
2817 |
if not isinstance(unique_id, (tuple, list)) or len(unique_id) != 2: |
|
2818 |
raise errors.ProgrammerError("Invalid configuration data %s" % |
|
2819 |
str(unique_id)) |
|
2820 |
|
|
2821 |
# Call the External Storage's create script, |
|
2822 |
# to provision a new Volume inside the External Storage |
|
2823 |
_ExtStorageAction(constants.ES_ACTION_CREATE, unique_id, str(size)) |
|
2824 |
|
|
2825 |
return ExtStorageDevice(unique_id, children, size, params) |
|
2826 |
|
|
2827 |
def Remove(self): |
|
2828 |
"""Remove the extstorage device. |
|
2829 |
|
|
2830 |
""" |
|
2831 |
if not self.minor and not self.Attach(): |
|
2832 |
# The extstorage device doesn't exist. |
|
2833 |
return |
|
2834 |
|
|
2835 |
# First shutdown the device (remove mappings). |
|
2836 |
self.Shutdown() |
|
2837 |
|
|
2838 |
# Call the External Storage's remove script, |
|
2839 |
# to remove the Volume from the External Storage |
|
2840 |
_ExtStorageAction(constants.ES_ACTION_REMOVE, self.unique_id) |
|
2841 |
|
|
2842 |
def Rename(self, new_id): |
|
2843 |
"""Rename this device. |
|
2844 |
|
|
2845 |
""" |
|
2846 |
pass |
|
2847 |
|
|
2848 |
def Attach(self): |
|
2849 |
"""Attach to an existing extstorage device. |
|
2850 |
|
|
2851 |
This method maps the extstorage volume that matches our name with |
|
2852 |
a corresponding block device and then attaches to this device. |
|
2853 |
|
|
2854 |
""" |
|
2855 |
self.attached = False |
|
2856 |
|
|
2857 |
# Call the External Storage's attach script, |
|
2858 |
# to attach an existing Volume to a block device under /dev |
|
2859 |
self.dev_path = _ExtStorageAction(constants.ES_ACTION_ATTACH, |
|
2860 |
self.unique_id) |
|
2861 |
|
|
2862 |
try: |
|
2863 |
st = os.stat(self.dev_path) |
|
2864 |
except OSError, err: |
|
2865 |
logging.error("Error stat()'ing %s: %s", self.dev_path, str(err)) |
|
2866 |
return False |
|
2867 |
|
|
2868 |
if not stat.S_ISBLK(st.st_mode): |
|
2869 |
logging.error("%s is not a block device", self.dev_path) |
|
2870 |
return False |
|
2871 |
|
|
2872 |
self.major = os.major(st.st_rdev) |
|
2873 |
self.minor = os.minor(st.st_rdev) |
|
2874 |
self.attached = True |
|
2875 |
|
|
2876 |
return True |
|
2877 |
|
|
2878 |
def Assemble(self): |
|
2879 |
"""Assemble the device. |
|
2880 |
|
|
2881 |
""" |
|
2882 |
pass |
|
2883 |
|
|
2884 |
def Shutdown(self): |
|
2885 |
"""Shutdown the device. |
|
2886 |
|
|
2887 |
""" |
|
2888 |
if not self.minor and not self.Attach(): |
|
2889 |
# The extstorage device doesn't exist. |
|
2890 |
return |
|
2891 |
|
|
2892 |
# Call the External Storage's detach script, |
|
2893 |
# to detach an existing Volume from it's block device under /dev |
|
2894 |
_ExtStorageAction(constants.ES_ACTION_DETACH, self.unique_id) |
|
2895 |
|
|
2896 |
self.minor = None |
|
2897 |
self.dev_path = None |
|
2898 |
|
|
2899 |
def Open(self, force=False): |
|
2900 |
"""Make the device ready for I/O. |
|
2901 |
|
|
2902 |
""" |
|
2903 |
pass |
|
2904 |
|
|
2905 |
def Close(self): |
|
2906 |
"""Notifies that the device will no longer be used for I/O. |
|
2907 |
|
|
2908 |
""" |
|
2909 |
pass |
|
2910 |
|
|
2911 |
def Grow(self, amount, dryrun, backingstore): |
|
2912 |
"""Grow the Volume. |
|
2913 |
|
|
2914 |
@type amount: integer |
|
2915 |
@param amount: the amount (in mebibytes) to grow with |
|
2916 |
@type dryrun: boolean |
|
2917 |
@param dryrun: whether to execute the operation in simulation mode |
|
2918 |
only, without actually increasing the size |
|
2919 |
|
|
2920 |
""" |
|
2921 |
if not backingstore: |
|
2922 |
return |
|
2923 |
if not self.Attach(): |
|
2924 |
_ThrowError("Can't attach to extstorage device during Grow()") |
|
2925 |
|
|
2926 |
if dryrun: |
|
2927 |
# we do not support dry runs of resize operations for now. |
|
2928 |
return |
|
2929 |
|
|
2930 |
new_size = self.size + amount |
|
2931 |
|
|
2932 |
# Call the External Storage's grow script, |
|
2933 |
# to grow an existing Volume inside the External Storage |
|
2934 |
_ExtStorageAction(constants.ES_ACTION_GROW, self.unique_id, |
|
2935 |
str(self.size), grow=str(new_size)) |
|
2936 |
|
|
2937 |
def SetInfo(self, text): |
|
2938 |
"""Update metadata with info text. |
|
2939 |
|
|
2940 |
""" |
|
2941 |
# Replace invalid characters |
|
2942 |
text = re.sub("^[^A-Za-z0-9_+.]", "_", text) |
|
2943 |
text = re.sub("[^-A-Za-z0-9_+.]", "_", text) |
|
2944 |
|
|
2945 |
# Only up to 128 characters are allowed |
|
2946 |
text = text[:128] |
|
2947 |
|
|
2948 |
# Call the External Storage's setinfo script, |
|
2949 |
# to set metadata for an existing Volume inside the External Storage |
|
2950 |
_ExtStorageAction(constants.ES_ACTION_SETINFO, self.unique_id, |
|
2951 |
metadata=text) |
|
2952 |
|
|
2953 |
|
|
2954 |
def _ExtStorageAction(action, unique_id, size=None, grow=None, metadata=None): |
|
2955 |
"""Take an External Storage action. |
|
2956 |
|
|
2957 |
Take an External Storage action concerning or affecting |
|
2958 |
a specific Volume inside the External Storage. |
|
2959 |
|
|
2960 |
@type action: string |
|
2961 |
@param action: which action to perform. One of: |
|
2962 |
create / remove / grow / attach / detach |
|
2963 |
@type unique_id: tuple (driver, vol_name) |
|
2964 |
@param unique_id: a tuple containing the type of ExtStorage (driver) |
|
2965 |
and the Volume name |
|
2966 |
@type size: integer |
|
2967 |
@param size: the size of the Volume in mebibytes |
|
2968 |
@type grow: integer |
|
2969 |
@param grow: the new size in mebibytes (after grow) |
|
2970 |
@type metadata: string |
|
2971 |
@param metadata: metadata info of the Volume, for use by the provider |
|
2972 |
@rtype: None or a block device path (during attach) |
|
2973 |
|
|
2974 |
""" |
|
2975 |
driver, vol_name = unique_id |
|
2976 |
|
|
2977 |
# Create an External Storage instance of type `driver' |
|
2978 |
status, inst_es = ExtStorageFromDisk(driver) |
|
2979 |
if not status: |
|
2980 |
_ThrowError("%s" % inst_es) |
|
2981 |
|
|
2982 |
# Create the basic environment for the driver's scripts |
|
2983 |
create_env = _ExtStorageEnvironment(unique_id, size, grow, metadata) |
|
2984 |
|
|
2985 |
# Do not use log file for action `attach' as we need |
|
2986 |
# to get the output from RunResult |
|
2987 |
# TODO: find a way to have a log file for attach too |
|
2988 |
logfile = None |
|
2989 |
if action is not constants.ES_ACTION_ATTACH: |
|
2990 |
logfile = _VolumeLogName(action, driver, vol_name) |
|
2991 |
|
|
2992 |
# Make sure the given action results in a valid script |
|
2993 |
if action not in constants.ES_SCRIPTS: |
|
2994 |
_ThrowError("Action '%s' doesn't result in a valid ExtStorage script" % |
|
2995 |
action) |
|
2996 |
|
|
2997 |
# Find out which external script to run according the given action |
|
2998 |
script_name = action + "_script" |
|
2999 |
script = getattr(inst_es, script_name) |
|
3000 |
|
|
3001 |
# Run the external script |
|
3002 |
result = utils.RunCmd([script], env=create_env, |
|
3003 |
cwd=inst_es.path, output=logfile,) |
|
3004 |
if result.failed: |
|
3005 |
logging.error("External storage's %s command '%s' returned" |
|
3006 |
" error: %s, logfile: %s, output: %s", |
|
3007 |
action, result.cmd, result.fail_reason, |
|
3008 |
logfile, result.output) |
|
3009 |
|
|
3010 |
# If logfile is 'None' (during attach), it breaks TailFile |
|
3011 |
# TODO: have a log file for attach too |
|
3012 |
if action is not constants.ES_ACTION_ATTACH: |
|
3013 |
lines = [utils.SafeEncode(val) |
|
3014 |
for val in utils.TailFile(logfile, lines=20)] |
|
3015 |
else: |
|
3016 |
lines = result.output[-20:] |
|
3017 |
|
|
3018 |
_ThrowError("External storage's %s script failed (%s), last" |
|
3019 |
" lines of output:\n%s", |
|
3020 |
action, result.fail_reason, "\n".join(lines)) |
|
3021 |
|
|
3022 |
if action == constants.ES_ACTION_ATTACH: |
|
3023 |
return result.stdout |
|
3024 |
|
|
3025 |
|
|
3026 |
def ExtStorageFromDisk(name, base_dir=None): |
|
3027 |
"""Create an ExtStorage instance from disk. |
|
3028 |
|
|
3029 |
This function will return an ExtStorage instance |
|
3030 |
if the given name is a valid ExtStorage name. |
|
3031 |
|
|
3032 |
@type base_dir: string |
|
3033 |
@keyword base_dir: Base directory containing ExtStorage installations. |
|
3034 |
Defaults to a search in all the ES_SEARCH_PATH dirs. |
|
3035 |
@rtype: tuple |
|
3036 |
@return: True and the ExtStorage instance if we find a valid one, or |
|
3037 |
False and the diagnose message on error |
|
3038 |
|
|
3039 |
""" |
|
3040 |
if base_dir is None: |
|
3041 |
es_base_dir = pathutils.ES_SEARCH_PATH |
|
3042 |
else: |
|
3043 |
es_base_dir = [base_dir] |
|
3044 |
|
|
3045 |
es_dir = utils.FindFile(name, es_base_dir, os.path.isdir) |
|
3046 |
|
|
3047 |
if es_dir is None: |
|
3048 |
return False, ("Directory for External Storage Provider %s not" |
|
3049 |
" found in search path" % name) |
|
3050 |
|
|
3051 |
# ES Files dictionary, we will populate it with the absolute path |
|
3052 |
# names; if the value is True, then it is a required file, otherwise |
|
3053 |
# an optional one |
|
3054 |
es_files = dict.fromkeys(constants.ES_SCRIPTS, True) |
|
3055 |
|
|
3056 |
for filename in es_files: |
|
3057 |
es_files[filename] = utils.PathJoin(es_dir, filename) |
|
3058 |
|
|
3059 |
try: |
|
3060 |
st = os.stat(es_files[filename]) |
|
3061 |
except EnvironmentError, err: |
|
3062 |
return False, ("File '%s' under path '%s' is missing (%s)" % |
|
3063 |
(filename, es_dir, utils.ErrnoOrStr(err))) |
|
3064 |
|
|
3065 |
if not stat.S_ISREG(stat.S_IFMT(st.st_mode)): |
|
3066 |
return False, ("File '%s' under path '%s' is not a regular file" % |
|
3067 |
(filename, es_dir)) |
|
3068 |
|
|
3069 |
if filename in constants.ES_SCRIPTS: |
|
3070 |
if stat.S_IMODE(st.st_mode) & stat.S_IXUSR != stat.S_IXUSR: |
|
3071 |
return False, ("File '%s' under path '%s' is not executable" % |
|
3072 |
(filename, es_dir)) |
|
3073 |
|
|
3074 |
es_obj = \ |
|
3075 |
objects.ExtStorage(name=name, path=es_dir, |
|
3076 |
create_script=es_files[constants.ES_SCRIPT_CREATE], |
|
3077 |
remove_script=es_files[constants.ES_SCRIPT_REMOVE], |
|
3078 |
grow_script=es_files[constants.ES_SCRIPT_GROW], |
|
3079 |
attach_script=es_files[constants.ES_SCRIPT_ATTACH], |
|
3080 |
detach_script=es_files[constants.ES_SCRIPT_DETACH], |
|
3081 |
setinfo_script=es_files[constants.ES_SCRIPT_SETINFO]) |
|
3082 |
return True, es_obj |
|
3083 |
|
|
3084 |
|
|
3085 |
def _ExtStorageEnvironment(unique_id, size=None, grow=None, metadata=None): |
|
3086 |
"""Calculate the environment for an External Storage script. |
|
3087 |
|
|
3088 |
@type unique_id: tuple (driver, vol_name) |
|
3089 |
@param unique_id: ExtStorage pool and name of the Volume |
|
3090 |
@type size: string |
|
3091 |
@param size: size of the Volume (in mebibytes) |
|
3092 |
@type grow: string |
|
3093 |
@param grow: new size of Volume after grow (in mebibytes) |
|
3094 |
@type metadata: string |
|
3095 |
@param metadata: metadata info of the Volume |
|
3096 |
@rtype: dict |
|
3097 |
@return: dict of environment variables |
|
3098 |
|
|
3099 |
""" |
|
3100 |
vol_name = unique_id[1] |
|
3101 |
|
|
3102 |
result = {} |
|
3103 |
result["VOL_NAME"] = vol_name |
|
3104 |
|
|
3105 |
if size is not None: |
|
3106 |
result["VOL_SIZE"] = size |
|
3107 |
|
|
3108 |
if grow is not None: |
|
3109 |
result["VOL_NEW_SIZE"] = grow |
|
3110 |
|
|
3111 |
if metadata is not None: |
|
3112 |
result["VOL_METADATA"] = metadata |
|
3113 |
|
|
3114 |
return result |
|
3115 |
|
|
3116 |
|
|
3117 |
def _VolumeLogName(kind, es_name, volume): |
|
3118 |
"""Compute the ExtStorage log filename for a given Volume and operation. |
|
3119 |
|
|
3120 |
@type kind: string |
|
3121 |
@param kind: the operation type (e.g. create, remove etc.) |
|
3122 |
@type es_name: string |
|
3123 |
@param es_name: the ExtStorage name |
|
3124 |
@type volume: string |
|
3125 |
@param volume: the name of the Volume inside the External Storage |
|
3126 |
|
|
3127 |
""" |
|
3128 |
# Check if the extstorage log dir is a valid dir |
|
3129 |
if not os.path.isdir(pathutils.LOG_ES_DIR): |
|
3130 |
_ThrowError("Cannot find log directory: %s", pathutils.LOG_ES_DIR) |
|
3131 |
|
|
3132 |
# TODO: Use tempfile.mkstemp to create unique filename |
|
3133 |
base = ("%s-%s-%s-%s.log" % |
|
3134 |
(kind, es_name, volume, utils.TimestampForFilename())) |
|
3135 |
return utils.PathJoin(pathutils.LOG_ES_DIR, base) |
|
3136 |
|
|
3137 |
|
|
2789 | 3138 |
DEV_MAP = { |
2790 | 3139 |
constants.LD_LV: LogicalVolume, |
2791 | 3140 |
constants.LD_DRBD8: DRBD8, |
2792 | 3141 |
constants.LD_BLOCKDEV: PersistentBlockDevice, |
2793 | 3142 |
constants.LD_RBD: RADOSBlockDevice, |
3143 |
constants.LD_EXT: ExtStorageDevice, |
|
2794 | 3144 |
} |
2795 | 3145 |
|
2796 | 3146 |
if constants.ENABLE_FILE_STORAGE or constants.ENABLE_SHARED_FILE_STORAGE: |
b/lib/client/gnt_cluster.py | ||
---|---|---|
452 | 452 |
ToStdout(" - primary ip version: %d", result["primary_ip_version"]) |
453 | 453 |
ToStdout(" - preallocation wipe disks: %s", result["prealloc_wipe_disks"]) |
454 | 454 |
ToStdout(" - OS search path: %s", utils.CommaJoin(pathutils.OS_SEARCH_PATH)) |
455 |
ToStdout(" - ExtStorage Providers search path: %s", |
|
456 |
utils.CommaJoin(pathutils.ES_SEARCH_PATH)) |
|
455 | 457 |
|
456 | 458 |
ToStdout("Default node parameters:") |
457 | 459 |
_PrintGroupedParams(result["ndparams"], roman=opts.roman_integers) |
b/lib/cmdlib.py | ||
---|---|---|
8849 | 8849 |
self._GoReconnect(False) |
8850 | 8850 |
self._WaitUntilSync() |
8851 | 8851 |
|
8852 |
# If the instance's disk template is `rbd' and there was a successful
|
|
8853 |
# migration, unmap the device from the source node. |
|
8854 |
if self.instance.disk_template == constants.DT_RBD:
|
|
8852 |
# If the instance's disk template is `rbd' or `ext' and there was a
|
|
8853 |
# successful migration, unmap the device from the source node.
|
|
8854 |
if self.instance.disk_template in (constants.DT_RBD, constants.DT_EXT):
|
|
8855 | 8855 |
disks = _ExpandCheckDisks(instance, instance.disks) |
8856 | 8856 |
self.feedback_fn("* unmapping instance's disks from %s" % source_node) |
8857 | 8857 |
for disk in disks: |
... | ... | |
9101 | 9101 |
_DISK_TEMPLATE_NAME_PREFIX = { |
9102 | 9102 |
constants.DT_PLAIN: "", |
9103 | 9103 |
constants.DT_RBD: ".rbd", |
9104 |
constants.DT_EXT: ".ext", |
|
9104 | 9105 |
} |
9105 | 9106 |
|
9106 | 9107 |
|
... | ... | |
9110 | 9111 |
constants.DT_SHARED_FILE: constants.LD_FILE, |
9111 | 9112 |
constants.DT_BLOCK: constants.LD_BLOCKDEV, |
9112 | 9113 |
constants.DT_RBD: constants.LD_RBD, |
9114 |
constants.DT_EXT: constants.LD_EXT, |
|
9113 | 9115 |
} |
9114 | 9116 |
|
9115 | 9117 |
|
... | ... | |
9189 | 9191 |
disk[constants.IDISK_ADOPT]) |
9190 | 9192 |
elif template_name == constants.DT_RBD: |
9191 | 9193 |
logical_id_fn = lambda idx, _, disk: ("rbd", names[idx]) |
9194 |
elif template_name == constants.DT_EXT: |
|
9195 |
logical_id_fn = lambda idx, _, disk: ("ext", names[idx]) |
|
9192 | 9196 |
else: |
9193 | 9197 |
raise errors.ProgrammerError("Unknown disk template '%s'" % template_name) |
9194 | 9198 |
|
... | ... | |
10433 | 10437 |
# Any function that checks prerequisites can be placed here. |
10434 | 10438 |
# Check if there is enough space on the RADOS cluster. |
10435 | 10439 |
_CheckRADOSFreeSpace() |
10440 |
elif self.op.disk_template == constants.DT_EXT: |
|
10441 |
# FIXME: Function that checks prereqs if needed |
|
10442 |
pass |
|
10436 | 10443 |
else: |
10437 | 10444 |
# Check lv size requirements, if not adopting |
10438 | 10445 |
req_sizes = _ComputeDiskSizePerVG(self.op.disk_template, self.disks) |
... | ... | |
12318 | 12325 |
|
12319 | 12326 |
if instance.disk_template not in (constants.DT_FILE, |
12320 | 12327 |
constants.DT_SHARED_FILE, |
12321 |
constants.DT_RBD): |
|
12328 |
constants.DT_RBD, |
|
12329 |
constants.DT_EXT): |
|
12322 | 12330 |
# TODO: check the free disk space for file, when that feature will be |
12323 | 12331 |
# supported |
12324 | 12332 |
_CheckNodesFreeDiskPerVG(self, nodenames, |
b/lib/constants.py | ||
---|---|---|
369 | 369 |
DT_SHARED_FILE = "sharedfile" |
370 | 370 |
DT_BLOCK = "blockdev" |
371 | 371 |
DT_RBD = "rbd" |
372 |
DT_EXT = "ext" |
|
372 | 373 |
|
373 | 374 |
# the set of network-mirrored disk templates |
374 | 375 |
DTS_INT_MIRROR = compat.UniqueFrozenset([DT_DRBD8]) |
... | ... | |
378 | 379 |
DT_SHARED_FILE, |
379 | 380 |
DT_BLOCK, |
380 | 381 |
DT_RBD, |
382 |
DT_EXT, |
|
381 | 383 |
]) |
382 | 384 |
|
383 | 385 |
# the set of non-lvm-based disk templates |
... | ... | |
387 | 389 |
DT_SHARED_FILE, |
388 | 390 |
DT_BLOCK, |
389 | 391 |
DT_RBD, |
392 |
DT_EXT, |
|
390 | 393 |
]) |
391 | 394 |
|
392 | 395 |
# the set of disk templates which can be grown |
... | ... | |
396 | 399 |
DT_FILE, |
397 | 400 |
DT_SHARED_FILE, |
398 | 401 |
DT_RBD, |
402 |
DT_EXT, |
|
399 | 403 |
]) |
400 | 404 |
|
401 | 405 |
# the set of disk templates that allow adoption |
... | ... | |
422 | 426 |
LD_FILE = "file" |
423 | 427 |
LD_BLOCKDEV = "blockdev" |
424 | 428 |
LD_RBD = "rbd" |
429 |
LD_EXT = "ext" |
|
425 | 430 |
LOGICAL_DISK_TYPES = compat.UniqueFrozenset([ |
426 | 431 |
LD_LV, |
427 | 432 |
LD_DRBD8, |
428 | 433 |
LD_FILE, |
429 | 434 |
LD_BLOCKDEV, |
430 | 435 |
LD_RBD, |
436 |
LD_EXT, |
|
431 | 437 |
]) |
432 | 438 |
|
433 | 439 |
LDS_BLOCK = compat.UniqueFrozenset([ |
... | ... | |
435 | 441 |
LD_DRBD8, |
436 | 442 |
LD_BLOCKDEV, |
437 | 443 |
LD_RBD, |
444 |
LD_EXT, |
|
438 | 445 |
]) |
439 | 446 |
|
440 | 447 |
# drbd constants |
... | ... | |
535 | 542 |
DT_SHARED_FILE, |
536 | 543 |
DT_BLOCK, |
537 | 544 |
DT_RBD, |
545 |
DT_EXT |
|
538 | 546 |
]) |
539 | 547 |
|
540 | 548 |
FILE_DRIVER = compat.UniqueFrozenset([FD_LOOP, FD_BLKTAP]) |
... | ... | |
661 | 669 |
OS_VALIDATE_PARAMETERS = "parameters" |
662 | 670 |
OS_VALIDATE_CALLS = compat.UniqueFrozenset([OS_VALIDATE_PARAMETERS]) |
663 | 671 |
|
672 |
# External Storage (ES) related constants |
|
673 |
ES_ACTION_CREATE = "create" |
|
674 |
ES_ACTION_REMOVE = "remove" |
|
675 |
ES_ACTION_GROW = "grow" |
|
676 |
ES_ACTION_ATTACH = "attach" |
|
677 |
ES_ACTION_DETACH = "detach" |
|
678 |
ES_ACTION_SETINFO = "setinfo" |
|
679 |
|
|
680 |
ES_SCRIPT_CREATE = ES_ACTION_CREATE |
|
681 |
ES_SCRIPT_REMOVE = ES_ACTION_REMOVE |
|
682 |
ES_SCRIPT_GROW = ES_ACTION_GROW |
|
683 |
ES_SCRIPT_ATTACH = ES_ACTION_ATTACH |
|
684 |
ES_SCRIPT_DETACH = ES_ACTION_DETACH |
|
685 |
ES_SCRIPT_SETINFO = ES_ACTION_SETINFO |
|
686 |
ES_SCRIPTS = frozenset([ |
|
687 |
ES_SCRIPT_CREATE, |
|
688 |
ES_SCRIPT_REMOVE, |
|
689 |
ES_SCRIPT_GROW, |
|
690 |
ES_SCRIPT_ATTACH, |
|
691 |
ES_SCRIPT_DETACH, |
|
692 |
ES_SCRIPT_SETINFO |
|
693 |
]) |
|
694 |
|
|
664 | 695 |
# ssh constants |
665 | 696 |
SSH = "ssh" |
666 | 697 |
SCP = "scp" |
... | ... | |
1936 | 1967 |
LD_RBD: { |
1937 | 1968 |
LDP_POOL: "rbd" |
1938 | 1969 |
}, |
1970 |
LD_EXT: {}, |
|
1939 | 1971 |
} |
1940 | 1972 |
|
1941 | 1973 |
# readability shortcuts |
... | ... | |
1969 | 2001 |
DT_RBD: { |
1970 | 2002 |
RBD_POOL: DISK_LD_DEFAULTS[LD_RBD][LDP_POOL] |
1971 | 2003 |
}, |
2004 |
DT_EXT: {}, |
|
1972 | 2005 |
} |
1973 | 2006 |
|
1974 | 2007 |
# we don't want to export the shortcuts |
b/lib/masterd/instance.py | ||
---|---|---|
1630 | 1630 |
constants.DT_SHARED_FILE: sum(d[constants.IDISK_SIZE] for d in disks), |
1631 | 1631 |
constants.DT_BLOCK: 0, |
1632 | 1632 |
constants.DT_RBD: sum(d[constants.IDISK_SIZE] for d in disks), |
1633 |
constants.DT_EXT: sum(d[constants.IDISK_SIZE] for d in disks), |
|
1633 | 1634 |
} |
1634 | 1635 |
|
1635 | 1636 |
if disk_template not in req_size_dict: |
b/lib/objects.py | ||
---|---|---|
602 | 602 |
|
603 | 603 |
""" |
604 | 604 |
if self.dev_type in [constants.LD_LV, constants.LD_FILE, |
605 |
constants.LD_BLOCKDEV, constants.LD_RBD]: |
|
605 |
constants.LD_BLOCKDEV, constants.LD_RBD, |
|
606 |
constants.LD_EXT]: |
|
606 | 607 |
result = [node] |
607 | 608 |
elif self.dev_type in constants.LDS_DRBD: |
608 | 609 |
result = [self.logical_id[0], self.logical_id[1]] |
... | ... | |
678 | 679 |
|
679 | 680 |
""" |
680 | 681 |
if self.dev_type in (constants.LD_LV, constants.LD_FILE, |
681 |
constants.LD_RBD): |
|
682 |
constants.LD_RBD, constants.LD_EXT):
|
|
682 | 683 |
self.size += amount |
683 | 684 |
elif self.dev_type == constants.LD_DRBD8: |
684 | 685 |
if self.children: |
... | ... | |
1235 | 1236 |
return cls.SplitNameVariant(name)[1] |
1236 | 1237 |
|
1237 | 1238 |
|
1239 |
class ExtStorage(ConfigObject): |
|
1240 |
"""Config object representing an External Storage Provider. |
|
1241 |
|
|
1242 |
""" |
|
1243 |
__slots__ = [ |
|
1244 |
"name", |
|
1245 |
"path", |
|
1246 |
"create_script", |
|
1247 |
"remove_script", |
|
1248 |
"grow_script", |
|
1249 |
"attach_script", |
|
1250 |
"detach_script", |
|
1251 |
"setinfo_script", |
|
1252 |
] |
|
1253 |
|
|
1254 |
|
|
1238 | 1255 |
class NodeHvState(ConfigObject): |
1239 | 1256 |
"""Hypvervisor state on a node. |
1240 | 1257 |
|
b/lib/pathutils.py | ||
---|---|---|
34 | 34 |
vcluster.AddNodePrefix(_autoconf.SHARED_FILE_STORAGE_DIR) |
35 | 35 |
EXPORT_DIR = vcluster.AddNodePrefix(_autoconf.EXPORT_DIR) |
36 | 36 |
OS_SEARCH_PATH = _autoconf.OS_SEARCH_PATH |
37 |
ES_SEARCH_PATH = _autoconf.ES_SEARCH_PATH |
|
37 | 38 |
SSH_CONFIG_DIR = _autoconf.SSH_CONFIG_DIR |
38 | 39 |
SYSCONFDIR = vcluster.AddNodePrefix(_autoconf.SYSCONFDIR) |
39 | 40 |
TOOLSDIR = _autoconf.TOOLSDIR |
... | ... | |
123 | 124 |
QUERY_SOCKET = SOCKET_DIR + "/ganeti-query" |
124 | 125 |
|
125 | 126 |
LOG_OS_DIR = LOG_DIR + "/os" |
127 |
LOG_ES_DIR = LOG_DIR + "/extstorage" |
|
126 | 128 |
|
127 | 129 |
# Job queue paths |
128 | 130 |
JOB_QUEUE_LOCK_FILE = QUEUE_DIR + "/lock" |
b/tools/burnin | ||
---|---|---|
466 | 466 |
constants.DT_PLAIN, |
467 | 467 |
constants.DT_DRBD8, |
468 | 468 |
constants.DT_RBD, |
469 |
constants.DT_EXT, |
|
469 | 470 |
) |
470 | 471 |
if options.disk_template not in supported_disk_templates: |
471 | 472 |
Err("Unknown disk template '%s'" % options.disk_template) |
Also available in: Unified diff