def run(innerself):
     innerself.starttime = datetime.datetime.utcnow()
     innerself.reporttime = innerself.starttime
     try:
         client = SwiftProvider.getConnection(
             innerself.clientParams)
         with open(innerself.toFilename, 'w') as openFile:
             SwiftProvider.doSwiftDownload(
                 client,
                 innerself.container,
                 innerself.fromFilename,
                 openFile,
                 progress=innerself._progressReport)
         innerself.succeeded = True
     except swiftclient.exceptions.ClientException as e:
         os.remove(innerself.toFilename)
         if e.http_status == 404 or e.http_status == 409:
             self.log.exception(
                 "Download of object '%s' returned %d",
                 innerself.fromFilename, e.http_status)
             self.log.warning(
                 "Step will not fail as this file was likely but not yet removed from the container"
             )
             innerself.succeeded = True
         else:
             self.log.exception("Download of object '%s' failed")
         innerself.httpstatus = e.http_status
     except:
         os.remove(innerself.toFilename)
         self.log.exception("Download of object '%s' failed",
                            innerself.fromFilename)
         innerself.succeeded = False
     return innerself.succeeded
Exemple #2
0
 def prep(self, options):
     (clientParams,
      account) = SwiftProvider.getAccount(self.engine, options['account'],
                                          'prep')
     client = SwiftProvider.getConnection(clientParams)
     if not self._isNoop(options):
         SwiftProvider.ensureContainer(client, options['to-container'])
     self.log.passed()
     return True
    def push(self, options):

        #Execute the account section to get the account info
        (clientParams,
         account) = SwiftProvider.getAccount(self.engine, options['account'],
                                             'push')
        client = SwiftProvider.getConnection(clientParams)

        containerMatcher = ','.join(
            options['containers'].split('\n')).split(',')

        targetedContainers = SwiftProvider.getAccountListing(
            client, containerMatcher)

        for ctrname, container in targetedContainers.iteritems():
            targetedObjects = SwiftProvider.getContainerListing(
                client, ctrname)

            self.log.debug("In Container: %s", ctrname)
            containerlen = len(targetedObjects)
            self.log.debug("Items in container to examine: %d", containerlen)
            for objectName, objectShort in targetedObjects.iteritems():
                objectDetails = client.head_object(ctrname, objectName)
                if 'x-object-manifest' in objectDetails:
                    #Get the pointer(s) to the real object(s)
                    manifest = objectDetails['x-object-manifest']
                    if '/' not in manifest:
                        self.log.info(
                            "The object manifest for '%s' is not well formed: %s",
                            objectName, manifest)
                        self.log.info("  --- skipping")
                        continue
                    realcontainer, realobject = manifest.split('/', 1)
                    realobjects = SwiftProvider.getContainerListing(
                        client, realcontainer, ["%s*" % realobject])
                    if len(realobjects) == 0:
                        #The object DNE
                        self.log.debug(
                            "The object link '%s' from '%s' didn't have a referant - deleting link file",
                            manifest, objectName)
                        client.delete_object(ctrname, objectName)
                        containerlen = containerlen - 1
                    else:
                        self.log.debug(
                            "The object link '%s' from '%s' still has a referant",
                            manifest, objectName)
                else:
                    self.log.debug("Object '%s' is not a link", objectName)
                    self.log.devdebug("   %s", str(objectDetails))
            if containerlen == 0:
                self.log.debug(
                    "Container: %s is now empty, removing container", ctrname)
                client.delete_container(ctrname)

        self.log.passed()
        return True
 def run(innerself):
     try:
         client = SwiftProvider.getConnection(clientParams)
         response = {}
         deleteat = 9999999999
         if secondsToExpire is not None:
             deleteat = secondsToExpire
         client.put_object(innerself.toContainer,
                           innerself.objectTarget,
                           None,
                           headers={
                               'X-Copy-From':
                               '%s/%s' % (options['from-container'],
                                          innerself.objectTarget),
                               'X-Object-Meta-CreateTime':
                               str(time.time()),
                               'X-Delete-At':
                               deleteat
                           },
                           response_dict=response)
         innerself.succeeded = True
     except swiftclient.exceptions.ClientException as e:
         if e.http_status == 404 or e.http_status == 409:
             self.log.warning("Copy of object '%s/%s' returned: %d",
                              options['from-container'],
                              innerself.objectTarget, e.http_status)
             self.log.warning(
                 "Step will not fail as this file was likely deleted but not yet removed from the container"
             )
             innerself.succeeded = True
         else:
             self.log.exception("Copy of object '%s/%s' failed",
                                options['from-container'],
                                innerself.objectTarget)
    def passed__push(self, phase, options, instance, instancedict):
        #Get just the id of the wrapper
        wrapperid = options['wrapper']
        if '@' in wrapperid:
            wrapperid = wrapperid.split('@')[1]
        if '__wrapper__%s' % wrapperid not in self.env.env:
            self.log.passed()
            self.log.info(
                "Wrapper %s is not in use, artefact will not be put in the wrapper",
                wrapperid)
            return False
        result = self.engine.launchStep(options['wrapper'], 'getinfo')
        if result is None or not result._didPass():
            self.log.failed()
            self.log.error("Wrapper '%s' is invalid", self['wrapper'])
            return False
        toContainer, account = result._getReturnValue('getinfo')
        swiftAccount, _ = SwiftProvider.getAccount(self.engine, account,
                                                   'push')
        client = SwiftProvider.getConnection(swiftAccount)

        objects = instance._getPushedObjects()
        for fromContainer, objectName in objects:
            self.log.debug("Linking '%s'/'%s' to '%s'", fromContainer,
                           objectName, toContainer)
            headers = {
                'X-Object-Manifest': '%s/%s' % (fromContainer, objectName),
                'X-Object-Meta-CreateTime': str(time.time())
            }
            putResult = {}
            client.put_object(toContainer,
                              objectName,
                              None,
                              headers=headers,
                              response_dict=putResult)
        self.log.passed()
        return True
