Commit 938adc87 authored by Constantinos Venetsanopoulos's avatar Constantinos Venetsanopoulos Committed by Iustin Pop
Browse files

Multiple ExtStorage Providers and ext-params



Add support for passing parameters to the ext template (ext-params).
Take advantage of disk-params, that don't seem to make much sense in
this template (ExtStorage Providers are not predefined and we don't
know their needs) and use them to pass the ext-params dynamically to
the template.

ext-params are correlated with gnt-os-interface's os-params.
All ext-params are exported to the ExtStorage Provider through it's
environment, with variables prefixed with 'EXTP_' (similarly to the
OS interface's 'OSP_' params).

ext-params are passed via the --disk option. If the disk template
is of type `ext', then any additional options passed to --disk and
are not in IDISK_PARAMS are considered ext-params e.g.:

 gnt-instance add -t ext --disk=0:size=2G,param1=value1,param2=value2

Finally, we introduce a new IDISK_PARAM called IDISK_PROVIDER, that is
mandatory for template `ext' and is used to select the desired
ExtStorage Provider. This parameter is not a valid --disk option for
any other template type.

The IDISK_PROVIDER parameter becomes the first element of the
disk's unique_id tuple e.g.:

 unique_id = ('sample_provider1', 'UUID.ext.diskX')

Example selecting different ExtStorage Providers for each disk and
passing different ext-params to them:

 -t ext --disk=0:size=2G,provider=sample_provider1,param1=value1
        --disk=1:size=3G,provider=sample_provider2,param2=value2
Signed-off-by: default avatarConstantinos Venetsanopoulos <cven@grnet.gr>
Signed-off-by: default avatarIustin Pop <iustin@google.com>
[iustin@google.com: small simplification in bdev code, pylint fixes]
Reviewed-by: default avatarIustin Pop <iustin@google.com>
parent 376631d1
......@@ -2802,6 +2802,7 @@ class ExtStorageDevice(BlockDev):
raise ValueError("Invalid configuration data %s" % str(unique_id))
self.driver, self.vol_name = unique_id
self.ext_params = params
self.major = self.minor = None
self.Attach()
......@@ -2820,7 +2821,8 @@ class ExtStorageDevice(BlockDev):
# Call the External Storage's create script,
# to provision a new Volume inside the External Storage
_ExtStorageAction(constants.ES_ACTION_CREATE, unique_id, str(size))
_ExtStorageAction(constants.ES_ACTION_CREATE, unique_id,
params, str(size))
return ExtStorageDevice(unique_id, children, size, params)
......@@ -2837,7 +2839,8 @@ class ExtStorageDevice(BlockDev):
# Call the External Storage's remove script,
# to remove the Volume from the External Storage
_ExtStorageAction(constants.ES_ACTION_REMOVE, self.unique_id)
_ExtStorageAction(constants.ES_ACTION_REMOVE, self.unique_id,
self.ext_params)
def Rename(self, new_id):
"""Rename this device.
......@@ -2857,7 +2860,7 @@ class ExtStorageDevice(BlockDev):
# Call the External Storage's attach script,
# to attach an existing Volume to a block device under /dev
self.dev_path = _ExtStorageAction(constants.ES_ACTION_ATTACH,
self.unique_id)
self.unique_id, self.ext_params)
try:
st = os.stat(self.dev_path)
......@@ -2891,7 +2894,8 @@ class ExtStorageDevice(BlockDev):
# Call the External Storage's detach script,
# to detach an existing Volume from it's block device under /dev
_ExtStorageAction(constants.ES_ACTION_DETACH, self.unique_id)
_ExtStorageAction(constants.ES_ACTION_DETACH, self.unique_id,
self.ext_params)
self.minor = None
self.dev_path = None
......@@ -2932,7 +2936,7 @@ class ExtStorageDevice(BlockDev):
# Call the External Storage's grow script,
# to grow an existing Volume inside the External Storage
_ExtStorageAction(constants.ES_ACTION_GROW, self.unique_id,
str(self.size), grow=str(new_size))
self.ext_params, str(self.size), grow=str(new_size))
def SetInfo(self, text):
"""Update metadata with info text.
......@@ -2948,10 +2952,11 @@ class ExtStorageDevice(BlockDev):
# Call the External Storage's setinfo script,
# to set metadata for an existing Volume inside the External Storage
_ExtStorageAction(constants.ES_ACTION_SETINFO, self.unique_id,
metadata=text)
self.ext_params, metadata=text)
def _ExtStorageAction(action, unique_id, size=None, grow=None, metadata=None):
def _ExtStorageAction(action, unique_id, ext_params,
size=None, grow=None, metadata=None):
"""Take an External Storage action.
Take an External Storage action concerning or affecting
......@@ -2963,6 +2968,8 @@ def _ExtStorageAction(action, unique_id, size=None, grow=None, metadata=None):
@type unique_id: tuple (driver, vol_name)
@param unique_id: a tuple containing the type of ExtStorage (driver)
and the Volume name
@type ext_params: dict
@param ext_params: ExtStorage parameters
@type size: integer
@param size: the size of the Volume in mebibytes
@type grow: integer
......@@ -2980,7 +2987,8 @@ def _ExtStorageAction(action, unique_id, size=None, grow=None, metadata=None):
_ThrowError("%s" % inst_es)
# Create the basic environment for the driver's scripts
create_env = _ExtStorageEnvironment(unique_id, size, grow, metadata)
create_env = _ExtStorageEnvironment(unique_id, ext_params, size,
grow, metadata)
# Do not use log file for action `attach' as we need
# to get the output from RunResult
......@@ -3053,7 +3061,9 @@ def ExtStorageFromDisk(name, base_dir=None):
# an optional one
es_files = dict.fromkeys(constants.ES_SCRIPTS, True)
for filename in es_files:
es_files[constants.ES_PARAMETERS_FILE] = True
for (filename, _) in es_files.items():
es_files[filename] = utils.PathJoin(es_dir, filename)
try:
......@@ -3071,6 +3081,16 @@ def ExtStorageFromDisk(name, base_dir=None):
return False, ("File '%s' under path '%s' is not executable" %
(filename, es_dir))
parameters = []
if constants.ES_PARAMETERS_FILE in es_files:
parameters_file = es_files[constants.ES_PARAMETERS_FILE]
try:
parameters = utils.ReadFile(parameters_file).splitlines()
except EnvironmentError, err:
return False, ("Error while reading the EXT parameters file at %s: %s" %
(parameters_file, utils.ErrnoOrStr(err)))
parameters = [v.split(None, 1) for v in parameters]
es_obj = \
objects.ExtStorage(name=name, path=es_dir,
create_script=es_files[constants.ES_SCRIPT_CREATE],
......@@ -3078,15 +3098,20 @@ def ExtStorageFromDisk(name, base_dir=None):
grow_script=es_files[constants.ES_SCRIPT_GROW],
attach_script=es_files[constants.ES_SCRIPT_ATTACH],
detach_script=es_files[constants.ES_SCRIPT_DETACH],
setinfo_script=es_files[constants.ES_SCRIPT_SETINFO])
setinfo_script=es_files[constants.ES_SCRIPT_SETINFO],
verify_script=es_files[constants.ES_SCRIPT_VERIFY],
supported_parameters=parameters)
return True, es_obj
def _ExtStorageEnvironment(unique_id, size=None, grow=None, metadata=None):
def _ExtStorageEnvironment(unique_id, ext_params,
size=None, grow=None, metadata=None):
"""Calculate the environment for an External Storage script.
@type unique_id: tuple (driver, vol_name)
@param unique_id: ExtStorage pool and name of the Volume
@type ext_params: dict
@param ext_params: the EXT parameters
@type size: string
@param size: size of the Volume (in mebibytes)
@type grow: string
......@@ -3102,6 +3127,10 @@ def _ExtStorageEnvironment(unique_id, size=None, grow=None, metadata=None):
result = {}
result["VOL_NAME"] = vol_name
# EXT params
for pname, pvalue in ext_params.items():
result["EXTP_%s" % pname.upper()] = str(pvalue)
if size is not None:
result["VOL_SIZE"] = size
......
......@@ -7302,6 +7302,7 @@ class LUInstanceRecreateDisks(LogicalUnit):
# TODO: Implement support changing VG while recreating
constants.IDISK_VG,
constants.IDISK_METAVG,
constants.IDISK_PROVIDER,
]))
 
