Search in sources :

Example 1 with BucketService

use of com.instaclustr.esop.impl.BucketService in project esop by instaclustr.

the class InPlaceRestorationStrategy method restore.

@Override
public void restore(final Restorer restorer, final Operation<RestoreOperationRequest> operation) throws Exception {
    final RestoreOperationRequest request = operation.request;
    try {
        if (operation.request.restorationStrategyType != RestorationStrategyType.IN_PLACE) {
            throw new IllegalStateException(format("restorationStrategyType has to be of type '%s' in case you want to use %s, it is of type '%s'", RestorationStrategyType.IN_PLACE, InPlaceRestorationStrategy.class.getName(), operation.request.restorationStrategyType));
        }
        if (!request.skipBucketVerification) {
            try (final BucketService bucketService = bucketServiceFactoryMap.get(request.storageLocation.storageProvider).createBucketService(request)) {
                bucketService.checkBucket(request.storageLocation.bucket, false);
            }
        }
        if (operation.request.resolveHostIdFromTopology) {
            final NodeTopology nodeTopology = getNodeTopology(restorer, request);
            // here, nodeTopology.nodeId is uuid, not hostname
            operation.request.storageLocation = StorageLocation.updateNodeId(operation.request.storageLocation, nodeTopology.nodeId);
            restorer.update(operation.request.storageLocation, null);
            logger.info(format("Updated storage location to %s", operation.request.storageLocation));
        }
        // 2. Download the manifest & tokens, chance to error out soon before we actually pull big files if something goes wrong here
        logger.info("Retrieving manifest for snapshot: {}", request.snapshotTag);
        final Manifest manifest = RestorationUtilities.downloadManifest(operation.request, restorer, null, objectMapper);
        manifest.enrichManifestEntries();
        final DataSynchronizator synchronizator = new DataSynchronizator(manifest, request).execute();
        // here we need to categorize into what data dir entries to download will be downloaded
        // categorization will set "localFile" on manifest entry
        // we need to do it in such a way that sstables belonging together will be placed into same dir
        final ManifestEntrySSTableClassifier classifier = new ManifestEntrySSTableClassifier();
        final Map<String, List<ManifestEntry>> classified = classifier.classify(synchronizator.entriesToDownload());
        classifier.map(classified, request);
        Session<DownloadUnit> downloadSession = null;
        try {
            downloadSession = downloadTracker.submit(restorer, operation, synchronizator.entriesToDownload(), operation.request.snapshotTag, operation.request.concurrentConnections);
            downloadSession.waitUntilConsideredFinished();
            downloadTracker.cancelIfNecessary(downloadSession);
        } finally {
            downloadTracker.removeSession(downloadSession);
        }
        synchronizator.deleteUnnecessarySSTableFiles();
        synchronizator.cleanData();
        // in the future, we might implement automatic configuration of cassandra.yaml for standalone installations
        if (request.updateCassandraYaml) {
            Path fileToAppendTo;
            boolean shouldAppend = true;
            if (KubernetesHelper.isRunningInKubernetes()) {
                // Cassandra operator specific dir
                fileToAppendTo = Paths.get("/var/lib/cassandra/tokens.yaml");
            } else {
                fileToAppendTo = request.cassandraConfigDirectory.resolve("cassandra.yaml");
                if (!Files.exists(fileToAppendTo)) {
                    logger.info(String.format("File %s does not exist, not going to append to it!", fileToAppendTo));
                    shouldAppend = false;
                }
            }
            if (shouldAppend) {
                FileUtils.replaceOrAppend(fileToAppendTo, content -> content.contains("auto_bootstrap: true"), content -> !content.contains("auto_bootstrap"), "auto_bootstrap: true", "auto_bootstrap: false");
                if (FileUtils.contains(fileToAppendTo, "initial_token") && !FileUtils.contains(fileToAppendTo, "# initial_token")) {
                    logger.warn(String.format("%s file does already contain 'initial_token' property, this is unexpected and " + "backup tooling is not going to update it for you, please proceed manually, new setting should be: %s", fileToAppendTo, manifest.getInitialTokensCassandraYamlFragment()));
                } else {
                    FileUtils.appendToFile(fileToAppendTo, manifest.getInitialTokensCassandraYamlFragment());
                }
                logger.debug(String.format("Content of file %s to which necessary changes for restore were applied: ", fileToAppendTo));
                logger.debug(new String(Files.readAllBytes(fileToAppendTo)));
            }
        } else {
            logger.info("Update of cassandra.yaml was turned off by --update-cassandra-yaml=false (or not specifying that flag at all.");
            logger.info("For the successful start of a node by Cassandra operator or manually, you have to do the following:");
            logger.info("1) add tokens in Cassandra installation dir to cassandra.yaml file");
            logger.info("2) change 'auto_bootstrap: true' to 'auto_bootstrap: false' in cassandra.yaml");
        }
    } catch (final Exception ex) {
        operation.addError(Error.from(ex));
    }
}
Also used : Path(java.nio.file.Path) ManifestEntrySSTableClassifier(com.instaclustr.esop.impl.restore.strategy.DataSynchronizator.ManifestEntrySSTableClassifier) DownloadUnit(com.instaclustr.esop.impl.restore.DownloadTracker.DownloadUnit) BucketService(com.instaclustr.esop.impl.BucketService) Manifest(com.instaclustr.esop.impl.Manifest) NodeTopology(com.instaclustr.esop.topology.CassandraClusterTopology.ClusterTopology.NodeTopology) List(java.util.List) RestoreOperationRequest(com.instaclustr.esop.impl.restore.RestoreOperationRequest)

Example 2 with BucketService

use of com.instaclustr.esop.impl.BucketService in project esop by instaclustr.

the class BaseBackupOperationCoordinator method coordinate.

@Override
public void coordinate(final Operation<BackupOperationRequest> operation) {
    final BackupOperationRequest request = operation.request;
    logger.info(request.toString());
    try {
        assert cassandraJMXService != null;
        assert backuperFactoryMap != null;
        assert bucketServiceFactoryMap != null;
        assert objectMapper != null;
        if (!request.skipBucketVerification) {
            try (final BucketService bucketService = bucketServiceFactoryMap.get(request.storageLocation.storageProvider).createBucketService(request)) {
                bucketService.checkBucket(request.storageLocation.bucket, request.createMissingBucket);
            }
        }
        final CassandraData cassandraData = CassandraData.parse(request.dataDirs.get(0));
        cassandraData.setDatabaseEntitiesFromRequest(request.entities);
        final List<String> tokens = new CassandraTokens(cassandraJMXService).act();
        logger.info("Tokens {}", tokens);
        if (!Snapshots.snapshotContainsTimestamp(operation.request.snapshotTag)) {
            if (operation.request.schemaVersion == null) {
                operation.request.schemaVersion = new CassandraSchemaVersion(cassandraJMXService).act();
            }
            operation.request.snapshotTag = resolveSnapshotTag(operation.request, System.currentTimeMillis());
        }
        logger.info("Taking snapshot with name {}", request.snapshotTag);
        new TakeSnapshotOperation(cassandraJMXService, new TakeSnapshotOperationRequest(request.entities, request.snapshotTag), cassandraVersionProvider).run0();
        Snapshots.hashSpec = hashSpec;
        final Snapshots snapshots = Snapshots.parse(request.dataDirs, request.snapshotTag);
        final Optional<Snapshot> snapshot = snapshots.get(request.snapshotTag);
        if (!snapshot.isPresent()) {
            throw new IllegalStateException(format("There is not any snapshot of tag %s", request.snapshotTag));
        }
        final Manifest manifest = Manifest.from(snapshot.get());
        manifest.setSchemaVersion(request.schemaVersion);
        manifest.setTokens(tokens);
        // manifest
        final Path localManifestPath = getLocalManifestPath(request.snapshotTag);
        Manifest.write(manifest, localManifestPath, objectMapper);
        manifest.setManifest(getManifestAsManifestEntry(localManifestPath));
        try (final Backuper backuper = backuperFactoryMap.get(request.storageLocation.storageProvider).createBackuper(request)) {
            final List<ManifestEntry> manifestEntries = manifest.getManifestEntries();
            Session<UploadUnit> uploadSession = null;
            try {
                uploadSession = uploadTracker.submit(backuper, operation, manifestEntries, request.snapshotTag, operation.request.concurrentConnections);
                uploadSession.waitUntilConsideredFinished();
                uploadTracker.cancelIfNecessary(uploadSession);
                final List<UploadUnit> failedUnits = uploadSession.getFailedUnits();
                if (!failedUnits.isEmpty()) {
                    final String message = failedUnits.stream().map(unit -> unit.getManifestEntry().objectKey.toString()).collect(Collectors.joining(","));
                    logger.error(message);
                    throw new IOException(format("Unable to upload some files successfully: %s", message));
                }
            } finally {
                uploadTracker.removeSession(uploadSession);
                uploadSession = null;
            }
            if (operation.request.uploadClusterTopology) {
                // here we will upload all topology because we do not know what restore might look like (what dc a restorer will restore against if any)
                final ClusterTopology topology = new CassandraClusterTopology(cassandraJMXService, null).act();
                ClusterTopology.upload(backuper, topology, objectMapper, operation.request.snapshotTag);
            }
        } finally {
            manifest.cleanup();
        }
    } catch (final Exception ex) {
        operation.addError(Error.from(ex));
    } finally {
        final ClearSnapshotOperation cso = new ClearSnapshotOperation(cassandraJMXService, new ClearSnapshotOperationRequest(request.snapshotTag));
        try {
            cso.run0();
        } catch (final Exception ex) {
            operation.addErrors(cso.errors);
        }
    }
}
Also used : CassandraData(com.instaclustr.esop.impl.CassandraData) ManifestEntry(com.instaclustr.esop.impl.ManifestEntry) Error(com.instaclustr.operations.Operation.Error) Manifest.getManifestAsManifestEntry(com.instaclustr.esop.impl.Manifest.getManifestAsManifestEntry) Provider(javax.inject.Provider) HashSpec(com.instaclustr.esop.impl.hash.HashSpec) OperationCoordinator(com.instaclustr.operations.OperationCoordinator) LoggerFactory(org.slf4j.LoggerFactory) Manifest.getLocalManifestPath(com.instaclustr.esop.impl.Manifest.getLocalManifestPath) BackuperFactory(com.instaclustr.esop.guice.BackuperFactory) Map(java.util.Map) Session(com.instaclustr.esop.impl.AbstractTracker.Session) CassandraClusterTopology(com.instaclustr.esop.topology.CassandraClusterTopology) Path(java.nio.file.Path) CassandraData(com.instaclustr.esop.impl.CassandraData) BucketServiceFactory(com.instaclustr.esop.guice.BucketServiceFactory) BucketService(com.instaclustr.esop.impl.BucketService) Backuper(com.instaclustr.esop.impl.backup.Backuper) CassandraSchemaVersion(com.instaclustr.esop.impl.interaction.CassandraSchemaVersion) Logger(org.slf4j.Logger) UploadTracker(com.instaclustr.esop.impl.backup.UploadTracker) Operation(com.instaclustr.operations.Operation) ObjectMapper(com.fasterxml.jackson.databind.ObjectMapper) IOException(java.io.IOException) Manifest(com.instaclustr.esop.impl.Manifest) Snapshot(com.instaclustr.esop.impl.Snapshots.Snapshot) Collectors(java.util.stream.Collectors) String.format(java.lang.String.format) ClearSnapshotOperationRequest(com.instaclustr.esop.impl.backup.coordination.ClearSnapshotOperation.ClearSnapshotOperationRequest) List(java.util.List) Snapshots(com.instaclustr.esop.impl.Snapshots) UploadUnit(com.instaclustr.esop.impl.backup.UploadTracker.UploadUnit) TakeSnapshotOperationRequest(com.instaclustr.esop.impl.backup.coordination.TakeSnapshotOperation.TakeSnapshotOperationRequest) CassandraVersion(com.instaclustr.cassandra.CassandraVersion) Optional(java.util.Optional) BackupOperationRequest(com.instaclustr.esop.impl.backup.BackupOperationRequest) CassandraTokens(com.instaclustr.esop.impl.interaction.CassandraTokens) ClusterTopology(com.instaclustr.esop.topology.CassandraClusterTopology.ClusterTopology) CassandraJMXService(jmx.org.apache.cassandra.service.CassandraJMXService) ClearSnapshotOperationRequest(com.instaclustr.esop.impl.backup.coordination.ClearSnapshotOperation.ClearSnapshotOperationRequest) TakeSnapshotOperationRequest(com.instaclustr.esop.impl.backup.coordination.TakeSnapshotOperation.TakeSnapshotOperationRequest) CassandraClusterTopology(com.instaclustr.esop.topology.CassandraClusterTopology) ClusterTopology(com.instaclustr.esop.topology.CassandraClusterTopology.ClusterTopology) CassandraSchemaVersion(com.instaclustr.esop.impl.interaction.CassandraSchemaVersion) UploadUnit(com.instaclustr.esop.impl.backup.UploadTracker.UploadUnit) CassandraClusterTopology(com.instaclustr.esop.topology.CassandraClusterTopology) CassandraTokens(com.instaclustr.esop.impl.interaction.CassandraTokens) Backuper(com.instaclustr.esop.impl.backup.Backuper) Snapshots(com.instaclustr.esop.impl.Snapshots) Manifest.getLocalManifestPath(com.instaclustr.esop.impl.Manifest.getLocalManifestPath) Path(java.nio.file.Path) BucketService(com.instaclustr.esop.impl.BucketService) IOException(java.io.IOException) Manifest(com.instaclustr.esop.impl.Manifest) IOException(java.io.IOException) Snapshot(com.instaclustr.esop.impl.Snapshots.Snapshot) BackupOperationRequest(com.instaclustr.esop.impl.backup.BackupOperationRequest) ManifestEntry(com.instaclustr.esop.impl.ManifestEntry) Manifest.getManifestAsManifestEntry(com.instaclustr.esop.impl.Manifest.getManifestAsManifestEntry)

Example 3 with BucketService

use of com.instaclustr.esop.impl.BucketService in project esop by instaclustr.

the class BackupCommitLogsOperation method run0.

@Override
protected void run0() throws Exception {
    updateStorageLocationIfNecessary();
    logger.info(request.toString());
    // generate manifest (set of object keys and source files defining the upload)
    // linked list to maintain order
    final Collection<ManifestEntry> manifestEntries = new LinkedList<>();
    try (final DirectoryStream<Path> commitLogs = getCommitLogs(request);
        final Backuper backuper = backuperFactoryMap.get(request.storageLocation.storageProvider).createCommitLogBackuper(request);
        final BucketService bucketService = bucketServiceMap.get(request.storageLocation.storageProvider).createBucketService(request)) {
        if (!request.skipBucketVerification) {
            bucketService.checkBucket(request.storageLocation.bucket, request.createMissingBucket);
        }
        for (final Path commitLog : commitLogs) {
            // Append file modified date so we have some idea of the time range this commitlog covers
            // millisecond precision, on *nix, it trims milliseconds and returns "000" instead
            // when using File.lastModified
            long commitLogLastModified = Files.getLastModifiedTime(commitLog.toFile().toPath()).toMillis();
            final Path bucketKey = CASSANDRA_COMMITLOG.resolve(commitLog.getFileName().toString() + "." + commitLogLastModified);
            manifestEntries.add(new ManifestEntry(bucketKey, commitLog, COMMIT_LOG, null));
        }
        logger.info("{} files in manifest for commitlog backup.", manifestEntries.size());
        Session<UploadUnit> uploadSession = null;
        try {
            uploadSession = uploadTracker.submit(backuper, this, manifestEntries, null, this.request.concurrentConnections);
            uploadSession.waitUntilConsideredFinished();
            uploadTracker.cancelIfNecessary(uploadSession);
        } finally {
            uploadTracker.removeSession(uploadSession);
        }
    }
}
Also used : Path(java.nio.file.Path) UploadUnit(com.instaclustr.esop.impl.backup.UploadTracker.UploadUnit) ManifestEntry(com.instaclustr.esop.impl.ManifestEntry) BucketService(com.instaclustr.esop.impl.BucketService) LinkedList(java.util.LinkedList)

Aggregations

BucketService (com.instaclustr.esop.impl.BucketService)3 Path (java.nio.file.Path)3 Manifest (com.instaclustr.esop.impl.Manifest)2 ManifestEntry (com.instaclustr.esop.impl.ManifestEntry)2 UploadUnit (com.instaclustr.esop.impl.backup.UploadTracker.UploadUnit)2 List (java.util.List)2 ObjectMapper (com.fasterxml.jackson.databind.ObjectMapper)1 CassandraVersion (com.instaclustr.cassandra.CassandraVersion)1 BackuperFactory (com.instaclustr.esop.guice.BackuperFactory)1 BucketServiceFactory (com.instaclustr.esop.guice.BucketServiceFactory)1 Session (com.instaclustr.esop.impl.AbstractTracker.Session)1 CassandraData (com.instaclustr.esop.impl.CassandraData)1 Manifest.getLocalManifestPath (com.instaclustr.esop.impl.Manifest.getLocalManifestPath)1 Manifest.getManifestAsManifestEntry (com.instaclustr.esop.impl.Manifest.getManifestAsManifestEntry)1 Snapshots (com.instaclustr.esop.impl.Snapshots)1 Snapshot (com.instaclustr.esop.impl.Snapshots.Snapshot)1 BackupOperationRequest (com.instaclustr.esop.impl.backup.BackupOperationRequest)1 Backuper (com.instaclustr.esop.impl.backup.Backuper)1 UploadTracker (com.instaclustr.esop.impl.backup.UploadTracker)1 ClearSnapshotOperationRequest (com.instaclustr.esop.impl.backup.coordination.ClearSnapshotOperation.ClearSnapshotOperationRequest)1