Exemple #6
0
    def push(self, options):
        (clientParams,
         account) = SwiftProvider.getAccount(self.engine, options['account'],
                                             "push")
        client = SwiftProvider.getConnection(clientParams)
        filematchers = ['*']
        if 'files' in options:
            filematchers = ','.join(options['files'].split('\n')).split(',')

        targetedObjects = SwiftProvider.getContainerListing(
            client, options['container'], filematchers,
            'latest-only' in options and options['latest-only'] == 'True')

        targetPath = self.engine.resultsDir
        if 'result-dir' in options:
            targetPath = options['result-dir']

        threads = []

        for filename, (data, _) in targetedObjects.iteritems():
            self.objects.append((options['container'], filename))

            if not self._isNoop(options):
                headers = {
                    'X-Object-Manifest':
                    '%s/%s' % (options['container'], filename),
                    'X-Object-Meta-CreateTime': str(time.time())
                }
                putResult = {}
                client.put_object(options['to-container'],
                                  filename,
                                  None,
                                  headers=headers,
                                  response_dict=putResult)

        self.log.passed()
        return True
Exemple #7
0
    def prep(self, options):
        self._dontValidateFiles()
        #Execute the account section to get the account info
        (clientParams,
         account) = SwiftProvider.getAccount(self.engine, options['account'],
                                             'prep')
        client = SwiftProvider.getConnection(clientParams)
        SwiftProvider.ensureContainer(client, options['backup'])
        if 'access' in options:
            SwiftProvider.setContainerAccounts(self.engine, 'Read', client,
                                               options['backup'],
                                               options['access'], 'prep')

        mycontainer = client.get_container(options['container'])
        mycontainer[0]['name'] = options['container']
        self.log.devdebug("Container obtained: %s", str(mycontainer))
        SwiftProvider.addDetailsToAccountListing(client, [mycontainer])
        headers = SwiftProvider.getMetadataFromContainerDict(mycontainer[0])
        headers['x-versions-location'] = urllib.quote(options['backup'])
        client.post_container(options['container'], headers)

        self.log.passed()
        return True
 def prep(self, options):
     #Ensure container exists
     connectParams, _ = SwiftProvider.getAccount(self.engine,
                                                 options['account'],
                                                 self.engine.getPhase())
     client = SwiftProvider.getConnection(connectParams)
     SwiftProvider.ensureContainer(client, options['container'])
     if 'access' in options:
         SwiftProvider.setContainerAccounts(self.engine, 'Read', client,
                                            options['container'],
                                            options['access'], 'prep')
     self.log.passed()
     return self.default(options)
    def prep(self, options):
        #Execute the account section to get the account info
        (clientParams,
         account) = SwiftProvider.getAccount(self.engine, options['account'],
                                             'prep')
        client = SwiftProvider.getConnection(clientParams)

        SwiftProvider.ensureContainer(client, options['container'])
        if 'access' in options:
            SwiftProvider.setContainerAccounts(self.engine, 'Read', client,
                                               options['container'],
                                               options['access'], 'prep')
        self.log.passed()
        return True
Exemple #10
0
    def prep(self, options):
        self._dontValidateFiles()
        #Execute the account section to get the account info
        (clientParams,
         account) = SwiftProvider.getAccount(self.engine, options['account'],
                                             'prep')
        client = SwiftProvider.getConnection(clientParams)

        for froms, tos in self.mapping.iterspecs():
            for container in tos:
                containerName, _ = SwiftProvider.getContainerAndFile(
                    None, container['relLocation'])
                SwiftProvider.ensureContainer(client, containerName)
                if 'access' in options:
                    SwiftProvider.setContainerAccounts(self.engine, 'Read',
                                                       client, containerName,
                                                       options['access'],
                                                       'prep')
        self.log.passed()
        return True
    def pull(self, options):
        class DownloadThread(threading.Thread):
            def _progressReport(innerself, xmitted, total):
                if self.reportProgress:
                    currenttime = datetime.datetime.utcnow()
                    delta = currenttime - innerself.reporttime
                    if delta.seconds < 2:
                        return
                    deltaXmitted = xmitted - innerself.previousamount
                    if delta.total_seconds() > 0.0:
                        rate = float(deltaXmitted) / float(
                            delta.total_seconds()) / 1000.0
                    else:
                        rate = 0.0
                    rateunit = "KB"
                    if rate > 1000.0:
                        rate /= 1000.0
                        rateunit = "MB"
                    if rate > 1000.0:
                        rate /= 1000.0
                        rateunit = "GB"
                    innerself.previousamount = xmitted
                    innerself.reporttime = currenttime
                    percent = float(xmitted) / float(total) * 100.0
                    if percent > 100.0:
                        percent = 100.0
                    self.log.info(
                        "[%s:%s] Transferred %2.1f%% (%d out of %d - %2.2f%s/s)",
                        innerself.container, innerself.toFilename, percent,
                        xmitted, total, rate, rateunit)

            def __init__(innerself, container, fromFilename, toFilename,
                         clientParams):

                threading.Thread.__init__(innerself)
                innerself.fromFilename = fromFilename
                innerself.toFilename = toFilename
                innerself.clientParams = clientParams
                innerself.container = container
                innerself.succeeded = False
                innerself.httpstatus = None
                innerself.starttime = None
                innerself.reporttime = None
                innerself.previousamount = 0

            def run(innerself):
                innerself.starttime = datetime.datetime.utcnow()
                innerself.reporttime = innerself.starttime
                try:
                    client = SwiftProvider.getConnection(
                        innerself.clientParams)
                    with open(innerself.toFilename, 'w') as openFile:
                        SwiftProvider.doSwiftDownload(
                            client,
                            innerself.container,
                            innerself.fromFilename,
                            openFile,
                            progress=innerself._progressReport)
                    innerself.succeeded = True
                except swiftclient.exceptions.ClientException as e:
                    os.remove(innerself.toFilename)
                    if e.http_status == 404 or e.http_status == 409:
                        self.log.exception(
                            "Download of object '%s' returned %d",
                            innerself.fromFilename, e.http_status)
                        self.log.warning(
                            "Step will not fail as this file was likely but not yet removed from the container"
                        )
                        innerself.succeeded = True
                    else:
                        self.log.exception("Download of object '%s' failed")
                    innerself.httpstatus = e.http_status
                except:
                    os.remove(innerself.toFilename)
                    self.log.exception("Download of object '%s' failed",
                                       innerself.fromFilename)
                    innerself.succeeded = False
                return innerself.succeeded

            def passed(innerself):
                return innerself.succeeded or \
                    ('ignore-fail' in options and options['ignore-fail'] == 'True')

            def httpstatus(innerself):
                if self.httpstatus is None:
                    return 200
                else:
                    return self.httpstatus

        self.reportProgress = True
        if 'progress' in options:
            self.reportProgress = options['progress'] == "True"
        ignorefail = 'ignore-fail' in options and options[
            'ignore-fail'] == 'True'
        (clientParams,
         account) = SwiftProvider.getAccount(self.engine, options['account'],
                                             "pull")
        client = SwiftProvider.getConnection(clientParams)
        filematchers = ['*']
        if 'files' in options:
            filematchers = ','.join(options['files'].split('\n')).split(',')

        try:
            targetedObjects = SwiftProvider.getContainerListing(
                client, options['container'], filematchers,
                'latest-only' in options and options['latest-only'] == 'True')
        except Exception as e:
            self.log.exception("Pull of the container failed")
            if not ignorefail:
                raise e
            else:
                self.log.passed()
                return False
        self.log.devdebug("targeted objects: %s", str(targetedObjects))

        targetPath = self.engine.resultsDir
        if 'result-dir' in options:
            targetPath = options['result-dir']

        threads = []

        for filename, (data, _) in targetedObjects.iteritems():
            targetFile = os.path.join(targetPath, filename)

            #Does the path exist?
            if os.path.exists(targetFile):
                #Yes, get the etag for the object
                eTag = data['hash']

                #get the md5 for the local file if there is one
                md5 = None
                with open(targetFile) as openFile:
                    md5 = self._fileMD5(openFile)
                if md5 == eTag:
                    self.log.info(
                        "'%s' is already up-to-date, not redownloading",
                        targetFile)
                    continue

            self._ensureDirectoryExists(targetFile)

            threads.append(
                DownloadThread(options['container'], filename, targetFile,
                               clientParams))
            threads[-1].start()

        for thread in threads:
            thread.join()
            if not thread.passed() and not ignorefail:
                self.log.failed()
                return False
        self.log.passed()
        return True
Exemple #12
0
    def push(self, options):
        class UploadReportThread(threading.Thread):
            def __init__(innerself, total, fileobject, container, filename):
                threading.Thread.__init__(innerself)
                innerself.stopping = False
                innerself.total = total
                innerself.fileobject = fileobject
                innerself.container = container
                innerself.filename = filename
                innerself.starttime = None
                innerself.reporttime = None
                innerself.previousamount = 0

            def run(innerself):
                innerself.starttime = datetime.datetime.utcnow()
                innerself.reporttime = innerself.starttime
                try:
                    counter = 0
                    while not innerself.stopping:
                        time.sleep(0.1)
                        counter += 1
                        if counter % 20:
                            continue
                        current = innerself.fileobject.tell()
                        percent = float(current) / float(
                            innerself.total) * 100.0
                        if not innerself.stopping:
                            currenttime = datetime.datetime.utcnow()
                            delta = currenttime - innerself.reporttime
                            deltaXmitted = current - innerself.previousamount
                            if delta.total_seconds() > 0.0:
                                rate = float(deltaXmitted) / float(
                                    delta.total_seconds()) / 1000.0
                            else:
                                rate = 0.0
                            rateunit = "KB"
                            if rate > 1000.0:
                                rate /= 1000.0
                                rateunit = "MB"
                            if rate > 1000.0:
                                rate /= 1000.0
                                rateunit = "GB"
                            innerself.previousamount = current
                            innerself.reporttime = currenttime
                            if percent > 100.0:
                                percent = 100.0
                            self.log.info(
                                "[%s:%s] Transferred %d%% (%d out of %d  - %2.2f%s/s)",
                                innerself.container, innerself.filename,
                                percent, current, innerself.total, rate,
                                rateunit)
                except:
                    self.log.exception("Couldn't show progress")
                return 0

            def stop(innerself):
                innerself.stopping = True

        self.reportProgress = True
        if 'progress' in options:
            self.reportProgress = options['progress'] == 'True'
        self._dontValidateFiles()
        secondsToExpire = None
        if 'expires' in options:
            secondsToExpire = int(
                SwiftProvider.timeDeltaDisgronifier(
                    options['expires']).total_seconds())
        #Execute the account section to get the account info
        (clientParams,
         account) = SwiftProvider.getAccount(self.engine, options['account'],
                                             'push')
        client = SwiftProvider.getConnection(clientParams)

        #Upload the requested objects in the mapping
        for froms, tos in self.mapping.iterspecs():
            for filename in froms:
                relfilename = filename['relLocation']
                if relfilename.startswith('./'):
                    relfilename = relfilename[2:]
                with open(filename['location'], 'rb', 0) as openFile:
                    self.log.debug("Using raw buffer, 10240 chunk size")
                    openFile.seek(0, os.SEEK_END)
                    fileSize = openFile.tell()
                    openFile.seek(0)
                    headers = {'X-Object-Meta-CreateTime': str(time.time())}
                    if secondsToExpire is not None:
                        headers.update(
                            {'X-Delete-After': str(secondsToExpire)})
                    for container in tos:
                        containerName, toFileName = SwiftProvider.getContainerAndFile(
                            relfilename, container['relLocation'])

                        if self.reportProgress:
                            reporter = UploadReportThread(
                                fileSize, openFile, containerName, toFileName)
                            reporter.start()

                        client.put_object(containerName,
                                          toFileName,
                                          openFile,
                                          content_length=fileSize,
                                          chunk_size=10240,
                                          headers=headers)

                        if self.reportProgress:
                            reporter.stop()
                            reporter.join()

                        self.objects.append((containerName, toFileName))

        self.log.passed()
        return True
    def push(self, options):
        secondsToExpire = None
        if 'expires' in options:
            secondsToExpire = int(
                SwiftProvider.timeDeltaDisgronifier(
                    options['expires']).total_seconds())

        #Execute the account section to get the account info
        (clientParams,
         account) = SwiftProvider.getAccount(self.engine, options['account'],
                                             'push')
        client = SwiftProvider.getConnection(clientParams)

        class CopyThread(threading.Thread):
            def __init__(innerself, toContainer, objectTarget, fromContainer,
                         toObjectName):

                threading.Thread.__init__(innerself)
                innerself.fromContainer = fromContainer
                innerself.toContainer = toContainer
                innerself.objectTarget = objectTarget
                innerself.toObjectName = toObjectName
                innerself.succeeded = False

            def run(innerself):
                try:
                    client = SwiftProvider.getConnection(clientParams)
                    response = {}
                    deleteat = 9999999999
                    if secondsToExpire is not None:
                        deleteat = secondsToExpire
                    client.put_object(innerself.toContainer,
                                      innerself.objectTarget,
                                      None,
                                      headers={
                                          'X-Copy-From':
                                          '%s/%s' % (options['from-container'],
                                                     innerself.objectTarget),
                                          'X-Object-Meta-CreateTime':
                                          str(time.time()),
                                          'X-Delete-At':
                                          deleteat
                                      },
                                      response_dict=response)
                    innerself.succeeded = True
                except swiftclient.exceptions.ClientException as e:
                    if e.http_status == 404 or e.http_status == 409:
                        self.log.warning("Copy of object '%s/%s' returned: %d",
                                         options['from-container'],
                                         innerself.objectTarget, e.http_status)
                        self.log.warning(
                            "Step will not fail as this file was likely deleted but not yet removed from the container"
                        )
                        innerself.succeeded = True
                    else:
                        self.log.exception("Copy of object '%s/%s' failed",
                                           options['from-container'],
                                           innerself.objectTarget)

            def passed(innerself):
                return innerself.succeeded

        container = options['container']

        filematchers = ['*']
        if 'objects' in options:
            filematchers = ','.join(options['objects'].split('\n')).split(',')

        targetedObjects = SwiftProvider.getContainerListing(
            client, options['from-container'], filematchers,
            'latest-only' in options and options['latest-only'] == 'True')

        threads = []
        for objectTarget in targetedObjects.keys():
            #TODO: Allow a mapping to another name
            self.log.info("Copying object: '%s'", objectTarget)
            threads.append(
                CopyThread(options['container'], objectTarget,
                           options['from-container'], objectTarget))
            threads[-1].start()

        for thread in threads:
            thread.join()
            if not thread.passed():
                self.log.failed()
                return False

        self.log.passed()
        return True
Exemple #14
0
    def push(self, options):

        #Get the current time
        utcnow = datetime.datetime.utcnow()

        #Get the timeout policy
        expires = datetime.timedelta()
        if 'expires' in options:
            expires = SwiftProvider.timeDeltaDisgronifier(options['expires'])

        self.log.devdebug("UTC: %s, expires: %s", utcnow, expires)

        #Execute the account section to get the account info
        (clientParams, account) = SwiftProvider.getAccount(self.engine, options['account'], 'push')
        client = SwiftProvider.getConnection(clientParams)

        containerMatcher = ','.join(options['containers'].split('\n')).split(',')
        objectMatcher = '*'
        if 'objects' in options:
            objectMatcher = ','.join(options['objects'].split('\n')).split(',')

        targetedContainers = SwiftProvider.getAccountListing(
            client,
            containerMatcher)

        for ctrname, container in targetedContainers.iteritems():
            targetedObjects = SwiftProvider.getContainerListing(
                client,
                ctrname,
                objectMatcher,
                details=True )

            objectlist = targetedObjects.keys()
            detaillist = targetedObjects.values()

            if 'leave' in options:
                leave = int(options['leave'])
                leave = min(leave,len(targetedObjects))
                sortedvals = sorted(
                    targetedObjects.values(), 
                    key=lambda k:k[0]['x-object-meta-createtime'] )
                leaves = sortedvals[-leave:]
                sortedvals = sortedvals[:-leave]
                leaveobjects = []
                leavedetail = []
                for val in leaves:
                    leaveobjects.append(val[0]['name'])
                    leavedetail.append(val)
                objectlist = []
                detaillist = []
                for val in sortedvals:
                    objectlist.append(val[0]['name'])
                    detaillist.append(val)

                leaveObjects = zip(leaveobjects, leavedetail)
                for objectTarget, (details, filterer) in leaveObjects:
                    if 'x-delete-at' in details:
                        if details['x-delete-at'] == '9999999999':
                            continue
                        #I want to delete the "delete-at", but it doesn't
                        #  appear a way to do that
                        headers = SwiftProvider.getMetadataFromDict(details)
                        headers['x-delete-at'] = "9999999999"
                        client.post_object(
                            ctrname, 
                            objectTarget, 
                            headers=headers )
                        self.log.debug("%s/%s: Object preserved by policy", ctrname, objectTarget)

            targetedObjects = zip(objectlist, detaillist)
               
            self.log.devdebug("In Container: %s", ctrname)

            for objectTarget, (details, filterer) in targetedObjects:
                #Check to see if x-object-meta-createtime exists
                timestamp = datetime.datetime.utcfromtimestamp(
                    float(details['x-object-meta-createtime']) )

                utcexpire = timestamp + expires

                #Is the object expired according to this policy?
                if utcexpire < utcnow:
                    #Yes. Delete it.
                    client.delete_object(ctrname, objectTarget)
                    self.log.debug("%s/%s: Object deleted - aged out", ctrname, objectTarget)
                    continue

                #Does the object already have an expiration set?
                if 'x-delete-at' in details:
                    #Yes.  Check the time, is it according to this policy?
                    deltime = datetime.datetime.utcfromtimestamp(
                        float(details['x-delete-at']))
                    if utcexpire - deltime <= datetime.timedelta(minutes=1) \
                       or deltime - utcexpire <= datetime.timedelta(minutes=1):
                        #Yes.  The world is as it should be.
                        #NOTE: A minute should give plenty of time to account
                        #      for losses and, really, what's one minute
                        #      for archival?  The object won't be cleaned
                        #      out off the disk until the "expirer" service
                        #      runs and takes out the trash.
                        #      The goal is to not have to communicate for
                        #      an object that already meets the policy +/-
                        self.log.debug("%s/%s: File expiry follows policy", ctrname,objectTarget)
                        continue

                #Set the policy.
                secondsToExpire = str(int((utcexpire-utcnow).total_seconds()))
                headers = SwiftProvider.getMetadataFromDict(details)
                headers['x-delete-after'] = secondsToExpire
                client.post_object(
                    ctrname, 
                    objectTarget, 
                    headers=headers )
                self.log.debug("%s/%s: File will expire after %s seconds", ctrname, objectTarget, secondsToExpire)
        self.log.passed()
        return True