def _RunAllocator(self):
......@@ -9192,13 +9193,26 @@ def _GenerateDiskTemplate(
elif template_name == constants.DT_RBD:
logical_id_fn = lambda idx, _, disk: ("rbd", names[idx])
elif template_name == constants.DT_EXT:
logical_id_fn = lambda idx, _, disk: ("ext", names[idx])
def logical_id_fn(idx, _, disk):
provider = disk.get(constants.IDISK_PROVIDER, None)
if provider is None:
raise errors.ProgrammerError("Disk template is %s, but '%s' is"
" not found", constants.DT_EXT,
constants.IDISK_PROVIDER)
return (provider, names[idx])
else:
raise errors.ProgrammerError("Unknown disk template '%s'" % template_name)
 
dev_type = _DISK_TEMPLATE_DEVICE_TYPE[template_name]
 
for idx, disk in enumerate(disk_info):
params = {}
# Only for the Ext template add disk_info to params
if template_name == constants.DT_EXT:
params[constants.IDISK_PROVIDER] = disk[constants.IDISK_PROVIDER]
for key in disk:
if key not in constants.IDISK_PARAMS:
params[key] = disk[key]
disk_index = idx + base_index
size = disk[constants.IDISK_SIZE]
feedback_fn("* disk %s, size %s" %
......@@ -9207,7 +9221,7 @@ def _GenerateDiskTemplate(
logical_id=logical_id_fn(idx, disk_index, disk),
iv_name="disk/%d" % disk_index,
mode=disk[constants.IDISK_MODE],
params={}))
params=params))
 
return disks
 
......@@ -9657,7 +9671,7 @@ def _ComputeDisks(op, default_vg):
@param op: The instance opcode
@param default_vg: The default_vg to assume
 
