Package org.rioproject.cybernode.service

Source Code of org.rioproject.cybernode.service.StagedDataManager

/*
* Copyright 2008 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.rioproject.cybernode.service;

import org.rioproject.deploy.DownloadRecord;
import org.rioproject.deploy.StagedData;
import org.rioproject.deploy.StagedSoftware;
import org.rioproject.deploy.SystemComponent;
import org.rioproject.impl.exec.Util;
import org.rioproject.impl.servicebean.DefaultServiceBeanContext;
import org.rioproject.opstring.ServiceElement;
import org.rioproject.impl.util.DownloadManager;
import org.rioproject.impl.util.FileUtils;
import org.rioproject.impl.system.ComputeResource;
import org.rioproject.impl.system.OperatingSystemType;
import org.rioproject.system.capability.PlatformCapability;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.util.*;

/**
* A utility to assist in downloading and installing data for a service.
*
* @author Dennis Reedy
*/
public class StagedDataManager {
    /** Collection of PlatformCapability instances that have been installed
     * by the ServiceBeanDelegateImpl */
    private final Collection<PlatformCapability> installedPlatformCapabilities = new ArrayList<PlatformCapability>();
    private final List<DownloadRecord> dlRecords = new ArrayList<DownloadRecord>();
    private final Map<StagedData, DownloadRecord[]> downloadedArtifacts = new HashMap<StagedData, DownloadRecord[]>();
    private ServiceElement sElem;
    private ComputeResource computeResource;
    /** Logger */
    static Logger logger = LoggerFactory.getLogger("org.rioproject.cybernode");

    /**
     * Create a StagedDataManager

     * @param computeResource The compute resource
     */
    public StagedDataManager(ComputeResource computeResource) {
        if(computeResource==null)
            throw new IllegalArgumentException("ComputeResource is null");
        this.computeResource = computeResource;
    }

    /**
     * @param sElem The service element information
     */
    public void setServiceElement(ServiceElement sElem) {
        if(sElem==null)
            throw new IllegalArgumentException("ServiceElement is null");
        this.sElem = sElem;
    }

    /**
     * Remove any installed PlatformCapability components
     *
     * @return An array of PlatformCapability instances that were removed. If
     * none were removed, return a zero-length array
     */
    public PlatformCapability[] removeInstalledPlatformCapabilities() {
        return removeInstalledPlatformCapabilities(true);
    }

    /**
     * Remove  installed PlatformCapability components
     *
     * @param force Whether to remove the PlatformCapability, regardless of
     * whether the remove on destroy attribute of the StatedData element is true
     *
     * @return An array of PlatformCapability instances that were removed. If
     * none were removed, return a zero-length array
     */
    public PlatformCapability[] removeInstalledPlatformCapabilities(boolean force) {
        List<PlatformCapability> removed = new ArrayList<PlatformCapability>();
        for (PlatformCapability pCap : installedPlatformCapabilities) {
            StagedSoftware[] software = pCap.getStagedSoftware();
            for(StagedSoftware sw : software) {
                if(force && pCap.getUsageCount()==0) {
                    if(computeResource.removePlatformCapability(pCap, true))
                        removed.add(pCap);
                } else {
                    if (sw.removeOnDestroy() && pCap.getUsageCount()==0) {
                        if(computeResource.removePlatformCapability(pCap, true))
                            removed.add(pCap);
                    }
                }
            }
        }

        return removed.toArray(new PlatformCapability[removed.size()]);
    }

    /**
     * Remove any installed StagedData
     */
    public void removeStagedData() {
        for(Map.Entry<StagedData, DownloadRecord[]> entry : downloadedArtifacts.entrySet()) {
            StagedData data = entry.getKey();
            if(data.removeOnDestroy()) {
                DownloadRecord[] records = entry.getValue();
                for(DownloadRecord record : records) {
                    DownloadManager.remove(record);
                }
            }
        }
    }

    /**
     * Get any {@link org.rioproject.system.capability.PlatformCapability}
     * instances that were installed
     *
     * @return A collection of
     * {@link org.rioproject.system.capability.PlatformCapability} instances
     * that were installed. If there were none installed, return a zero-length
     * collection
     */
    public Collection<PlatformCapability> getInstalledPlatformCapabilities() {
        return installedPlatformCapabilities;
    }

    /**
     * Get all DownloadRecords
     *
     * @return An array of {@link org.rioproject.deploy.DownloadRecord}
     * instances that represent the download of a
     * {@link org.rioproject.deploy.StagedData} instance. If nothing
     * was downloaded return a zero-length array
     */
    public DownloadRecord[] getDownloadRecords() {
        return dlRecords.toArray(new DownloadRecord[dlRecords.size()]);
    }

    /**
     * Get the map of {@link org.rioproject.deploy.StagedData} keys and
     * {@link org.rioproject.deploy.DownloadRecord} values for each
     * downloaded item.
     *
     * @return A map of {@link org.rioproject.deploy.StagedData} keys and
     * {@link org.rioproject.deploy.DownloadRecord} values for each
     * downloaded item. If nothing was downloaded, return an empty map
     */
    public Map<StagedData, DownloadRecord[]> getDownloadedArtifacts() {
        return downloadedArtifacts;
    }

    /**
     * Download any artifacts the service requires
     *
     * @return A map of {@link org.rioproject.deploy.StagedData} keys and
     * {@link org.rioproject.deploy.DownloadRecord} values for each
     * downloaded item. If nothing was downloaded, return an empty map
     *
     * @throws Exception If errors occur downloading or creating
     * {@link org.rioproject.system.capability.PlatformCapability} instances
     */
    public Map<StagedData, DownloadRecord[]> download() throws Exception {
        if(sElem==null)
            throw new IllegalStateException("ServiceElement has not been set");
        /* If there are provisionable capabilities, or data staging, perform
         * the stagedData/installation */
        Collection<SystemComponent> installableComponents =
            sElem.getProvisionablePlatformCapabilities();
        install(installableComponents);

        /* Verify missing components. If there are any, go get them */
        Collection<SystemComponent> missing = verifyPlatformCapabilities();
        if(!missing.isEmpty()) {
            install(missing);
            logger.info("Missing requirements have been provisioned");
        }

        StagedData[] stagedData = sElem.getStagedData();
        for (StagedData data : stagedData) {
            DownloadRecord dlRec;
            if (data.getInstallRoot().startsWith(File.separator)) {
                DownloadManager dlManager = new DownloadManager(data);
                dlRec = dlManager.download();
                dlRecords.add(dlRec);
            } else {
                String provisionRoot = computeResource.getPersistentProvisioningRoot();
                DownloadManager dlManager = new DownloadManager(provisionRoot, data);
                dlRec = dlManager.download();
                dlRecords.add(dlRec);
            }
            if (data.getPerms() != null) {
                if (OperatingSystemType.isWindows()) {
                    logger.warn("Cannot apply permissions [{}] to StagedData on Windows", data.getPerms());
                } else {
                    File toChmod;
                    StringBuilder perms = new StringBuilder();
                    if (dlRec.unarchived()) {
                        toChmod = new File(dlRec.getPath());
                        perms.append("-R ");
                    } else {
                        toChmod = new File(FileUtils.makeFileName(dlRec.getPath(), dlRec.getName()));
                    }
                    perms.append(data.getPerms());
                    logger.info("Applying permissions [{}] to data staged at [{}]",
                                perms.toString(), FileUtils.getFilePath(toChmod));
                    Util.chmod(toChmod, perms.toString());
                }
            }
            downloadedArtifacts.put(data, new DownloadRecord[]{dlRec});
        }
        return downloadedArtifacts;
    }

    /**
     * Verify that required platform capabilities are present
     *
     * @return A collection of {@code SystemComponent}s that are not found.
     * If there are no missing requirements, return an empty collection
     */
    public Collection<SystemComponent> verifyPlatformCapabilities() {
        if(sElem==null)
            throw new IllegalStateException("ServiceElement has not been set");
        PlatformCapability[] platformCapabilities = computeResource.getPlatformCapabilities();
        SystemComponent[] jsbRequirements =
            sElem.getServiceLevelAgreements().getSystemRequirements().getSystemComponents();
        ArrayList<SystemComponent> missing = new ArrayList<SystemComponent>();

        /*
         * If there are no PlatformCapability requirements we can return
         * successfully
         */
        if(jsbRequirements.length == 0)
            return missing;
        /*
         * Check each of our PlatformCapability objects for supportability
         */
        for (SystemComponent jsbRequirement : jsbRequirements) {
            boolean supported = false;
            /*
             * Iterate through all resource PlatformCapability objects and see
             * if any of them supports the current PlatformCapability. If none
             * are found, then we dont have a match
             */
            for (PlatformCapability pCap : platformCapabilities) {
                if (pCap.supports(jsbRequirement)) {
                    supported = true;
                    /* Make sure that if the platform capability is
                     * provisionable that it is not being removed */
                    if(pCap.getType()==PlatformCapability.PROVISIONABLE &&
                        computeResource.removalInProcess(pCap)) {
                        logger.warn("Service [{}] has a requirement [{}] that " +
                                    "is being removed as part of a previous " +
                                    "instantiation. An attempt will be made " +
                                    "to install the software", sElem.getName(), jsbRequirement);
                        missing.add(jsbRequirement);
                        logger.info("Wait for the removal to finish...");
                        do {
                            try {
                                Thread.sleep(500);
                            } catch (InterruptedException e) {
                                Thread.currentThread().interrupt();
                            }
                        } while(computeResource.removalInProcess(pCap));
                    }
                    break;
                }
            }
            if (!supported) {
                StagedSoftware data = jsbRequirement.getStagedSoftware();
                if(data!=null) {
                    missing.add(jsbRequirement);
                    logger.info("Service [{}] has a missing requirement [{}]. An attempt will be made to install it.",
                                sElem.getName(), jsbRequirement);
                } else {
                    logger.error("Service [{}] has a requirement for [{}], and it is not found on the Cybernode, not " +
                                 "is it downloadable. The capability may have been administratively removed during the " +
                                 "instantiation of the service", sElem.getName(), jsbRequirement);
                }
            }
        }

        return missing;
    }

    /*
     * Install Platform capabilities
     */
    private void install(Collection<SystemComponent> toInstall)
        throws IllegalAccessException, InstantiationException,ClassNotFoundException {
        for (SystemComponent sysComp : toInstall) {
            String className = sysComp.getClassName();
            if (className == null) {
                Map<String, String> pCapMap =
                    computeResource.getPlatformCapabilityNameTable();
                className = pCapMap.get(sysComp.getName());
            }
            PlatformCapability pCap = DefaultServiceBeanContext.createPlatformCapability(className,
                                                                                         sysComp.getAttributes());
            installedPlatformCapabilities.add(pCap);
            StagedSoftware staged = sysComp.getStagedSoftware();
            if(staged!=null) {
                DownloadRecord[] dlRecs = computeResource.provision(pCap, staged);
                //downloadedArtifacts.put(sw, dlRecs);
                Collections.addAll(dlRecords, dlRecs);
            }
        }
    }
}
TOP

Related Classes of org.rioproject.cybernode.service.StagedDataManager

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.