def _ExtStorageAction(action, unique_id, ext_params, size=None, grow=None, metadata=None, name=None, uuid=None, snap_name=None, snap_size=None, exclusive=None): """Take an External Storage action. Take an External Storage action concerning or affecting a specific Volume inside the External Storage. @type action: string @param action: which action to perform. One of: create / remove / grow / attach / detach / snapshot @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 @param grow: the new size in mebibytes (after grow) @type metadata: string @param metadata: metadata info of the Volume, for use by the provider @type name: string @param name: name of the Volume (objects.Disk.name) @type uuid: string @type snap_size: integer @param snap_size: the size of the snapshot @type snap_name: string @param snap_name: the name of the snapshot @type exclusive: boolean @param exclusive: Whether the Volume will be opened exclusively or not @param uuid: uuid of the Volume (objects.Disk.uuid) @rtype: None or a block device path (during attach) """ driver, vol_name = unique_id # Create an External Storage instance of type `driver' status, inst_es = ExtStorageFromDisk(driver) if not status: base.ThrowError("%s" % inst_es) # Create the basic environment for the driver's scripts create_env = _ExtStorageEnvironment(unique_id, ext_params, size, grow, metadata, name, uuid, snap_name, snap_size, exclusive) # Do not use log file for action `attach' as we need # to get the output from RunResult # TODO: find a way to have a log file for attach too logfile = None if action is not constants.ES_ACTION_ATTACH: logfile = _VolumeLogName(action, driver, vol_name) # Make sure the given action results in a valid script if action not in constants.ES_SCRIPTS: base.ThrowError( "Action '%s' doesn't result in a valid ExtStorage script" % action) # Find out which external script to run according the given action script_name = action + "_script" script = getattr(inst_es, script_name) # Here script is either a valid file path or None if the script is optional if not script: logging.info( "Optional action '%s' is not supported by provider '%s'," " skipping", action, driver) return # Run the external script # pylint: disable=E1103 result = utils.RunCmd( [script], env=create_env, cwd=inst_es.path, output=logfile, ) if result.failed: logging.error( "External storage's %s command '%s' returned" " error: %s, logfile: %s, output: %s", action, result.cmd, result.fail_reason, logfile, result.output) # If logfile is 'None' (during attach), it breaks TailFile # TODO: have a log file for attach too if action is not constants.ES_ACTION_ATTACH: lines = [ utils.SafeEncode(val) for val in utils.TailFile(logfile, lines=20) ] else: lines = result.output.splitlines()[-20:] base.ThrowError( "External storage's %s script failed (%s), last" " lines of output:\n%s", action, result.fail_reason, "\n".join(lines)) if action == constants.ES_ACTION_ATTACH: return result.stdout
def testUnicode(self): # 1024 is high enough to catch non-direct ASCII mappings for i in range(1024): txt = utils.SafeEncode(chr(i)) self.assertEqual(txt, utils.SafeEncode(txt))
def testDoubleEncode(self): for i in range(255): txt = utils.SafeEncode(chr(i)) self.assertEqual(txt, utils.SafeEncode(txt))
def testAscii(self): for txt in [string.digits, string.ascii_letters, string.punctuation]: self.assertEqual(txt, utils.SafeEncode(txt))
def testDoubleEncode(self): for i in range(255): txt = utils.SafeEncode(chr(i)) self.failUnlessEqual(txt, utils.SafeEncode(txt))
def testAscii(self): for txt in [string.digits, string.letters, string.punctuation]: self.failUnlessEqual(txt, utils.SafeEncode(txt))