@return: The computer disks
@return: The computed disks
 
"""
disks = []
......@@ -9675,16 +9689,37 @@ def _ComputeDisks(op, default_vg):
raise errors.OpPrereqError("Invalid disk size '%s'" % size,
errors.ECODE_INVAL)
 
ext_provider = disk.get(constants.IDISK_PROVIDER, None)
if ext_provider and op.disk_template != constants.DT_EXT:
raise errors.OpPrereqError("The '%s' option is only valid for the %s"
" disk template, not %s" %
(constants.IDISK_PROVIDER, constants.DT_EXT,
op.disk_template), errors.ECODE_INVAL)
data_vg = disk.get(constants.IDISK_VG, default_vg)
new_disk = {
constants.IDISK_SIZE: size,
constants.IDISK_MODE: mode,
constants.IDISK_VG: data_vg,
}
if constants.IDISK_METAVG in disk:
new_disk[constants.IDISK_METAVG] = disk[constants.IDISK_METAVG]
if constants.IDISK_ADOPT in disk:
new_disk[constants.IDISK_ADOPT] = disk[constants.IDISK_ADOPT]
# For extstorage, demand the `provider' option and add any
# additional parameters (ext-params) to the dict
if op.disk_template == constants.DT_EXT:
if ext_provider:
new_disk[constants.IDISK_PROVIDER] = ext_provider
for key in disk:
if key not in constants.IDISK_PARAMS:
new_disk[key] = disk[key]
else:
raise errors.OpPrereqError("Missing provider for template '%s'" %
constants.DT_EXT, errors.ECODE_INVAL)
disks.append(new_disk)
 
return disks
......@@ -9751,7 +9786,8 @@ class LUInstanceCreate(LogicalUnit):
# check disks. parameter names and consistent adopt/no-adopt strategy
has_adopt = has_no_adopt = False
for disk in self.op.disks:
utils.ForceDictType(disk, constants.IDISK_PARAMS_TYPES)
if self.op.disk_template != constants.DT_EXT:
utils.ForceDictType(disk, constants.IDISK_PARAMS_TYPES)
if constants.IDISK_ADOPT in disk:
has_adopt = True
else:
......@@ -10544,6 +10580,9 @@ class LUInstanceCreate(LogicalUnit):
 
_CheckNicsBridgesExist(self, self.nics, self.pnode.name)
 
#TODO: _CheckExtParams (remotely)
# Check parameters for extstorage
# memory check on primary node
#TODO(dynmem): use MINMEM for checking
if self.op.start:
......
......@@ -676,6 +676,7 @@ ES_ACTION_GROW = "grow"
ES_ACTION_ATTACH = "attach"
ES_ACTION_DETACH = "detach"
ES_ACTION_SETINFO = "setinfo"
ES_ACTION_VERIFY = "verify"
ES_SCRIPT_CREATE = ES_ACTION_CREATE
ES_SCRIPT_REMOVE = ES_ACTION_REMOVE
......@@ -683,15 +684,19 @@ ES_SCRIPT_GROW = ES_ACTION_GROW
ES_SCRIPT_ATTACH = ES_ACTION_ATTACH
ES_SCRIPT_DETACH = ES_ACTION_DETACH
ES_SCRIPT_SETINFO = ES_ACTION_SETINFO
ES_SCRIPT_VERIFY = ES_ACTION_VERIFY
ES_SCRIPTS = frozenset([
ES_SCRIPT_CREATE,
ES_SCRIPT_REMOVE,
ES_SCRIPT_GROW,
ES_SCRIPT_ATTACH,
ES_SCRIPT_DETACH,
ES_SCRIPT_SETINFO
ES_SCRIPT_SETINFO,
ES_SCRIPT_VERIFY
])
ES_PARAMETERS_FILE = "parameters.list"
# ssh constants
SSH = "ssh"
SCP = "scp"
......@@ -1175,12 +1180,14 @@ IDISK_MODE = "mode"
IDISK_ADOPT = "adopt"
IDISK_VG = "vg"
IDISK_METAVG = "metavg"
IDISK_PROVIDER = "provider"
IDISK_PARAMS_TYPES = {
IDISK_SIZE: VTYPE_SIZE,
IDISK_MODE: VTYPE_STRING,
IDISK_ADOPT: VTYPE_STRING,
IDISK_VG: VTYPE_STRING,
IDISK_METAVG: VTYPE_STRING,
IDISK_PROVIDER: VTYPE_STRING,
}
IDISK_PARAMS = frozenset(IDISK_PARAMS_TYPES.keys())
......
......@@ -909,6 +909,9 @@ class Disk(ConfigObject):
constants.LDP_POOL: dt_params[constants.RBD_POOL],
}))
elif disk_template == constants.DT_EXT:
result.append(constants.DISK_LD_DEFAULTS[constants.LD_EXT])
return result
......@@ -1249,6 +1252,8 @@ class ExtStorage(ConfigObject):
"attach_script",
"detach_script",
"setinfo_script",
"verify_script",
"supported_parameters",
]
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment