Search in sources :

Example 11 with PatchException

use of io.fabric8.api.PatchException in project fabric8 by jboss-fuse.

the class ServiceImpl method install.

/**
 * <p>Main installation method. Installing a patch in non-fabric mode is a matter of correct merge (cherry-pick, merge,
 * rebase) of patch branch into <code>master</code> branch.</p>
 * <p>Static changes are handled by git, runtime changes (bundles, features) are handled depending on patch type:<ul>
 *     <li>Rollup: clear OSGi bundle cache, reinstall features that were installed after restart</li>
 *     <li>Non-Rollup: update bundles, generate overrides.properties and update scripts to reference new versions</li>
 * </ul></p>
 * <p>For Rollup patches we don't update bundles - we clear the bundle cache instead.</p>
 * @param patches
 * @param simulate
 * @param synchronous
 * @return
 */
private Map<String, PatchResult> install(final Collection<Patch> patches, final boolean simulate, boolean synchronous) {
    PatchKind kind = checkConsistency(patches);
    checkPrerequisites(patches);
    checkStandaloneChild(patches);
    // checkFabric();
    String transaction = null;
    try {
        // Compute individual patch results (patchId -> Result)
        final Map<String, PatchResult> results = new LinkedHashMap<String, PatchResult>();
        // current state of the framework
        Bundle[] allBundles = bundleContext.getBundles();
        // bundle -> url to update the bundle from (used for non-rollup patch)
        final Map<Bundle, String> bundleUpdateLocations = new HashMap<>();
        /* A "key" is name + "update'able version". Such version is current version with micro version == 0 */
        // [symbolic name|updateable-version] -> newest update for the bundle out of all installed patches
        final Map<String, BundleUpdate> updatesForBundleKeys = new LinkedHashMap<>();
        // [feature name|updateable-version] -> newest update for the feature out of all installed patches
        final Map<String, FeatureUpdate> updatesForFeatureKeys = new LinkedHashMap<>();
        // symbolic name -> version -> location
        final BundleVersionHistory history = createBundleVersionHistory();
        // beginning installation transaction = creating of temporary branch in git
        transaction = this.patchManagement.beginInstallation(kind);
        // bundles from etc/startup.properties + felix.framework = all bundles not managed by features
        // these bundles will be treated in special way
        // symbolic name -> Bundle
        final Map<String, Bundle> coreBundles = helper.getCoreBundles(allBundles);
        // runtime info is prepared to apply runtime changes and static info is prepared to update KARAF_HOME files
        for (Patch patch : patches) {
            List<FeatureUpdate> featureUpdatesInThisPatch = null;
            if (kind == PatchKind.ROLLUP) {
                // list of feature updates for the current patch
                featureUpdatesInThisPatch = featureUpdatesInPatch(patch, updatesForFeatureKeys, kind);
                helper.sortFeatureUpdates(featureUpdatesInThisPatch);
            }
            // list of bundle updates for the current patch - for ROLLUP patch, we minimize the list of bundles
            // to "restore" (install after clearing data/cache) by not including bundles that are
            // already updated as part of fueatures update
            List<BundleUpdate> bundleUpdatesInThisPatch = bundleUpdatesInPatch(patch, allBundles, bundleUpdateLocations, history, updatesForBundleKeys, kind, coreBundles, featureUpdatesInThisPatch);
            // each patch may change files, we're not updating the main files yet - it'll be done when
            // install transaction is committed
            patchManagement.install(transaction, patch, bundleUpdatesInThisPatch);
            // each patch may ship a migrator
            if (!simulate) {
                installMigratorBundle(patch);
            }
            // prepare patch result before doing runtime changes
            PatchResult result = null;
            if (patch.getResult() != null) {
                result = patch.getResult();
                if (patchManagement.isStandaloneChild()) {
                    // ENTESB-5120: "result" is actually a result of patch installation in root container
                    // we need dedicated result for admin:create based child container
                    PatchResult childResult = new PatchResult(patch.getPatchData(), simulate, System.currentTimeMillis(), bundleUpdatesInThisPatch, featureUpdatesInThisPatch, result);
                    result.addChildResult(System.getProperty("karaf.name"), childResult);
                }
            } else {
                result = new PatchResult(patch.getPatchData(), simulate, System.currentTimeMillis(), bundleUpdatesInThisPatch, featureUpdatesInThisPatch);
            }
            result.getKarafBases().add(String.format("%s | %s", System.getProperty("karaf.name"), System.getProperty("karaf.base")));
            results.put(patch.getPatchData().getId(), result);
        }
        // One special case
        if (kind == PatchKind.NON_ROLLUP) {
            // for rollup patch, this bundle will be installed from scratch
            for (Map.Entry<Bundle, String> entry : bundleUpdateLocations.entrySet()) {
                Bundle bundle = entry.getKey();
                if (bundle.getSymbolicName() != null && "org.ops4j.pax.url.mvn".equals(stripSymbolicName(bundle.getSymbolicName()))) {
                    // handle this bundle specially - update it here
                    URL location = new URL(entry.getValue());
                    System.out.printf("Special update of bundle \"%s\" from \"%s\"%n", bundle.getSymbolicName(), location);
                    if (!simulate) {
                        BundleUtils.update(bundle, location);
                        bundle.start();
                    }
                    // replace location - to be stored in result
                    bundleUpdateLocations.put(bundle, location.toString());
                }
            }
        }
        Presentation.displayFeatureUpdates(updatesForFeatureKeys.values(), true);
        // effectively, we will update all the bundles from this list - even if some bundles will be "updated"
        // as part of feature installation
        Presentation.displayBundleUpdates(updatesForBundleKeys.values(), true);
        // then required repositories, features and bundles will be reinstalled
        if (kind == PatchKind.ROLLUP) {
            if (!simulate) {
                if (patches.size() == 1) {
                    Patch patch = patches.iterator().next();
                    PatchResult result = results.get(patch.getPatchData().getId());
                    patch.setResult(result);
                    // single shot
                    if (patchManagement.isStandaloneChild()) {
                        backupService.backupDataFiles(result.getChildPatches().get(System.getProperty("karaf.name")), Pending.ROLLUP_INSTALLATION);
                    } else {
                        backupService.backupDataFiles(result, Pending.ROLLUP_INSTALLATION);
                    }
                    for (Bundle b : coreBundles.values()) {
                        if (b.getSymbolicName() != null && Utils.stripSymbolicName(b.getSymbolicName()).equals("org.apache.felix.fileinstall")) {
                            b.stop(Bundle.STOP_TRANSIENT);
                            break;
                        }
                    }
                    // update KARAF_HOME
                    patchManagement.commitInstallation(transaction);
                    if (patchManagement.isStandaloneChild()) {
                        result.getChildPatches().get(System.getProperty("karaf.name")).setPending(Pending.ROLLUP_INSTALLATION);
                    } else {
                        result.setPending(Pending.ROLLUP_INSTALLATION);
                    }
                    result.store();
                    // Some updates need a full JVM restart.
                    if (isJvmRestartNeeded(results)) {
                        boolean handlesFullRestart = Boolean.getBoolean("karaf.restart.jvm.supported");
                        if (handlesFullRestart) {
                            System.out.println("Rollup patch " + patch.getPatchData().getId() + " installed. Restarting Karaf..");
                            System.setProperty("karaf.restart.jvm", "true");
                        } else {
                            System.out.println("Rollup patch " + patch.getPatchData().getId() + " installed. Shutting down Karaf, please restart...");
                        }
                    } else {
                        // We don't need a JVM restart, so lets just do a OSGi framework restart
                        System.setProperty("karaf.restart", "true");
                    }
                    File karafData = new File(bundleContext.getProperty("karaf.data"));
                    File cleanCache = new File(karafData, "clean_cache");
                    cleanCache.createNewFile();
                    Thread.currentThread().setContextClassLoader(bundleContext.getBundle(0l).adapt(BundleWiring.class).getClassLoader());
                    bundleContext.getBundle(0l).stop();
                }
            } else {
                System.out.println("Simulation only - no files and runtime data will be modified.");
                patchManagement.rollbackInstallation(transaction);
            }
            return results;
        }
        // update KARAF_HOME
        if (!simulate) {
            patchManagement.commitInstallation(transaction);
        } else {
            patchManagement.rollbackInstallation(transaction);
        }
        if (!simulate) {
            Runnable task = new Runnable() {

                @Override
                public void run() {
                    try {
                        // update bundles
                        applyChanges(bundleUpdateLocations);
                        // persist results of all installed patches
                        for (Patch patch : patches) {
                            PatchResult result = results.get(patch.getPatchData().getId());
                            patch.setResult(result);
                            result.store();
                        }
                    } catch (Exception e) {
                        e.printStackTrace(System.err);
                        System.err.flush();
                    }
                }
            };
            if (synchronous) {
                task.run();
            } else {
                new Thread(task).start();
            }
        } else {
            System.out.println("Simulation only - no files and runtime data will be modified.");
        }
        return results;
    } catch (Exception e) {
        e.printStackTrace(System.err);
        System.err.flush();
        if (transaction != null && patchManagement != null) {
            patchManagement.rollbackInstallation(transaction);
        }
        throw new PatchException(e.getMessage(), e);
    } finally {
        System.out.flush();
    }
}
Also used : HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) PatchKind(io.fabric8.patch.management.PatchKind) URL(java.net.URL) LinkedHashMap(java.util.LinkedHashMap) BundleUpdate(io.fabric8.patch.management.BundleUpdate) FeatureUpdate(io.fabric8.patch.management.FeatureUpdate) Bundle(org.osgi.framework.Bundle) URISyntaxException(java.net.URISyntaxException) PatchException(io.fabric8.patch.management.PatchException) BundleException(org.osgi.framework.BundleException) IOException(java.io.IOException) PatchResult(io.fabric8.patch.management.PatchResult) PatchException(io.fabric8.patch.management.PatchException) Patch(io.fabric8.patch.management.Patch) Map(java.util.Map) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) File(java.io.File)

