Java tutorial
/******************************************************************************* * Copyright (c) 2011, 2016 Eurotech and/or its affiliates * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Eurotech *******************************************************************************/ package org.eclipse.kura.core.deployment.install; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.FileReader; import java.io.IOException; import java.io.InputStream; import java.util.Date; import java.util.Properties; import org.apache.commons.io.FileUtils; import org.eclipse.kura.KuraErrorCode; import org.eclipse.kura.KuraException; import org.eclipse.kura.core.deployment.CloudDeploymentHandlerV2; import org.eclipse.kura.core.deployment.CloudDeploymentHandlerV2.INSTALL_STATUS; import org.eclipse.kura.core.deployment.DeploymentPackageOptions; import org.eclipse.kura.core.deployment.download.DeploymentPackageDownloadOptions; import org.eclipse.kura.core.util.ProcessUtil; import org.eclipse.kura.core.util.SafeProcess; import org.eclipse.kura.message.KuraResponsePayload; import org.osgi.service.deploymentadmin.DeploymentAdmin; import org.osgi.service.deploymentadmin.DeploymentException; import org.osgi.service.deploymentadmin.DeploymentPackage; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class InstallImpl { private static final Logger s_logger = LoggerFactory.getLogger(InstallImpl.class); private static final int PROGRESS_COMPLETE = 100; private static final String MESSAGE_CONFIGURATION_FILE_NOT_SPECIFIED = "Configuration file not specified"; public static final String RESOURCE_INSTALL = "install"; public static final String PERSISTANCE_SUFFIX = "_persistance"; public static final String PERSISTANCE_FOLDER_NAME = "persistance"; public static final String PERSISTANCE_VERIFICATION_FOLDER_NAME = "verification"; public static final String PERSISTANCE_FILE_NAME = "persistance.file.name"; private DeploymentPackageInstallOptions options; private final CloudDeploymentHandlerV2 callback; private DeploymentAdmin deploymentAdmin; private Properties m_installPersistance; private String dpaConfPath; private final String m_installVerifDir; private final String m_installPersistanceDir; private String packagesPath; public InstallImpl(CloudDeploymentHandlerV2 callback, String kuraDataDir) { this.callback = callback; StringBuilder pathSB = new StringBuilder(); pathSB.append(kuraDataDir); pathSB.append(File.separator); pathSB.append(PERSISTANCE_FOLDER_NAME); this.m_installPersistanceDir = pathSB.toString(); File installPersistanceDir = new File(this.m_installPersistanceDir); if (!installPersistanceDir.exists()) { installPersistanceDir.mkdir(); } pathSB = new StringBuilder(); pathSB.append(this.m_installPersistanceDir); pathSB.append(File.separator); pathSB.append(PERSISTANCE_VERIFICATION_FOLDER_NAME); this.m_installVerifDir = pathSB.toString(); File installVerificationDir = new File(this.m_installVerifDir); if (!installVerificationDir.exists()) { installVerificationDir.mkdir(); } } public Properties getDeployedPackages() { FileInputStream fis = null; Properties deployedPackages = new Properties(); try { fis = new FileInputStream(this.dpaConfPath); deployedPackages.load(fis); } catch (IOException e) { s_logger.error("Error opening package configuration file", e); } finally { try { if (fis != null) { fis.close(); } } catch (IOException e) { s_logger.error("Exception while closing opened resources!", e); } } return deployedPackages; } public void setOptions(DeploymentPackageInstallOptions options) { this.options = options; } public void setPackagesPath(String packagesPath) { this.packagesPath = packagesPath; } public void setDeploymentAdmin(DeploymentAdmin deploymentAdmin) { this.deploymentAdmin = deploymentAdmin; } public void setDpaConfPath(String dpaConfPath) { this.dpaConfPath = dpaConfPath; } public void installDp(DeploymentPackageInstallOptions options, File dpFile) throws KuraException { SafeProcess proc = null; try { installDeploymentPackageInternal(dpFile); installCompleteAsync(options, dpFile.getName()); s_logger.info("Install completed!"); if (options.isReboot()) { Thread.sleep(options.getRebootDelay()); proc = ProcessUtil.exec("reboot"); } } catch (Exception e) { s_logger.info("Install failed!"); installFailedAsync(options, dpFile.getName(), e); } finally { if (proc != null) { ProcessUtil.destroy(proc); } } } public void installSh(DeploymentPackageOptions options, File shFile) throws KuraException { updateInstallPersistance(shFile.getName(), options); // Script Exec SafeProcess proc = null; try { proc = ProcessUtil.exec("chmod 700 " + shFile.getCanonicalPath()); } catch (IOException e) { throw new KuraException(KuraErrorCode.INTERNAL_ERROR); } finally { if (proc != null) { ProcessUtil.destroy(proc); } } SafeProcess proc2 = null; try { proc2 = ProcessUtil.exec(shFile.getCanonicalPath()); } catch (IOException e) { throw new KuraException(KuraErrorCode.INTERNAL_ERROR); } finally { if (proc2 != null) { ProcessUtil.destroy(proc2); } } } public void installInProgressSyncMessage(KuraResponsePayload respPayload) { respPayload.setTimestamp(new Date()); respPayload.addMetric(KuraInstallPayload.METRIC_INSTALL_STATUS, INSTALL_STATUS.IN_PROGRESS); respPayload.addMetric(KuraInstallPayload.METRIC_DP_NAME, this.options.getDpName()); respPayload.addMetric(KuraInstallPayload.METRIC_DP_VERSION, this.options.getDpVersion()); } public void installIdleSyncMessage(KuraResponsePayload respPayload) { respPayload.setTimestamp(new Date()); respPayload.addMetric(KuraInstallPayload.METRIC_INSTALL_STATUS, INSTALL_STATUS.IDLE); } public void installCompleteAsync(DeploymentPackageOptions options, String dpName) throws KuraException { KuraInstallPayload notify = new KuraInstallPayload(options.getClientId()); notify.setTimestamp(new Date()); notify.setInstallStatus(INSTALL_STATUS.COMPLETED.getStatusString()); notify.setJobId(options.getJobId()); notify.setDpName(dpName); // Probably split dpName and dpVersion? notify.setInstallProgress(PROGRESS_COMPLETE); this.callback.publishMessage(options, notify, RESOURCE_INSTALL); } public void installFailedAsync(DeploymentPackageInstallOptions options, String dpName, Exception e) throws KuraException { KuraInstallPayload notify = new KuraInstallPayload(options.getClientId()); notify.setTimestamp(new Date()); notify.setInstallStatus(INSTALL_STATUS.FAILED.getStatusString()); notify.setJobId(options.getJobId()); notify.setDpName(dpName); // Probably split dpName and dpVersion? notify.setInstallProgress(0); if (e != null) { notify.setErrorMessage(e.getMessage()); } this.callback.publishMessage(options, notify, RESOURCE_INSTALL); } public void sendInstallConfirmations() { s_logger.info("Ready to send Confirmations"); File verificationDir = new File(this.m_installVerifDir); if (verificationDir.listFiles() != null) { for (File fileEntry : verificationDir.listFiles()) { if (fileEntry.isFile() && fileEntry.getName().endsWith(".sh")) { SafeProcess proc = null; try { proc = ProcessUtil.exec("chmod 700 " + fileEntry.getCanonicalPath()); } catch (IOException e) { } finally { if (proc != null) { ProcessUtil.destroy(proc); } } SafeProcess proc2 = null; try { proc2 = ProcessUtil.exec(fileEntry.getCanonicalPath()); int exitValue = proc2.exitValue(); if (exitValue == 0) { sendSysUpdateSuccess(); } else { sendSysUpdateFailure(); } } catch (Exception e) { } finally { fileEntry.delete(); if (proc2 != null) { ProcessUtil.destroy(proc2); } } } } } } private DeploymentPackage installDeploymentPackageInternal(File fileReference) throws DeploymentException, IOException { InputStream dpInputStream = null; DeploymentPackage dp = null; File dpPersistentFile = null; File downloadedFile = fileReference; try { String dpBasename = fileReference.getName(); StringBuilder pathSB = new StringBuilder(); pathSB.append(this.packagesPath); pathSB.append(File.separator); pathSB.append(dpBasename); String dpPersistentFilePath = pathSB.toString(); dpPersistentFile = new File(dpPersistentFilePath); dpInputStream = new FileInputStream(downloadedFile); dp = this.deploymentAdmin.installDeploymentPackage(dpInputStream); // Now we need to copy the deployment package file to the Kura // packages directory unless it's already there. if (!downloadedFile.getCanonicalPath().equals(dpPersistentFile.getCanonicalPath())) { s_logger.debug("dpFile.getCanonicalPath(): {}", downloadedFile.getCanonicalPath()); s_logger.debug("dpPersistentFile.getCanonicalPath(): {}", dpPersistentFile.getCanonicalPath()); FileUtils.copyFile(downloadedFile, dpPersistentFile); addPackageToConfFile(dp.getName(), "file:" + dpPersistentFilePath); } } catch (FileNotFoundException ex) { } catch (IOException ex) { } finally { if (dpInputStream != null) { try { dpInputStream.close(); } catch (IOException e) { s_logger.warn("Cannot close input stream", e); } } // The file from which we have installed the deployment package will be deleted // unless it's a persistent deployment package file. if (downloadedFile != null && dpPersistentFile != null && !downloadedFile.getCanonicalPath().equals(dpPersistentFile.getCanonicalPath())) { downloadedFile.delete(); } } return dp; } private void updateInstallPersistance(String fileName, DeploymentPackageOptions options) { this.m_installPersistance = new Properties(); this.m_installPersistance.setProperty(DeploymentPackageOptions.METRIC_DP_CLIENT_ID, options.getClientId()); this.m_installPersistance.setProperty(DeploymentPackageOptions.METRIC_JOB_ID, Long.toString(options.getJobId())); this.m_installPersistance.setProperty(DeploymentPackageOptions.METRIC_DP_NAME, fileName); this.m_installPersistance.setProperty(DeploymentPackageOptions.METRIC_DP_VERSION, options.getDpVersion()); this.m_installPersistance.setProperty(CloudDeploymentHandlerV2.METRIC_REQUESTER_CLIENT_ID, options.getRequestClientId()); this.m_installPersistance.setProperty(PERSISTANCE_FILE_NAME, fileName); if (this.m_installPersistanceDir == null) { s_logger.warn(MESSAGE_CONFIGURATION_FILE_NOT_SPECIFIED); return; } FileOutputStream fos = null; try { StringBuilder pathSB = new StringBuilder(); pathSB.append(this.m_installPersistanceDir); pathSB.append(File.separator); pathSB.append(fileName); pathSB.append(PERSISTANCE_SUFFIX); String persistanceFile = pathSB.toString(); fos = new FileOutputStream(persistanceFile); this.m_installPersistance.store(fos, null); fos.flush(); fos.getFD().sync(); } catch (IOException e) { s_logger.error("Error writing remote install configuration file", e); } finally { if (fos != null) { try { fos.close(); } catch (IOException e) { s_logger.error("Exception while closing the stream!", e); } } } } private void addPackageToConfFile(String packageName, String packageUrl) { Properties deployedPackages = getDeployedPackages(); deployedPackages.setProperty(packageName, packageUrl); if (this.dpaConfPath == null) { s_logger.warn(MESSAGE_CONFIGURATION_FILE_NOT_SPECIFIED); return; } FileOutputStream fos = null; try { fos = new FileOutputStream(this.dpaConfPath); deployedPackages.store(fos, null); fos.flush(); fos.getFD().sync(); } catch (IOException e) { s_logger.error("Error writing package configuration file", e); } finally { try { if (fos != null) { fos.close(); } } catch (IOException e) { s_logger.error("Exception while closing opened resources!", e); } } } public void removePackageFromConfFile(String packageName) { Properties deployedPackages = getDeployedPackages(); deployedPackages.remove(packageName); if (this.dpaConfPath == null) { s_logger.warn(MESSAGE_CONFIGURATION_FILE_NOT_SPECIFIED); return; } FileOutputStream fos = null; try { fos = new FileOutputStream(this.dpaConfPath); deployedPackages.store(fos, null); fos.flush(); fos.getFD().sync(); } catch (IOException e) { s_logger.error("Error writing package configuration file", e); } finally { try { if (fos != null) { fos.close(); } } catch (IOException e) { s_logger.error("Exception while closing opened resources!", e); } } } private void sendSysUpdateSuccess() throws KuraException { s_logger.info("Ready to send success after install"); File installDir = new File(this.m_installPersistanceDir); if (installDir != null) { for (File fileEntry : installDir.listFiles()) { if (fileEntry.isFile() && fileEntry.getName().endsWith(PERSISTANCE_SUFFIX)) { // && // fileEntry.getName().contains(verificationFile.getName() Properties downloadProperties = loadInstallPersistance(fileEntry); String deployUrl = downloadProperties .getProperty(DeploymentPackageDownloadOptions.METRIC_DP_DOWNLOAD_URI); String dpName = downloadProperties.getProperty(DeploymentPackageOptions.METRIC_DP_NAME); String dpVersion = downloadProperties.getProperty(DeploymentPackageOptions.METRIC_DP_VERSION); String clientId = downloadProperties.getProperty(DeploymentPackageOptions.METRIC_DP_CLIENT_ID); Long jobId = Long .valueOf(downloadProperties.getProperty(DeploymentPackageOptions.METRIC_JOB_ID)); String fileSystemFileName = downloadProperties.getProperty(PERSISTANCE_FILE_NAME); String requestClientId = downloadProperties .getProperty(CloudDeploymentHandlerV2.METRIC_REQUESTER_CLIENT_ID); DeploymentPackageDownloadOptions deployOptions = new DeploymentPackageDownloadOptions(deployUrl, dpName, dpVersion); deployOptions.setClientId(clientId); deployOptions.setJobId(jobId); deployOptions.setRequestClientId(requestClientId); try { installCompleteAsync(deployOptions, fileSystemFileName); s_logger.info("Sent install complete"); fileEntry.delete(); break; } catch (KuraException e) { throw new KuraException(KuraErrorCode.INTERNAL_ERROR); } } } } } private void sendSysUpdateFailure() throws KuraException { File installDir = new File(this.m_installPersistanceDir); if (installDir != null) { for (final File fileEntry : installDir.listFiles()) { if (fileEntry.isFile() && fileEntry.getName().endsWith(PERSISTANCE_SUFFIX)) { // && // fileEntry.getName().contains(verificationFile.getName()) Properties downloadProperties = loadInstallPersistance(fileEntry); String deployUrl = downloadProperties .getProperty(DeploymentPackageDownloadOptions.METRIC_DP_DOWNLOAD_URI); String dpName = downloadProperties.getProperty(DeploymentPackageOptions.METRIC_DP_NAME); String dpVersion = downloadProperties.getProperty(DeploymentPackageOptions.METRIC_DP_VERSION); String clientId = downloadProperties.getProperty(DeploymentPackageOptions.METRIC_DP_CLIENT_ID); Long jobId = Long .valueOf(downloadProperties.getProperty(DeploymentPackageOptions.METRIC_JOB_ID)); String fileSystemFileName = downloadProperties.getProperty(PERSISTANCE_FILE_NAME); String requestClientId = downloadProperties .getProperty(CloudDeploymentHandlerV2.METRIC_REQUESTER_CLIENT_ID); DeploymentPackageDownloadOptions deployOptions = new DeploymentPackageDownloadOptions(deployUrl, dpName, dpVersion); deployOptions.setClientId(clientId); deployOptions.setJobId(jobId); deployOptions.setRequestClientId(requestClientId); try { installFailedAsync(deployOptions, fileSystemFileName, new KuraException(KuraErrorCode.INTERNAL_ERROR)); s_logger.info("Sent install failed"); fileEntry.delete(); break; } catch (KuraException e) { throw new KuraException(KuraErrorCode.INTERNAL_ERROR); } } } } } private Properties loadInstallPersistance(File installedDpPersistance) { Properties downloadProperies = new Properties(); FileReader fr = null; try { fr = new FileReader(installedDpPersistance); downloadProperies.load(fr); } catch (IOException e) { s_logger.error("Exception loading install configuration file", e); } finally { try { if (fr != null) { fr.close(); } } catch (IOException e) { s_logger.error("Exception while closing opened resources!", e); } } return downloadProperies; } }