Example 12 with PatchException

use of io.fabric8.api.PatchException in project fabric8 by jboss-fuse.

the class GitPatchManagementServiceIT method initializationPerformedNoBaselineDistribution.

@Test
public void initializationPerformedNoBaselineDistribution() throws IOException, GitAPIException {
    freshKarafStandaloneDistro();
    pm = new GitPatchManagementServiceImpl(bundleContext);
    pm.start();
    try {
        pm.ensurePatchManagementInitialized();
        fail("Should fail, because no baseline distribution is found");
    } catch (PatchException e) {
        assertTrue(e.getMessage().contains("Can't find baseline distribution"));
    }
}
Also used : GitPatchManagementServiceImpl(io.fabric8.patch.management.impl.GitPatchManagementServiceImpl) Test(org.junit.Test)

Example 13 with PatchException

use of io.fabric8.api.PatchException in project fabric8 by jboss-fuse.

the class SimulateAction method doExecute.

@Override
protected void doExecute(Service service) throws Exception {
    Patch patch = service.getPatch(patchId);
    if (patch == null) {
        throw new PatchException("Patch '" + patchId + "' not found");
    }
    if (patch.isInstalled()) {
        throw new PatchException("Patch '" + patchId + "' is already installed");
    }
    PatchResult result = service.install(patch, true);
// display(result);
}
Also used : PatchResult(io.fabric8.patch.management.PatchResult) PatchException(io.fabric8.patch.management.PatchException) Patch(io.fabric8.patch.management.Patch)

Example 14 with PatchException

use of io.fabric8.api.PatchException in project fabric8 by jboss-fuse.

the class Offline method applyPatch.

protected void applyPatch(PatchData patch, ZipFile zipFile, File storage) throws IOException {
    log(DEBUG, "Applying patch: " + patch.getId() + " / " + patch.getDescription());
    File startupFile = new File(karafBase, "etc/startup.properties");
    File overridesFile = new File(karafBase, "etc/overrides.properties");
    List<String> startup = readLines(new File(karafBase, "etc/startup.properties"));
    List<String> overrides = readLines(overridesFile);
    List<Artifact> toExtract = new ArrayList<Artifact>();
    List<Artifact> toDelete = new ArrayList<Artifact>();
    for (String bundle : patch.getBundles()) {
        Artifact artifact = mvnurlToArtifact(bundle, true);
        if (artifact == null) {
            continue;
        }
        // Compute patch bundle version and range
        VersionRange range;
        Version oVer = VersionTable.getVersion(artifact.getVersion());
        String vr = patch.getVersionRange(bundle);
        String override;
        if (vr != null && !vr.isEmpty()) {
            override = bundle + OVERRIDE_RANGE + vr;
            range = VersionRange.parseVersionRange(vr);
        } else {
            override = bundle;
            Version v1 = new Version(oVer.getMajor(), oVer.getMinor(), 0);
            Version v2 = new Version(oVer.getMajor(), oVer.getMinor() + 1, 0);
            range = new VersionRange(false, v1, v2, true);
        }
        // Process overrides.properties
        boolean matching = false;
        boolean added = false;
        for (int i = 0; i < overrides.size(); i++) {
            String line = overrides.get(i).trim();
            if (!line.isEmpty() && !line.startsWith("#")) {
                Artifact overrideArtifact = mvnurlToArtifact(line, true);
                if (overrideArtifact != null) {
                    Version ver = VersionTable.getVersion(overrideArtifact.getVersion());
                    if (isSameButVersion(artifact, overrideArtifact) && range.contains(ver)) {
                        matching = true;
                        if (ver.compareTo(oVer) < 0) {
                            // Replace old override with the new one
                            overrides.set(i, override);
                            if (!added) {
                                log(DEBUG, "Replacing with artifact: " + override);
                                added = true;
                            }
                            // Remove old file
                            toDelete.add(overrideArtifact);
                            toExtract.remove(overrideArtifact);
                        }
                    }
                } else {
                    log(WARN, "Unable to convert to artifact: " + line);
                }
            }
        }
        // If there was not matching bundles, add it
        if (!matching) {
            overrides.add(override);
            log(DEBUG, "Adding artifact: " + override);
        }
        // Process startup.properties
        for (int i = 0; i < startup.size(); i++) {
            String line = startup.get(i).trim();
            if (!line.isEmpty() && !line.startsWith("#")) {
                int index = line.indexOf('=');
                String mvnUrl = Utils.pathToMvnurl(line.substring(0, index));
                if (mvnUrl != null) {
                    Artifact startupArtifact = mvnurlToArtifact(mvnUrl, true);
                    if (startupArtifact != null) {
                        Version ver = VersionTable.getVersion(startupArtifact.getVersion());
                        if (isSameButVersion(artifact, startupArtifact) && range.contains(ver)) {
                            matching = true;
                            // Now check versions
                            if (ver.compareTo(oVer) < 0) {
                                line = artifact.getPath() + line.substring(index);
                                startup.set(i, line);
                                log(DEBUG, "Overwriting startup.properties with: " + artifact);
                                added = true;
                            }
                        }
                    }
                }
            }
        }
        // Extract artifact
        if (!matching || added) {
            toExtract.add(artifact);
        }
    }
    // Extract / delete artifacts if needed
    if (zipFile != null) {
        for (Artifact artifact : toExtract) {
            log(DEBUG, "Extracting artifact: " + artifact);
            ZipEntry entry = zipFile.getEntry("repository/" + artifact.getPath());
            if (entry == null) {
                log(ERROR, "Could not find artifact in patch zip: " + artifact);
                continue;
            }
            File f = new File(karafBase, "system/" + artifact.getPath());
            if (!f.isFile()) {
                f.getParentFile().mkdirs();
                InputStream fis = zipFile.getInputStream(entry);
                FileOutputStream fos = new FileOutputStream(f);
                try {
                    IOUtils.copy(fis, fos);
                } finally {
                    IOUtils.closeQuietly(fis);
                    IOUtils.closeQuietly(fos);
                }
            }
        }
        for (Artifact artifact : toDelete) {
            String fileName = artifact.getPath();
            File file = new File(karafBase, "system/" + fileName);
            if (file.exists()) {
                log(DEBUG, "Removing old artifact " + artifact);
                file.delete();
            } else {
                log(WARN, "Could not find: " + file);
            }
        }
    }
    overrides = new ArrayList<String>(new HashSet<String>(overrides));
    Collections.sort(overrides);
    writeLines(overridesFile, overrides);
    writeLines(startupFile, startup);
    // update the remaining patch files (using either the patch ZIP file or the patch storage location)
    if (zipFile != null) {
        patchFiles(patch, zipFile);
    } else if (storage != null) {
        patchFiles(patch, storage);
    } else {
        throw new PatchException("Unable to update patch files: no access to patch ZIP file or patch storage location");
    }
    if (patch.getMigratorBundle() != null) {
        Artifact artifact = mvnurlToArtifact(patch.getMigratorBundle(), true);
        if (artifact != null) {
            // Copy it to the deploy dir
            File src = new File(karafBase, "system/" + artifact.getPath());
            File target = new File(new File(karafBase, "deploy"), artifact.getArtifactId() + ".jar");
            copy(src, target);
        }
    }
}
Also used : FileInputStream(java.io.FileInputStream) InputStream(java.io.InputStream) ZipEntry(java.util.zip.ZipEntry) ArrayList(java.util.ArrayList) VersionRange(org.apache.felix.utils.version.VersionRange) Utils.mvnurlToArtifact(io.fabric8.patch.management.Utils.mvnurlToArtifact) Artifact(io.fabric8.patch.management.Artifact) Artifact.isSameButVersion(io.fabric8.patch.management.Artifact.isSameButVersion) Version(org.osgi.framework.Version) FileOutputStream(java.io.FileOutputStream) PatchException(io.fabric8.patch.management.PatchException) ZipFile(java.util.zip.ZipFile) File(java.io.File) HashSet(java.util.HashSet)

Example 15 with PatchException

use of io.fabric8.api.PatchException in project fabric8 by jboss-fuse.

the class ShowAction method doExecute.

@Override
protected void doExecute(Service service) throws Exception {
    Patch patch = patchManagement.loadPatch(new PatchDetailsRequest(patchId, bundles, files, diff));
    if (patch == null) {
        throw new PatchException("Patch '" + patchId + "' not found");
    }
    System.out.println(String.format("Patch ID: %s", patch.getPatchData().getId()));
    if (patch.getManagedPatch() != null) {
        System.out.println(String.format("Patch Commit ID: %s", patch.getManagedPatch().getCommitId()));
    }
    if (bundles) {
        System.out.println(String.format("#### %d Bundles%s", patch.getPatchData().getBundles().size(), patch.getPatchData().getBundles().size() == 0 ? "" : ":"));
        iterate(patch.getPatchData().getBundles());
    }
    if (files) {
        ManagedPatch details = patch.getManagedPatch();
        System.out.println(String.format("#### %d Files added%s", details.getFilesAdded().size(), details.getFilesAdded().size() == 0 ? "" : ":"));
        iterate(details.getFilesAdded());
        System.out.println(String.format("#### %d Files modified%s", details.getFilesModified().size(), details.getFilesModified().size() == 0 ? "" : ":"));
        iterate(details.getFilesModified());
        System.out.println(String.format("#### %d Files removed%s", details.getFilesRemoved().size(), details.getFilesRemoved().size() == 0 ? "" : ":"));
        iterate(details.getFilesRemoved());
    }
    if (diff) {
        System.out.println("#### Patch changes:\n" + patch.getManagedPatch().getUnifiedDiff());
    }
}
Also used : ManagedPatch(io.fabric8.patch.management.ManagedPatch) PatchException(io.fabric8.patch.management.PatchException) ManagedPatch(io.fabric8.patch.management.ManagedPatch) Patch(io.fabric8.patch.management.Patch) PatchDetailsRequest(io.fabric8.patch.management.PatchDetailsRequest)

Aggregations

PatchException (io.fabric8.patch.management.PatchException)30 IOException (java.io.IOException)19 File (java.io.File)15 Patch (io.fabric8.patch.management.Patch)14 GitAPIException (org.eclipse.jgit.api.errors.GitAPIException)11 ZipFile (org.apache.commons.compress.archivers.zip.ZipFile)10 Git (org.eclipse.jgit.api.Git)10 LinkedList (java.util.LinkedList)9 Test (org.junit.Test)9 ArrayList (java.util.ArrayList)7 GitPatchManagementServiceImpl (io.fabric8.patch.management.impl.GitPatchManagementServiceImpl)6 URISyntaxException (java.net.URISyntaxException)6 HashMap (java.util.HashMap)6 RevCommit (org.eclipse.jgit.revwalk.RevCommit)6 PatchResult (io.fabric8.patch.management.PatchResult)5 FileInputStream (java.io.FileInputStream)5 FileNotFoundException (java.io.FileNotFoundException)5 BundleException (org.osgi.framework.BundleException)5 ManagedPatch (io.fabric8.patch.management.ManagedPatch)4 URL (java.net.URL)4